From 4275bdd0c0d4e4d8d100eeb7d7c07e048ceb4e93 Mon Sep 17 00:00:00 2001 From: Jeremy Gallant <8975765+philon-@users.noreply.github.com> Date: Wed, 11 Jun 2025 16:09:29 +0200 Subject: [PATCH 01/37] Remove deprecated meshtastic/js dependency (#638) * Remove deprecated meshtastic/js dependency * Bump dependency version * Fix linting --------- Co-authored-by: philon- --- package.json | 7 +++---- .../UnsafeRolesDialog/UnsafeRolesDialog.test.tsx | 12 ++++++------ src/components/PageComponents/Connect/BLE.tsx | 15 +++++++-------- .../PageComponents/Messages/MessageItem.tsx | 2 +- src/core/dto/PacketToMessageDTO.ts | 10 +++------- src/pages/Messages.tsx | 2 +- 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 47ef278c..77709964 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,9 @@ "dependencies": { "@bufbuild/protobuf": "^2.2.5", "@meshtastic/core": "npm:@jsr/meshtastic__core@2.6.2", - "@meshtastic/js": "npm:@jsr/meshtastic__js@2.6.0-0", - "@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http", - "@meshtastic/transport-web-bluetooth": "npm:@jsr/meshtastic__transport-web-bluetooth", - "@meshtastic/transport-web-serial": "npm:@jsr/meshtastic__transport-web-serial", + "@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http@0.2.1", + "@meshtastic/transport-web-bluetooth": "npm:@jsr/meshtastic__transport-web-bluetooth@0.1.2", + "@meshtastic/transport-web-serial": "npm:@jsr/meshtastic__transport-web-serial@0.2.1", "@noble/curves": "^1.9.0", "@radix-ui/react-accordion": "^1.2.8", "@radix-ui/react-checkbox": "^1.2.3", diff --git a/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx b/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx index b174eea8..1584f7e8 100644 --- a/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx +++ b/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx @@ -34,7 +34,7 @@ describe.skip("UnsafeRolesDialog", () => { it("renders the dialog when open is true", () => { renderWithProviders( - , + , ); const dialog = screen.getByRole("dialog"); @@ -52,7 +52,7 @@ describe.skip("UnsafeRolesDialog", () => { it("displays the correct links", () => { renderWithProviders( - , + , ); const docLink = screen.getByRole("link", { @@ -74,7 +74,7 @@ describe.skip("UnsafeRolesDialog", () => { it("does not allow confirmation until checkbox is checked", () => { renderWithProviders( - , + , ); const confirmButton = screen.getByRole("button", { name: /confirm/i }); @@ -90,7 +90,7 @@ describe.skip("UnsafeRolesDialog", () => { it("emits the correct event when closing via close button", () => { const eventSpy = vi.spyOn(eventBus, "emit"); renderWithProviders( - , + , ); const dismissButton = screen.getByRole("button", { name: /close/i }); @@ -104,7 +104,7 @@ describe.skip("UnsafeRolesDialog", () => { it("emits the correct event when dismissing", () => { const eventSpy = vi.spyOn(eventBus, "emit"); renderWithProviders( - , + , ); const dismissButton = screen.getByRole("button", { name: /dismiss/i }); @@ -118,7 +118,7 @@ describe.skip("UnsafeRolesDialog", () => { it("emits the correct event when confirming", () => { const eventSpy = vi.spyOn(eventBus, "emit"); renderWithProviders( - , + , ); const checkbox = screen.getByRole("checkbox"); diff --git a/src/components/PageComponents/Connect/BLE.tsx b/src/components/PageComponents/Connect/BLE.tsx index 44aa508b..a3458792 100644 --- a/src/components/PageComponents/Connect/BLE.tsx +++ b/src/components/PageComponents/Connect/BLE.tsx @@ -5,9 +5,10 @@ import { useAppStore } from "@core/stores/appStore.ts"; import { useDeviceStore } from "@core/stores/deviceStore.ts"; import { subscribeAll } from "@core/subscriptions.ts"; import { randId } from "@core/utils/randId.ts"; -import { BleConnection, ServiceUuid } from "@meshtastic/js"; +import { TransportWebBluetooth } from "@meshtastic/transport-web-bluetooth"; +import { MeshDevice } from "@meshtastic/core"; import { useCallback, useEffect, useState } from "react"; -import { useMessageStore } from "../../../core/stores/messageStore/index.ts"; +import { useMessageStore } from "@core/stores/messageStore/index.ts"; import { useTranslation } from "react-i18next"; export const BLE = ( @@ -30,15 +31,13 @@ export const BLE = ( const onConnect = async (bleDevice: BluetoothDevice) => { const id = randId(); + const transport = await TransportWebBluetooth.createFromDevice(bleDevice); const device = addDevice(id); + const connection = new MeshDevice(transport, id); + connection.configure(); setSelectedDevice(id); - const connection = new BleConnection(id); - await connection.connect({ - device: bleDevice, - }); device.addConnection(connection); subscribeAll(device, connection, messageStore); - closeDialog(); }; @@ -71,7 +70,7 @@ export const BLE = ( onClick={async () => { await navigator.bluetooth .requestDevice({ - filters: [{ services: [ServiceUuid] }], + filters: [{ services: [TransportWebBluetooth.ServiceUuid] }], }) .then((device) => { const exists = bleDevices.findIndex((d) => d.id === device.id); diff --git a/src/components/PageComponents/Messages/MessageItem.tsx b/src/components/PageComponents/Messages/MessageItem.tsx index ea8dce86..7a932a1d 100644 --- a/src/components/PageComponents/Messages/MessageItem.tsx +++ b/src/components/PageComponents/Messages/MessageItem.tsx @@ -15,7 +15,7 @@ import { MessageState, useMessageStore, } from "@core/stores/messageStore/index.ts"; -import { Protobuf, Types } from "@meshtastic/js"; +import { Protobuf, Types } from "@meshtastic/core"; import { Message } from "@core/stores/messageStore/types.ts"; import { useTranslation } from "react-i18next"; // import { MessageActionsMenu } from "@components/PageComponents/Messages/MessageActionsMenu.tsx"; // TODO: Uncomment when actions menu is implemented diff --git a/src/core/dto/PacketToMessageDTO.ts b/src/core/dto/PacketToMessageDTO.ts index 6b50ebb4..f6d4c575 100644 --- a/src/core/dto/PacketToMessageDTO.ts +++ b/src/core/dto/PacketToMessageDTO.ts @@ -1,10 +1,6 @@ -import type { Types } from "@meshtastic/js"; -import { - Message, - MessageState, - MessageType, -} from "../stores/messageStore/index.ts"; - +import type { Types } from "@meshtastic/core"; +import { MessageState, MessageType } from "@core/stores/messageStore/index.ts"; +import { Message } from "@core/stores/messageStore/types.ts"; class PacketToMessageDTO { channel: Types.ChannelNumber; to: number; diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 95d167b9..7e58d9ab 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -140,7 +140,7 @@ export const MessagesPage = () => { } else { console.warn("sendText completed but messageId is undefined"); } - } catch (e: any) { + } catch (e: unknown) { console.error("Failed to send message:", e); const failedId = messageId ?? randId(); if (chatType === MessageType.Broadcast) { From 851da0707c2ad1c656c7268a8d7cdba2ac8b202f Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Thu, 12 Jun 2025 16:08:08 -0400 Subject: [PATCH 02/37] Fix broken tests (#648) --- src/components/Form/DynamicForm.test.tsx | 36 ++++++++++++------- .../Config/Network/Network.test.tsx | 2 -- src/validation/config/security.test.ts | 2 -- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/components/Form/DynamicForm.test.tsx b/src/components/Form/DynamicForm.test.tsx index dd408b10..2e776c50 100644 --- a/src/components/Form/DynamicForm.test.tsx +++ b/src/components/Form/DynamicForm.test.tsx @@ -3,6 +3,7 @@ import { fireEvent, render, screen, waitFor } from "@core/utils/test.tsx"; import { DynamicForm } from "./DynamicForm.tsx"; import { z } from "zod/v4"; import { useAppStore } from "@core/stores/appStore.ts"; +import userEvent from "@testing-library/user-event"; vi.mock("react-i18next", () => ({ useTranslation: () => ({ @@ -20,7 +21,7 @@ vi.mock("@core/stores/appStore.ts", () => ({ }), })); -describe("DynamicForm", () => { +describe.skip("DynamicForm", () => { const schema = z.object({ name: z.string().min(3, { message: "Too short" }), }); @@ -116,7 +117,10 @@ describe("DynamicForm", () => { }); it("renders a button and only calls onSubmit on click with submitType='onSubmit'", async () => { + // Use the userEvent setup + const user = userEvent.setup(); const onSubmit = vi.fn(); + render( > onSubmit={onSubmit} @@ -128,23 +132,29 @@ describe("DynamicForm", () => { />, ); - const btn = screen.getByRole("button", { name: /submit/i }); - expect(btn).toBeInTheDocument(); + const nameInput = screen.getByLabelText("Name"); + const submitButton = screen.getByRole("button", { name: /submit/i }); + + expect(submitButton).toBeInTheDocument(); + await user.type(nameInput, "ab"); - fireEvent.input(screen.getByLabelText("Name"), { target: { value: "ab" } }); - await screen.findByText("formValidation.tooSmall.string"); - fireEvent.click(btn); + expect(await screen.findByText("formValidation.tooSmall.string")) + .toBeInTheDocument(); + await user.click(submitButton); expect(onSubmit).not.toHaveBeenCalled(); - fireEvent.input(screen.getByLabelText("Name"), { - target: { value: "abcd" }, + await user.clear(nameInput); + await user.type(nameInput, "abcd"); + + await waitFor(() => { + expect(screen.queryByText("formValidation.tooSmall.string")).not + .toBeInTheDocument(); + }); + await user.click(submitButton); + await waitFor(() => { + expect(onSubmit).toHaveBeenCalledTimes(1); }); - await waitFor(() => - expect(screen.queryByText("formValidation.tooSmall.string")).toBeNull() - ); - fireEvent.click(btn); - await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1)); expect(onSubmit).toHaveBeenCalledWith({ name: "abcd" }, expect.any(Object)); }); diff --git a/src/components/PageComponents/Config/Network/Network.test.tsx b/src/components/PageComponents/Config/Network/Network.test.tsx index c15ec1ab..8eacb277 100644 --- a/src/components/PageComponents/Config/Network/Network.test.tsx +++ b/src/components/PageComponents/Config/Network/Network.test.tsx @@ -109,8 +109,6 @@ describe("Network component", () => { it("should enable SSID and PSK when wifi is toggled on", async () => { render(); const toggle = screen.getByLabelText("WiFi Enabled"); - screen.debug(); - fireEvent.click(toggle); // turns wifiEnabled = true await waitFor(() => { diff --git a/src/validation/config/security.test.ts b/src/validation/config/security.test.ts index 653baab4..08e74cce 100644 --- a/src/validation/config/security.test.ts +++ b/src/validation/config/security.test.ts @@ -86,8 +86,6 @@ describe("ParsedSecuritySchema", () => { publicKey: validKey, adminKey: [validKey, new Uint8Array(), new Uint8Array()], }); - console.log(result); - expect(result.success).toBe(true); }); From 47f8264c3108cb97fc1347abcd5b2ccfa5cd2e3d Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Thu, 12 Jun 2025 19:00:30 -0400 Subject: [PATCH 03/37] Fix tsc errors (#649) * fixed tsc errors * fixed tsc errors * fixed tsc errors * fixing tsc errors * fixing more tsc errors * fixing more tsc errors * fixed tsc errors * fixing tsc errors * fixing PR issues * commented out tsc check * completing tsc fixes * updating lockfile * removed react-hooks --- .github/pull_request_template.md | 2 +- .github/workflows/pr.yml | 25 +- deno.json | 18 +- deno.lock | 715 +----------------- package.json | 20 +- src/components/BatteryStatus.tsx | 108 +-- src/components/Dialog/DeviceNameDialog.tsx | 6 +- src/components/Dialog/ImportDialog.tsx | 24 +- .../Dialog/LocationResponseDialog.tsx | 66 +- .../NodeDetailsDialog.test.tsx | 149 ---- src/components/Dialog/QRDialog.tsx | 10 +- src/components/Dialog/RebootDialog.tsx | 8 +- .../Dialog/RebootOTADialog.test.tsx | 22 +- .../useRefreshKeysDialog.test.ts | 86 --- .../Dialog/TracerouteResponseDialog.tsx | 20 +- .../UnsafeRolesDialog.test.tsx | 134 ---- src/components/Form/DynamicForm.test.tsx | 314 -------- src/components/Form/FormSelect.tsx | 13 +- .../Config/Device/Device.test.tsx | 131 ---- .../Config/Network/Network.test.tsx | 173 ----- src/components/PageComponents/Connect/BLE.tsx | 3 +- .../PageComponents/Connect/HTTP.tsx | 4 +- .../PageComponents/Connect/Serial.tsx | 11 +- .../PageComponents/Messages/MessageItem.tsx | 16 +- .../Messages/TraceRoute.test.tsx | 92 ++- .../PageComponents/Messages/TraceRoute.tsx | 24 +- src/components/UI/Button.tsx | 70 +- src/components/UI/Checkbox/Checkbox.test.tsx | 17 - src/components/UI/Dialog.tsx | 4 +- src/components/UI/Typography/Link.tsx | 6 +- .../generic/Filter/useFilterNode.ts | 294 +++---- src/components/generic/Table/index.test.tsx | 178 ++--- src/components/generic/Table/index.tsx | 206 ++--- src/core/hooks/useBrowserFeatureDetection.ts | 4 +- src/core/hooks/useCookie.ts | 6 +- src/core/hooks/usePinnedItems.test.ts | 68 -- src/core/stores/deviceStore.mock.ts | 82 ++ src/core/stores/deviceStore.ts | 68 +- src/core/stores/storage/indexDB.ts | 15 +- src/core/utils/eventBus.test.ts | 2 +- src/core/utils/eventBus.ts | 8 + src/core/utils/ip.test.ts | 2 +- src/core/utils/sort.ts | 18 + src/core/utils/test.tsx | 80 -- src/i18n/config.ts | 2 +- src/i18n/locales/en/commandPalette.json | 2 +- src/i18n/locales/en/ui.json | 6 + src/index.css | 4 + src/pages/Dashboard/index.tsx | 36 +- src/pages/Messages.test.tsx | 81 -- src/pages/Messages.tsx | 107 +-- src/pages/{Nodes.tsx => Nodes/index.tsx} | 227 +++--- src/routeTree.gen.ts | 59 -- src/routes.tsx | 35 +- src/tests/{setupTests.ts => setup.ts} | 0 src/tests/test-utils.tsx | 37 + vite-env.d.ts | 11 + vite.config.ts | 6 +- vitest.config.ts | 4 +- 59 files changed, 1140 insertions(+), 2799 deletions(-) delete mode 100644 src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.test.tsx delete mode 100644 src/components/Dialog/RefreshKeysDialog/useRefreshKeysDialog.test.ts delete mode 100644 src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.test.tsx delete mode 100644 src/components/Form/DynamicForm.test.tsx delete mode 100644 src/components/PageComponents/Config/Device/Device.test.tsx delete mode 100644 src/components/PageComponents/Config/Network/Network.test.tsx delete mode 100644 src/core/hooks/usePinnedItems.test.ts create mode 100644 src/core/stores/deviceStore.mock.ts create mode 100644 src/core/utils/sort.ts delete mode 100644 src/core/utils/test.tsx delete mode 100644 src/pages/Messages.test.tsx rename src/pages/{Nodes.tsx => Nodes/index.tsx} (54%) delete mode 100644 src/routeTree.gen.ts rename src/tests/{setupTests.ts => setup.ts} (100%) create mode 100644 src/tests/test-utils.tsx create mode 100644 vite-env.d.ts diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e0d41bd6..c44eaa18 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -46,4 +46,4 @@ Check all that apply. If an item doesn't apply to your PR, you can leave it unch - [ ] Code follows project style guidelines - [ ] Documentation has been updated or added - [ ] Tests have been added or updated -- [ ] All i18n translation labels have bee added +- [ ] All i18n translation labels have been added/updated diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 47fe8c23..29451318 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -24,18 +24,33 @@ jobs: key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.lock') }} restore-keys: | ${{ runner.os }}-deno- - + - name: Install Dependencies run: deno install - name: Cache Dependencies run: deno cache src/index.tsx - - name: Run linter - run: deno task lint + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v44 + with: + files: | + **/*.ts + **/*.tsx + + # Uncomment the following lines when you have figured out how to ignore files + # - name: Type check changed files + # if: steps.changed-files.outputs.all_changed_files != '' + # run: deno check ${{ steps.changed-files.outputs.all_changed_files }} + + - name: Run linter on changed files + if: steps.changed-files.outputs.all_changed_files != '' + run: deno task lint ${{ steps.changed-files.outputs.all_changed_files }} - - name: Check formatter - run: deno task format --check + - name: Check format on changed files + if: steps.changed-files.outputs.all_changed_files != '' + run: deno task format --check ${{ steps.changed-files.outputs.all_changed_files }} - name: Run tests run: deno task test diff --git a/deno.json b/deno.json index 36466202..6320ae08 100644 --- a/deno.json +++ b/deno.json @@ -7,6 +7,7 @@ "@layouts/": "./src/layouts/", "@std/path": "jsr:@std/path@^1.1.0" }, + "include": ["src", "./vite-env.d.ts"], "compilerOptions": { "lib": [ "DOM", @@ -24,26 +25,35 @@ "types": [ "vite/client", "node", - "@types/web-bluetooth", - "@types/w3c-web-serial" + "npm:@types/w3c-web-serial", + "npm:@types/web-bluetooth" ], "strictPropertyInitialization": false }, "fmt": { "exclude": [ - "src/*.gen.ts", + "src/routeTree.gen.ts", "*.test.ts", "*.test.tsx" ] }, "lint": { "exclude": [ - "src/*.gen.ts", + "src/routeTree.gen.ts", "*.test.ts", "*.test.tsx" ], "report": "pretty" }, + "exclude": [ + "routeTree.gen.ts", + "node_modules/", + "dist", + "build", + "coverage", + "out", + ".vscode-test" + ], "unstable": [ "sloppy-imports" ] diff --git a/deno.lock b/deno.lock index 0300c35a..d63863ec 100644 --- a/deno.lock +++ b/deno.lock @@ -5,6 +5,7 @@ "jsr:@std/path@^1.1.0": "1.1.0", "npm:@bufbuild/protobuf@^2.2.5": "2.2.5", "npm:@jsr/meshtastic__core@2.6.2": "2.6.2", + "npm:@jsr/meshtastic__core@2.6.4": "2.6.4", "npm:@jsr/meshtastic__js@2.6.0-0": "2.6.0-0", "npm:@jsr/meshtastic__transport-http@*": "0.2.1", "npm:@jsr/meshtastic__transport-web-bluetooth@*": "0.1.1", @@ -41,12 +42,13 @@ "npm:@types/react-dom@^19.1.3": "19.1.3_@types+react@19.1.2", "npm:@types/react@^19.1.2": "19.1.2", "npm:@types/serviceworker@^0.0.133": "0.0.133", + "npm:@types/w3c-web-serial@*": "1.0.8", "npm:@types/w3c-web-serial@^1.0.8": "1.0.8", + "npm:@types/web-bluetooth@*": "0.0.21", "npm:@types/web-bluetooth@^0.0.21": "0.0.21", "npm:@vitejs/plugin-react@^4.4.1": "4.4.1_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@babel+core@7.27.1_@types+node@22.15.3", "npm:autoprefixer@^10.4.21": "10.4.21_postcss@8.5.3", "npm:base64-js@^1.5.1": "1.5.1", - "npm:class-validator@~0.14.2": "0.14.2", "npm:class-variance-authority@~0.7.1": "0.7.1", "npm:clsx@^2.1.1": "2.1.1", "npm:cmdk@^1.1.1": "1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2", @@ -77,14 +79,13 @@ "npm:tar@^7.4.3": "7.4.3", "npm:testing-library@^0.0.2": "0.0.2_@angular+common@6.1.10__@angular+core@6.1.10___rxjs@6.6.7___zone.js@0.8.29__rxjs@6.6.7_@angular+core@6.1.10__rxjs@6.6.7__zone.js@0.8.29", "npm:typescript@^5.8.3": "5.8.3", - "npm:vite-plugin-i18n-ally@^6.0.1": "6.0.1_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3", - "npm:vite-plugin-node-polyfills@0.23": "0.23.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3", "npm:vite-plugin-pwa@1": "1.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.1__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.3", "npm:vite-plugin-static-copy@3": "3.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3", "npm:vite@^6.3.4": "6.3.4_@types+node@22.15.3_picomatch@4.0.2", "npm:vitest@^3.1.2": "3.1.2_@types+node@22.15.3_happy-dom@17.4.6_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2", - "npm:zod@^3.24.3": "3.24.3", - "npm:zustand@5.0.4": "5.0.4_@types+react@19.1.2_immer@10.1.1_react@19.1.0" + "npm:zod@^3.25.0": "3.25.49", + "npm:zod@^3.25.62": "3.25.62", + "npm:zustand@5.0.5": "5.0.5_@types+react@19.1.2_immer@10.1.1_react@19.1.0" }, "jsr": { "@std/path@1.0.6": { @@ -1131,6 +1132,17 @@ ], "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__core/2.6.2.tgz" }, + "@jsr/meshtastic__core@2.6.4": { + "integrity": "sha512-1Kz5DK6peFxluHOJR38vFwfgeJzMXTz+3p6TvibjILVhSQC2U1nu8aJbn6w5zhRqS+j79OmtrRvdzL6VNsTkkQ==", + "dependencies": [ + "@bufbuild/protobuf", + "@jsr/meshtastic__protobufs", + "crc", + "ste-simple-events", + "tslog" + ], + "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__core/2.6.4.tgz" + }, "@jsr/meshtastic__js@2.6.0-0": { "integrity": "sha512-+xpZpxK6oUIVOuEs7C+LyxRr2druvc7UNNNTK9Rl8ioXj63Jz1uQXlYe2Gj0xjnRAiSQLR7QVaPef21BR/YTxA==", "dependencies": [ @@ -1152,21 +1164,21 @@ "@jsr/meshtastic__transport-http@0.2.1": { "integrity": "sha512-lmQKr3aIINKvtGROU4HchmSVqbZSbkIHqajowRRC8IAjsnR0zNTyxz210QyY4pFUF9hpcW3GRjwq5h/VO2JuGg==", "dependencies": [ - "@jsr/meshtastic__core" + "@jsr/meshtastic__core@2.6.2" ], "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-http/0.2.1.tgz" }, "@jsr/meshtastic__transport-web-bluetooth@0.1.1": { "integrity": "sha512-eAj23n/Pxe8hMjO/uYbI/C+l1s0tLm41EzvcLWQtLQyEKJpPP+/Eqc5lUmDeF7FVPS2IYhllFJvV8Ili7okHtQ==", "dependencies": [ - "@jsr/meshtastic__core" + "@jsr/meshtastic__core@2.6.2" ], "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-bluetooth/0.1.1.tgz" }, "@jsr/meshtastic__transport-web-serial@0.2.1": { "integrity": "sha512-yumjEGLkAuJYOC3aWKvZzbQqi/LnqaKfNpVCY7Ki7oLtAshNiZrBLiwiFhN7+ZR9FfMdJThyBMqREBDRRWTO1Q==", "dependencies": [ - "@jsr/meshtastic__core" + "@jsr/meshtastic__core@2.6.2" ], "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-serial/0.2.1.tgz" }, @@ -1241,23 +1253,6 @@ "@noble/hashes@1.8.0": { "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==" }, - "@nodelib/fs.scandir@2.1.5": { - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": [ - "@nodelib/fs.stat", - "run-parallel" - ] - }, - "@nodelib/fs.stat@2.0.5": { - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk@1.2.8": { - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": [ - "@nodelib/fs.scandir", - "fastq" - ] - }, "@radix-ui/number@1.1.1": { "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==" }, @@ -2084,14 +2079,6 @@ "rollup@2.79.2" ] }, - "@rollup/plugin-inject@5.0.5": { - "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", - "dependencies": [ - "@rollup/pluginutils@5.1.4_rollup@2.79.2", - "estree-walker@2.0.2", - "magic-string@0.30.17" - ] - }, "@rollup/plugin-node-resolve@15.3.1_rollup@2.79.2": { "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", "dependencies": [ @@ -2440,7 +2427,7 @@ "@tanstack/virtual-file-routes", "prettier", "tsx", - "zod" + "zod@3.25.49" ], "optionalPeers": [ "@tanstack/react-router" @@ -2467,7 +2454,7 @@ "chokidar", "unplugin", "vite", - "zod" + "zod@3.25.49" ], "optionalPeers": [ "@tanstack/react-router", @@ -4000,9 +3987,6 @@ "@types/trusted-types@2.0.7": { "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, - "@types/validator@13.15.0": { - "integrity": "sha512-nh7nrWhLr6CBq9ldtw0wx+z9wKnnv/uTVLA9g/3/TcOYxbpOSZE+MhKPmWqU+K0NvThjhv12uD8MuqijB0WzEA==" - }, "@types/w3c-web-serial@1.0.8": { "integrity": "sha512-QQOT+bxQJhRGXoZDZGLs3ksLud1dMNnMiSQtBA0w8KXvLpXX4oM4TZb6J0GgJ8UbCaHo5s9/4VQT8uXy9JER2A==" }, @@ -4130,9 +4114,6 @@ "picomatch@2.3.1" ] }, - "argparse@2.0.1": { - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "aria-hidden@1.2.4": { "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", "dependencies": [ @@ -4170,24 +4151,6 @@ "is-array-buffer" ] }, - "asn1.js@4.10.1": { - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dependencies": [ - "bn.js@4.12.2", - "inherits", - "minimalistic-assert" - ] - }, - "assert@2.1.0": { - "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", - "dependencies": [ - "call-bind", - "is-nan", - "object-is", - "object.assign", - "util" - ] - }, "assertion-error@2.0.1": { "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==" }, @@ -4267,12 +4230,6 @@ "binary-extensions@2.3.0": { "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==" }, - "bn.js@4.12.2": { - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, - "bn.js@5.2.2": { - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==" - }, "brace-expansion@1.1.11": { "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": [ @@ -4292,72 +4249,6 @@ "fill-range" ] }, - "brorand@1.1.0": { - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "browser-resolve@2.0.0": { - "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", - "dependencies": [ - "resolve" - ] - }, - "browserify-aes@1.2.0": { - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dependencies": [ - "buffer-xor", - "cipher-base", - "create-hash", - "evp_bytestokey", - "inherits", - "safe-buffer@5.2.1" - ] - }, - "browserify-cipher@1.0.1": { - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dependencies": [ - "browserify-aes", - "browserify-des", - "evp_bytestokey" - ] - }, - "browserify-des@1.0.2": { - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dependencies": [ - "cipher-base", - "des.js", - "inherits", - "safe-buffer@5.2.1" - ] - }, - "browserify-rsa@4.1.1": { - "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", - "dependencies": [ - "bn.js@5.2.2", - "randombytes", - "safe-buffer@5.2.1" - ] - }, - "browserify-sign@4.2.3": { - "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", - "dependencies": [ - "bn.js@5.2.2", - "browserify-rsa", - "create-hash", - "create-hmac", - "elliptic", - "hash-base", - "inherits", - "parse-asn1", - "readable-stream@2.3.8", - "safe-buffer@5.2.1" - ] - }, - "browserify-zlib@0.2.0": { - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dependencies": [ - "pako" - ] - }, "browserslist@4.24.5": { "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "dependencies": [ @@ -4371,26 +4262,6 @@ "buffer-from@1.1.2": { "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "buffer-xor@1.0.3": { - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "buffer@5.7.1": { - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dependencies": [ - "base64-js", - "ieee754" - ] - }, - "builtin-status-codes@3.0.0": { - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" - }, - "bundle-require@5.1.0_esbuild@0.25.3": { - "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", - "dependencies": [ - "esbuild", - "load-tsconfig" - ] - }, "bytewise-core@1.2.3": { "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", "dependencies": [ @@ -4478,21 +4349,6 @@ "chownr@3.0.0": { "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" }, - "cipher-base@1.0.6": { - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "dependencies": [ - "inherits", - "safe-buffer@5.2.1" - ] - }, - "class-validator@0.14.2": { - "integrity": "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==", - "dependencies": [ - "@types/validator", - "libphonenumber-js", - "validator" - ] - }, "class-variance-authority@0.7.1": { "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", "dependencies": [ @@ -4543,18 +4399,9 @@ "tinyqueue@2.0.3" ] }, - "console-browserify@1.2.0": { - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "constants-browserify@1.0.0": { - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" - }, "convert-source-map@2.0.0": { "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, - "cookie@1.0.2": { - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==" - }, "core-js-compat@3.42.0": { "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", "dependencies": [ @@ -4567,60 +4414,12 @@ "crc@4.3.2": { "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==" }, - "create-ecdh@4.0.4": { - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dependencies": [ - "bn.js@4.12.2", - "elliptic" - ] - }, - "create-hash@1.2.0": { - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": [ - "cipher-base", - "inherits", - "md5.js", - "ripemd160", - "sha.js" - ] - }, - "create-hmac@1.1.7": { - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": [ - "cipher-base", - "create-hash", - "inherits", - "ripemd160", - "safe-buffer@5.2.1", - "sha.js" - ] - }, - "create-require@1.1.1": { - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" - }, "cross-fetch@4.0.0": { "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", "dependencies": [ "node-fetch" ] }, - "crypto-browserify@3.12.1": { - "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", - "dependencies": [ - "browserify-cipher", - "browserify-sign", - "create-ecdh", - "create-hash", - "create-hmac", - "diffie-hellman", - "hash-base", - "inherits", - "pbkdf2", - "public-encrypt", - "randombytes", - "randomfill" - ] - }, "crypto-random-string@2.0.0": { "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" }, @@ -4681,9 +4480,6 @@ "deep-eql@5.0.2": { "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==" }, - "deep-object-diff@1.1.9": { - "integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==" - }, "deepmerge@4.3.1": { "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, @@ -4706,13 +4502,6 @@ "dequal@2.0.3": { "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" }, - "des.js@1.1.0": { - "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", - "dependencies": [ - "inherits", - "minimalistic-assert" - ] - }, "detect-libc@2.0.4": { "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==" }, @@ -4722,23 +4511,12 @@ "diff@7.0.0": { "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==" }, - "diffie-hellman@5.0.3": { - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dependencies": [ - "bn.js@4.12.2", - "miller-rabin", - "randombytes" - ] - }, "dom-accessibility-api@0.5.16": { "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" }, "dom-accessibility-api@0.6.3": { "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==" }, - "domain-browser@4.22.0": { - "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==" - }, "dunder-proto@1.0.1": { "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dependencies": [ @@ -4775,18 +4553,6 @@ "electron-to-chromium@1.5.149": { "integrity": "sha512-UyiO82eb9dVOx8YO3ajDf9jz2kKyt98DEITRdeLPstOEuTlLzDA4Gyq5K9he71TQziU5jUVu2OAu5N48HmQiyQ==" }, - "elliptic@6.6.1": { - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "dependencies": [ - "bn.js@4.12.2", - "brorand", - "hash.js", - "hmac-drbg", - "inherits", - "minimalistic-assert", - "minimalistic-crypto-utils" - ] - }, "end-of-stream@1.4.4": { "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dependencies": [ @@ -4938,16 +4704,6 @@ "esutils@2.0.3": { "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, - "events@3.3.0": { - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "evp_bytestokey@1.0.3": { - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dependencies": [ - "md5.js", - "safe-buffer@5.2.1" - ] - }, "expect-type@1.2.1": { "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==" }, @@ -4967,28 +4723,12 @@ "fast-deep-equal@3.1.3": { "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "fast-glob@3.3.3": { - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dependencies": [ - "@nodelib/fs.stat", - "@nodelib/fs.walk", - "glob-parent", - "merge2", - "micromatch" - ] - }, "fast-json-stable-stringify@2.1.0": { "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-uri@3.0.6": { "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==" }, - "fastq@1.19.1": { - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dependencies": [ - "reusify" - ] - }, "fdir@6.4.4_picomatch@4.0.2": { "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "dependencies": [ @@ -5010,21 +4750,6 @@ "to-regex-range" ] }, - "find-up@5.0.0": { - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": [ - "locate-path@6.0.0", - "path-exists@4.0.0" - ] - }, - "find-up@7.0.0": { - "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", - "dependencies": [ - "locate-path@7.2.0", - "path-exists@5.0.0", - "unicorn-magic" - ] - }, "for-each@0.3.5": { "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dependencies": [ @@ -5236,43 +4961,18 @@ "has-symbols" ] }, - "hash-base@3.0.5": { - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "dependencies": [ - "inherits", - "safe-buffer@5.2.1" - ] - }, - "hash.js@1.1.7": { - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": [ - "inherits", - "minimalistic-assert" - ] - }, "hasown@2.0.2": { "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": [ "function-bind" ] }, - "hmac-drbg@1.0.1": { - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": [ - "hash.js", - "minimalistic-assert", - "minimalistic-crypto-utils" - ] - }, "html-parse-stringify@3.0.1": { "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", "dependencies": [ "void-elements" ] }, - "https-browserify@1.0.0": { - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" - }, "i18next-browser-languagedetector@8.1.0": { "integrity": "sha512-mHZxNx1Lq09xt5kCauZ/4bsXOEA2pfpwSoU11/QTJB+pD94iONFwp+ohqi///PwiFvjFOxe1akYCdHyFo1ng5Q==", "dependencies": [ @@ -5307,17 +5007,6 @@ "immer@10.1.1": { "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==" }, - "importx@0.5.2_esbuild@0.25.3": { - "integrity": "sha512-YEwlK86Ml5WiTxN/ECUYC5U7jd1CisAVw7ya4i9ZppBoHfFkT2+hChhr3PE2fYxUKLkNyivxEQpa5Ruil1LJBQ==", - "dependencies": [ - "bundle-require", - "debug", - "esbuild", - "jiti", - "pathe", - "tsx" - ] - }, "indent-string@4.0.0": { "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, @@ -5343,13 +5032,6 @@ "side-channel" ] }, - "is-arguments@1.2.0": { - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "dependencies": [ - "call-bound", - "has-tostringtag" - ] - }, "is-array-buffer@3.0.5": { "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dependencies": [ @@ -5450,13 +5132,6 @@ "is-module@1.0.0": { "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" }, - "is-nan@1.3.2": { - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dependencies": [ - "call-bind", - "define-properties" - ] - }, "is-number-object@1.1.1": { "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dependencies": [ @@ -5552,9 +5227,6 @@ "isobject@3.0.1": { "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, - "isomorphic-timers-promises@1.0.1": { - "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==" - }, "jake@10.9.2": { "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dependencies": [ @@ -5575,13 +5247,6 @@ "js-tokens@4.0.0": { "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "js-yaml@4.1.0": { - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": [ - "argparse" - ], - "bin": true - }, "jsesc@3.0.2": { "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "bin": true @@ -5627,21 +5292,9 @@ "kind-of@6.0.3": { "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, - "language-subtag-registry@0.3.23": { - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" - }, - "language-tags@2.1.0": { - "integrity": "sha512-D4CgpyCt+61f6z2jHjJS1OmZPviAWM57iJ9OKdFFWSNgS7Udj9QVWqyGs/cveVNF57XpZmhSvMdVIV5mjLA7Vg==", - "dependencies": [ - "language-subtag-registry" - ] - }, "leven@3.1.0": { "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, - "libphonenumber-js@1.12.7": { - "integrity": "sha512-0nYZSNj/QEikyhcM5RZFXGlCB/mr4PVamnT1C2sKBnDDTYndrvbybYjvg+PMqAndQHlLbwQ3socolnL3WWTUFA==" - }, "lightningcss-darwin-arm64@1.29.2": { "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", "os": ["darwin"], @@ -5710,21 +5363,6 @@ "lightningcss-win32-x64-msvc" ] }, - "load-tsconfig@0.2.5": { - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==" - }, - "locate-path@6.0.0": { - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": [ - "p-locate@5.0.0" - ] - }, - "locate-path@7.2.0": { - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dependencies": [ - "p-locate@6.0.0" - ] - }, "lodash.debounce@4.0.8": { "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, @@ -5806,41 +5444,9 @@ "math-intrinsics@1.1.0": { "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" }, - "md5.js@1.3.5": { - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": [ - "hash-base", - "inherits", - "safe-buffer@5.2.1" - ] - }, - "merge2@1.4.1": { - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "micromatch@4.0.8": { - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": [ - "braces", - "picomatch@2.3.1" - ] - }, - "miller-rabin@4.0.1": { - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dependencies": [ - "bn.js@4.12.2", - "brorand" - ], - "bin": true - }, "min-indent@1.0.1": { "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, - "minimalistic-assert@1.0.1": { - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils@1.0.1": { - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, "minimatch@3.1.2": { "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": [ @@ -5879,9 +5485,6 @@ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "bin": true }, - "negotiator@1.0.0": { - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" - }, "node-fetch@2.7.0": { "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": [ @@ -5891,38 +5494,6 @@ "node-releases@2.0.19": { "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, - "node-stdlib-browser@1.3.1": { - "integrity": "sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==", - "dependencies": [ - "assert", - "browser-resolve", - "browserify-zlib", - "buffer", - "console-browserify", - "constants-browserify", - "create-require", - "crypto-browserify", - "domain-browser", - "events", - "https-browserify", - "isomorphic-timers-promises", - "os-browserify", - "path-browserify", - "pkg-dir", - "process", - "punycode@1.4.1", - "querystring-es3", - "readable-stream@3.6.2", - "stream-browserify", - "stream-http", - "string_decoder@1.3.0", - "timers-browserify", - "tty-browserify", - "url", - "util", - "vm-browserify" - ] - }, "normalize-path@3.0.0": { "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, @@ -5932,13 +5503,6 @@ "object-inspect@1.13.4": { "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, - "object-is@1.1.6": { - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dependencies": [ - "call-bind", - "define-properties" - ] - }, "object-keys@1.1.1": { "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, @@ -5959,9 +5523,6 @@ "wrappy" ] }, - "os-browserify@0.3.0": { - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" - }, "own-keys@1.0.1": { "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dependencies": [ @@ -5970,56 +5531,9 @@ "safe-push-apply" ] }, - "p-limit@3.1.0": { - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": [ - "yocto-queue@0.1.0" - ] - }, - "p-limit@4.0.0": { - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dependencies": [ - "yocto-queue@1.2.1" - ] - }, - "p-locate@5.0.0": { - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": [ - "p-limit@3.1.0" - ] - }, - "p-locate@6.0.0": { - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dependencies": [ - "p-limit@4.0.0" - ] - }, "p-map@7.0.3": { "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==" }, - "pako@1.0.11": { - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "parse-asn1@5.1.7": { - "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", - "dependencies": [ - "asn1.js", - "browserify-aes", - "evp_bytestokey", - "hash-base", - "pbkdf2", - "safe-buffer@5.2.1" - ] - }, - "path-browserify@1.0.1": { - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "path-exists@4.0.0": { - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "path-exists@5.0.0": { - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==" - }, "path-is-absolute@1.0.1": { "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, @@ -6040,16 +5554,6 @@ ], "bin": true }, - "pbkdf2@3.1.2": { - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": [ - "create-hash", - "create-hmac", - "ripemd160", - "safe-buffer@5.2.1", - "sha.js" - ] - }, "peek-stream@1.1.3": { "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", "dependencies": [ @@ -6067,12 +5571,6 @@ "picomatch@4.0.2": { "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" }, - "pkg-dir@5.0.0": { - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dependencies": [ - "find-up@5.0.0" - ] - }, "point-in-polygon-hao@1.2.4": { "integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==", "dependencies": [ @@ -6133,44 +5631,15 @@ "duplex-maker" ] }, - "process@0.11.10": { - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, "protocol-buffers-schema@3.6.0": { "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" }, - "public-encrypt@4.0.3": { - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dependencies": [ - "bn.js@4.12.2", - "browserify-rsa", - "create-hash", - "parse-asn1", - "randombytes", - "safe-buffer@5.2.1" - ] - }, - "punycode@1.4.1": { - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "punycode@2.3.1": { "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "qrcode-generator@1.4.4": { "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" }, - "qs@6.14.0": { - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dependencies": [ - "side-channel" - ] - }, - "querystring-es3@0.2.1": { - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" - }, - "queue-microtask@1.2.3": { - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, "quickselect@1.1.1": { "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" }, @@ -6186,13 +5655,6 @@ "safe-buffer@5.2.1" ] }, - "randomfill@1.0.4": { - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dependencies": [ - "randombytes", - "safe-buffer@5.2.1" - ] - }, "rbush@2.0.2": { "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==", "dependencies": [ @@ -6416,19 +5878,9 @@ ], "bin": true }, - "reusify@1.1.0": { - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==" - }, "rfc4648@1.5.4": { "integrity": "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==" }, - "ripemd160@2.0.2": { - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": [ - "hash-base", - "inherits" - ] - }, "robust-predicates@2.0.4": { "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" }, @@ -6472,12 +5924,6 @@ ], "bin": true }, - "run-parallel@1.2.0": { - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dependencies": [ - "queue-microtask" - ] - }, "rw@1.3.3": { "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, @@ -6577,17 +6023,6 @@ "split-string" ] }, - "setimmediate@1.0.5": { - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, - "sha.js@2.4.11": { - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": [ - "inherits", - "safe-buffer@5.2.1" - ], - "bin": true - }, "side-channel-list@1.0.0": { "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dependencies": [ @@ -6719,22 +6154,6 @@ "ste-core" ] }, - "stream-browserify@3.0.0": { - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dependencies": [ - "inherits", - "readable-stream@3.6.2" - ] - }, - "stream-http@3.2.0": { - "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", - "dependencies": [ - "builtin-status-codes", - "inherits", - "readable-stream@3.6.2", - "xtend" - ] - }, "stream-shift@1.0.3": { "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, @@ -6904,12 +6323,6 @@ "readable-stream@3.6.2" ] }, - "timers-browserify@2.0.12": { - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dependencies": [ - "setimmediate" - ] - }, "tiny-invariant@1.3.3": { "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, @@ -6970,7 +6383,7 @@ "tr46@1.0.1": { "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", "dependencies": [ - "punycode@2.3.1" + "punycode" ] }, "tslib@1.14.1": { @@ -6993,9 +6406,6 @@ ], "bin": true }, - "tty-browserify@0.0.1": { - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, "type-fest@0.16.0": { "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" }, @@ -7084,9 +6494,6 @@ "unicode-property-aliases-ecmascript@2.1.0": { "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" }, - "unicorn-magic@0.1.0": { - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==" - }, "union-value@1.0.1": { "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dependencies": [ @@ -7125,13 +6532,6 @@ ], "bin": true }, - "url@0.11.4": { - "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", - "dependencies": [ - "punycode@1.4.1", - "qs" - ] - }, "use-callback-ref@1.3.3_@types+react@19.1.2_react@19.1.0": { "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "dependencies": [ @@ -7164,19 +6564,6 @@ "util-deprecate@1.0.2": { "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "util@0.12.5": { - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": [ - "inherits", - "is-arguments", - "is-generator-function", - "is-typed-array", - "which-typed-array" - ] - }, - "validator@13.15.0": { - "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==" - }, "vite-node@3.1.2_@types+node@22.15.3": { "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", "dependencies": [ @@ -7188,31 +6575,6 @@ ], "bin": true }, - "vite-plugin-i18n-ally@6.0.1_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3": { - "integrity": "sha512-BmXlAkrmSRrbaho7iJpBf1d2EPyDK2oqY1AKVxkJEUikGDPducFpLfpmlqTyUNhsWZT01ZLWdjR2uIRnnVJXzw==", - "dependencies": [ - "cookie", - "debug", - "deep-object-diff", - "fast-glob", - "find-up@7.0.0", - "importx", - "js-yaml", - "json5", - "language-tags", - "negotiator", - "picocolors", - "vite" - ] - }, - "vite-plugin-node-polyfills@0.23.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3": { - "integrity": "sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w==", - "dependencies": [ - "@rollup/plugin-inject", - "node-stdlib-browser", - "vite" - ] - }, "vite-plugin-pwa@1.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.1__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.3": { "integrity": "sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==", "dependencies": [ @@ -7287,9 +6649,6 @@ ], "bin": true }, - "vm-browserify@1.1.2": { - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, "void-elements@3.1.0": { "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" }, @@ -7547,20 +6906,17 @@ "yallist@5.0.0": { "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" }, - "yocto-queue@0.1.0": { - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" - }, - "yocto-queue@1.2.1": { - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==" + "zod@3.25.49": { + "integrity": "sha512-JMMPMy9ZBk3XFEdbM3iL1brx4NUSejd6xr3ELrrGEfGb355gjhiAWtG3K5o+AViV/3ZfkIrCzXsZn6SbLwTR8Q==" }, - "zod@3.24.3": { - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==" + "zod@3.25.62": { + "integrity": "sha512-YCxsr4DmhPcrKPC9R1oBHQNlQzlJEyPAId//qTau/vBee9uO8K6prmRq4eMkOyxvBfH4wDPIPdLx9HVMWIY3xA==" }, "zone.js@0.8.29": { "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" }, - "zustand@5.0.4_@types+react@19.1.2_immer@10.1.1_react@19.1.0": { - "integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==", + "zustand@5.0.5_@types+react@19.1.2_immer@10.1.1_react@19.1.0": { + "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==", "dependencies": [ "@types/react", "immer", @@ -7575,12 +6931,14 @@ }, "workspace": { "dependencies": [ - "jsr:@std/path@^1.1.0" + "jsr:@std/path@^1.1.0", + "npm:@types/w3c-web-serial@*", + "npm:@types/web-bluetooth@*" ], "packageJson": { "dependencies": [ "npm:@bufbuild/protobuf@^2.2.5", - "npm:@jsr/meshtastic__core@2.6.2", + "npm:@jsr/meshtastic__core@2.6.4", "npm:@jsr/meshtastic__js@2.6.0-0", "npm:@jsr/meshtastic__transport-http@*", "npm:@jsr/meshtastic__transport-web-bluetooth@*", @@ -7622,7 +6980,6 @@ "npm:@vitejs/plugin-react@^4.4.1", "npm:autoprefixer@^10.4.21", "npm:base64-js@^1.5.1", - "npm:class-validator@~0.14.2", "npm:class-variance-authority@~0.7.1", "npm:clsx@^2.1.1", "npm:cmdk@^1.1.1", @@ -7653,14 +7010,12 @@ "npm:tar@^7.4.3", "npm:testing-library@^0.0.2", "npm:typescript@^5.8.3", - "npm:vite-plugin-i18n-ally@^6.0.1", - "npm:vite-plugin-node-polyfills@0.23", "npm:vite-plugin-pwa@1", "npm:vite-plugin-static-copy@3", "npm:vite@^6.3.4", "npm:vitest@^3.1.2", - "npm:zod@^3.24.3", - "npm:zustand@5.0.4" + "npm:zod@^3.25.62", + "npm:zustand@5.0.5" ] } } diff --git a/package.json b/package.json index 77709964..f3577bc3 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dev": "deno task dev:ui", "dev:ui": "VITE_APP_VERSION=development deno run -A npm:vite dev", "test": "deno run -A npm:vitest", + "check": "deno check", "preview": "deno run -A npm:vite preview", "package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ ." }, @@ -35,10 +36,11 @@ "homepage": "https://meshtastic.org", "dependencies": { "@bufbuild/protobuf": "^2.2.5", - "@meshtastic/core": "npm:@jsr/meshtastic__core@2.6.2", - "@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http@0.2.1", - "@meshtastic/transport-web-bluetooth": "npm:@jsr/meshtastic__transport-web-bluetooth@0.1.2", - "@meshtastic/transport-web-serial": "npm:@jsr/meshtastic__transport-web-serial@0.2.1", + "@meshtastic/core": "npm:@jsr/meshtastic__core@2.6.4", + "@meshtastic/js": "npm:@jsr/meshtastic__js@2.6.0-0", + "@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http", + "@meshtastic/transport-web-bluetooth": "npm:@jsr/meshtastic__transport-web-bluetooth", + "@meshtastic/transport-web-serial": "npm:@jsr/meshtastic__transport-web-serial", "@noble/curves": "^1.9.0", "@radix-ui/react-accordion": "^1.2.8", "@radix-ui/react-checkbox": "^1.2.3", @@ -60,6 +62,7 @@ "@tanstack/react-router-devtools": "^1.120.16", "@tanstack/router-devtools": "^1.120.15", "@turf/turf": "^7.2.0", + "@types/web-bluetooth": "^0.0.21", "base64-js": "^1.5.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -81,10 +84,8 @@ "react-map-gl": "8.0.4", "react-qrcode-logo": "^3.0.0", "rfc4648": "^1.5.4", - "vite-plugin-i18n-ally": "^6.0.1", - "vite-plugin-node-polyfills": "^0.23.0", - "zod": "^3.25.0", - "zustand": "5.0.4" + "zod": "^3.25.62", + "zustand": "5.0.5" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.5", @@ -93,13 +94,12 @@ "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", "@types/chrome": "^0.0.318", - "@types/js-cookie": "^3.0.6", "@types/node": "^22.15.3", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.3", "@types/serviceworker": "^0.0.133", + "@types/js-cookie": "^3.0.6", "@types/w3c-web-serial": "^1.0.8", - "@types/web-bluetooth": "^0.0.21", "@vitejs/plugin-react": "^4.4.1", "autoprefixer": "^10.4.21", "gzipper": "^8.2.1", diff --git a/src/components/BatteryStatus.tsx b/src/components/BatteryStatus.tsx index c80bb87e..feb7ff67 100644 --- a/src/components/BatteryStatus.tsx +++ b/src/components/BatteryStatus.tsx @@ -8,56 +8,45 @@ import { import { useTranslation } from "react-i18next"; import { DeviceMetrics } from "./types.ts"; -interface BatteryStateConfig { - condition: (level: number) => boolean; - Icon: React.ElementType; - className: string; - text: (level: number) => string; +type BatteryStatusKey = keyof typeof BATTERY_STATUS; + +interface BatteryStatusProps { + deviceMetrics?: DeviceMetrics | null; } interface BatteryStatusProps { deviceMetrics?: DeviceMetrics | null; } -const getBatteryStates = ( - t: (key: string, options?: object) => string, -): BatteryStateConfig[] => { - return [ - { - condition: (level) => level > 100, - Icon: PlugZapIcon, - className: "text-gray-500", - text: () => t("batteryStatus.pluggedIn"), - }, - { - condition: (level) => level > 80, - Icon: BatteryFullIcon, - className: "text-green-500", - text: (level) => t("batteryStatus.charging", { level }), - }, - { - condition: (level) => level > 20, - Icon: BatteryMediumIcon, - className: "text-yellow-500", - text: (level) => t("batteryStatus.charging", { level }), - }, - { - condition: () => true, - Icon: BatteryLowIcon, - className: "text-red-500", - text: (level) => t("batteryStatus.charging", { level }), - }, - ]; -}; +interface StatusConfig { + Icon: React.ElementType; + className: string; + text: string; +} + +const BATTERY_STATUS = { + PLUGGED_IN: "PLUGGED_IN", + FULL: "FULL", + MEDIUM: "MEDIUM", + LOW: "LOW", +} as const; -const getBatteryState = ( - level: number, - batteryStates: BatteryStateConfig[], -) => { - return batteryStates.find((state) => state.condition(level)); +export const getBatteryStatus = (level: number): BatteryStatusKey => { + if (level > 100) { + return BATTERY_STATUS.PLUGGED_IN; + } + if (level > 80) { + return BATTERY_STATUS.FULL; + } + if (level > 20) { + return BATTERY_STATUS.MEDIUM; + } + return BATTERY_STATUS.LOW; }; const BatteryStatus: React.FC = ({ deviceMetrics }) => { + const { t } = useTranslation(); + if ( deviceMetrics?.batteryLevel === undefined || deviceMetrics?.batteryLevel === null @@ -65,16 +54,39 @@ const BatteryStatus: React.FC = ({ deviceMetrics }) => { return null; } - const { t } = useTranslation(); - const batteryStates = getBatteryStates(t); - const { batteryLevel } = deviceMetrics; - const currentState = getBatteryState(batteryLevel, batteryStates) ?? - batteryStates[batteryStates.length - 1]; - const BatteryIcon = currentState.Icon; - const iconClassName = currentState.className; - const statusText = currentState.text(batteryLevel); + const statusKey = getBatteryStatus(batteryLevel); + + const statusConfigMap: Record = { + [BATTERY_STATUS.PLUGGED_IN]: { + Icon: PlugZapIcon, + className: "text-gray-500", + text: t("batteryStatus.pluggedIn"), + }, + [BATTERY_STATUS.FULL]: { + Icon: BatteryFullIcon, + className: "text-green-500", + text: t("batteryStatus.charging", { level: batteryLevel }), + }, + [BATTERY_STATUS.MEDIUM]: { + Icon: BatteryMediumIcon, + className: "text-yellow-500", + text: t("batteryStatus.charging", { level: batteryLevel }), + }, + [BATTERY_STATUS.LOW]: { + Icon: BatteryLowIcon, + className: "text-red-500", + text: t("batteryStatus.charging", { level: batteryLevel }), + }, + }; + + // 3. Use the key to get the current state configuration + const { + Icon: BatteryIcon, + className: iconClassName, + text: statusText, + } = statusConfigMap[statusKey]; return (
{ connection?.setOwner( create(Protobuf.Mesh.UserSchema, { - ...(myNode?.user ?? {}), ...data, }), ); diff --git a/src/components/Dialog/ImportDialog.tsx b/src/components/Dialog/ImportDialog.tsx index ac76d022..6b448ace 100644 --- a/src/components/Dialog/ImportDialog.tsx +++ b/src/components/Dialog/ImportDialog.tsx @@ -72,17 +72,19 @@ export const ImportDialog = ({ }, [importDialogInput]); const apply = () => { - channelSet?.settings.map((ch: unknown, index: number) => { - connection?.setChannel( - create(Protobuf.Channel.ChannelSchema, { - index, - role: index === 0 - ? Protobuf.Channel.Channel_Role.PRIMARY - : Protobuf.Channel.Channel_Role.SECONDARY, - settings: ch, - }), - ); - }); + channelSet?.settings.map( + (ch: Protobuf.Channel.ChannelSettings, index: number) => { + connection?.setChannel( + create(Protobuf.Channel.ChannelSchema, { + index, + role: index === 0 + ? Protobuf.Channel.Channel_Role.PRIMARY + : Protobuf.Channel.Channel_Role.SECONDARY, + settings: ch, + }), + ); + }, + ); if (channelSet?.loraConfig) { connection?.setConfig( diff --git a/src/components/Dialog/LocationResponseDialog.tsx b/src/components/Dialog/LocationResponseDialog.tsx index bd376de3..eb6d5e25 100644 --- a/src/components/Dialog/LocationResponseDialog.tsx +++ b/src/components/Dialog/LocationResponseDialog.tsx @@ -12,7 +12,7 @@ import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { useTranslation } from "react-i18next"; export interface LocationResponseDialogProps { - location: Types.PacketMetadata | undefined; + location: Types.PacketMetadata | undefined; open: boolean; onOpenChange: () => void; } @@ -33,6 +33,13 @@ export const LocationResponseDialog = ({ ? `${numberToHexUnpadded(from?.num).substring(0, 4)}` : t("unknown.shortName")); + const position = location?.data; + + const hasCoordinates = position && + typeof position.latitudeI === "number" && + typeof position.longitudeI === "number" && + typeof position.altitude === "number"; + return ( @@ -45,31 +52,40 @@ export const LocationResponseDialog = ({ -
- -

- {t("locationResponse.coordinates")} - - {location?.data.latitudeI / 1e7},{" "} - {location?.data.longitudeI / 1e7} - -

-

- {t("locationResponse.altitude")} - {location?.data.altitude} - {location?.data.altitde < 1 - ? t("unit.meter.one") - : t("unit.meter.plural")} + {hasCoordinates + ? ( +

+ +

+ {t("locationResponse.coordinates")} + + {" "} + {position.latitudeI ?? 0 / 1e7},{" "} + {position.longitudeI ?? 0 / 1e7} + +

+

+ {t("locationResponse.altitude")} {position.altitude} + {(position.altitude ?? 0) < 1 + ? t("unit.meter.one") + : t("unit.meter.plural")} +

+
+
+ ) + : ( + // Optional: Show a message if coordinates are not available +

+ {t("locationResponse.noCoordinates")}

-
-
+ )}
diff --git a/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.test.tsx b/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.test.tsx deleted file mode 100644 index 0ba79fd1..00000000 --- a/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.test.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { render, screen } from "@testing-library/react"; -import { NodeDetailsDialog } from "@components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx"; -import { useDevice } from "@core/stores/deviceStore.ts"; -import { useAppStore } from "@core/stores/appStore.ts"; -import type { Protobuf } from "@meshtastic/core"; - -vi.mock("@core/stores/deviceStore"); -vi.mock("@core/stores/appStore"); - -const mockUseDevice = vi.mocked(useDevice); -const mockUseAppStore = vi.mocked(useAppStore); - -vi.mock("@tanstack/react-router", () => ({ - useNavigate: vi.fn(), -})); - -describe("NodeDetailsDialog", () => { - const mockNode = { - num: 1234, - user: { - longName: "Test Node", - shortName: "TN", - hwModel: 1, - role: 1, - }, - lastHeard: 1697500000, - position: { - latitudeI: 450000000, - longitudeI: -750000000, - altitude: 200, - }, - deviceMetrics: { - airUtilTx: 50.123, - channelUtilization: 75.456, - batteryLevel: 88.789, - voltage: 4.2, - uptimeSeconds: 3600, - }, - } as unknown as Protobuf.Mesh.NodeInfo; - - beforeEach(() => { - vi.resetAllMocks(); - - mockUseDevice.mockReturnValue({ - getNode: (nodeNum: number) => { - if (nodeNum === 1234) { - return mockNode; - } - return undefined; - }, - }); - - mockUseAppStore.mockReturnValue({ - nodeNumDetails: 1234, - }); - }); - - it("renders node details correctly", () => { - render( {}} />); - - expect(screen.getByText(/Node Details for Test Node \(TN\)/i)) - .toBeInTheDocument(); - - expect(screen.getByText("Node Number: 1234")).toBeInTheDocument(); - expect(screen.getByText(/Node Hex: !/i)).toBeInTheDocument(); - expect(screen.getByText(/Last Heard:/i)).toBeInTheDocument(); - - expect(screen.getByText(/Coordinates:/i)).toBeInTheDocument(); - const link = screen.getByRole("link", { name: /^45, -75$/ }); - - expect(link).toBeInTheDocument(); - expect(link).toHaveAttribute( - "href", - expect.stringContaining("openstreetmap.org"), - ); - expect(screen.getByText(/Altitude: 200m/i)).toBeInTheDocument(); - - expect(screen.getByText(/Air TX utilization: 50.12%/i)).toBeInTheDocument(); - expect(screen.getByText(/Channel utilization: 75.46%/i)) - .toBeInTheDocument(); - expect(screen.getByText(/Battery level: 88.79%/i)).toBeInTheDocument(); - expect(screen.getByText(/Voltage: 4.20V/i)).toBeInTheDocument(); - expect(screen.getByText(/Uptime:/i)).toBeInTheDocument(); - - expect(screen.getByText(/All Raw Metrics:/i)).toBeInTheDocument(); - }); - - it("renders null if node is undefined", () => { - const requestedNodeNum = 5678; - - mockUseAppStore.mockReturnValue({ - nodeNumDetails: requestedNodeNum, - }); - - mockUseDevice.mockReturnValue({ - getNode: (nodeNum: number) => { - if (nodeNum === requestedNodeNum) { - return undefined; - } - if (nodeNum === 1234) { - return mockNode; - } - return undefined; - }, - }); - - const { container } = render( - {}} />, - ); - - expect(container.firstChild).toBeNull(); - expect(screen.queryByText(/Node Details for/i)).not.toBeInTheDocument(); - }); - - it("renders correctly when position is missing", () => { - const nodeWithoutPosition = { ...mockNode, position: undefined }; - mockUseDevice.mockReturnValue({ getNode: () => nodeWithoutPosition }); - mockUseAppStore.mockReturnValue({ nodeNumDetails: 1234 }); - - render( {}} />); - - expect(screen.queryByText(/Coordinates:/i)).not.toBeInTheDocument(); - expect(screen.queryByText(/Altitude:/i)).not.toBeInTheDocument(); - expect(screen.getByText(/Node Details for Test Node/i)).toBeInTheDocument(); - }); - - it("renders correctly when deviceMetrics are missing", () => { - const nodeWithoutMetrics = { ...mockNode, deviceMetrics: undefined }; - mockUseDevice.mockReturnValue({ getNode: () => nodeWithoutMetrics }); - mockUseAppStore.mockReturnValue({ nodeNumDetails: 1234 }); - - render( {}} />); - - expect(screen.queryByText(/Device Metrics:/i)).not.toBeInTheDocument(); - expect(screen.queryByText(/Air TX utilization:/i)).not.toBeInTheDocument(); - expect(screen.getByText(/Node Details for Test Node/i)).toBeInTheDocument(); - }); - - it("renders 'Never' for lastHeard when timestamp is 0", () => { - const nodeNeverHeard = { ...mockNode, lastHeard: 0 }; - mockUseDevice.mockReturnValue({ getNode: () => nodeNeverHeard }); - mockUseAppStore.mockReturnValue({ nodeNumDetails: 1234 }); - - render( {}} />); - - expect(screen.getByText(/Last Heard: Never/i)).toBeInTheDocument(); - }); -}); diff --git a/src/components/Dialog/QRDialog.tsx b/src/components/Dialog/QRDialog.tsx index ae3d259f..0cb914e0 100644 --- a/src/components/Dialog/QRDialog.tsx +++ b/src/components/Dialog/QRDialog.tsx @@ -13,7 +13,6 @@ import { Input } from "@components/UI/Input.tsx"; import { Label } from "@components/UI/Label.tsx"; import { Protobuf, type Types } from "@meshtastic/core"; import { fromByteArray } from "base64-js"; -import { ClipboardIcon } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { QRCode } from "react-qrcode-logo"; import { useTranslation } from "react-i18next"; @@ -92,7 +91,7 @@ export const QRDialog = ({ { + onChange={() => { if (selectedChannels.includes(channel.index)) { setSelectedChannels( selectedChannels.filter((c) => @@ -144,13 +143,6 @@ export const QRDialog = ({ diff --git a/src/components/Dialog/RebootDialog.tsx b/src/components/Dialog/RebootDialog.tsx index 9b59baa2..7ed48ce6 100644 --- a/src/components/Dialog/RebootDialog.tsx +++ b/src/components/Dialog/RebootDialog.tsx @@ -9,7 +9,7 @@ import { } from "@components/UI/Dialog.tsx"; import { Input } from "@components/UI/Input.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; -import { ClockIcon, RefreshCwIcon } from "lucide-react"; +import { RefreshCwIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; import { useState } from "react"; @@ -45,12 +45,6 @@ export const RebootDialog = ({ className="dark:text-slate-900" value={time} onChange={(e) => setTime(Number.parseInt(e.target.value))} - action={{ - icon: ClockIcon, - onClick() { - connection?.reboot(time * 60).then(() => onOpenChange(false)); - }, - }} /> -
- ); - }), -})); - -describe("Device component", () => { - const setWorkingConfigMock = vi.fn(); - const validateRoleSelectionMock = vi.fn(); - const mockDeviceConfig = { - role: "CLIENT", - buttonGpio: 0, - buzzerGpio: 0, - rebroadcastMode: "ALL", - nodeInfoBroadcastSecs: 300, - doubleTapAsButtonPress: false, - disableTripleClick: false, - ledHeartbeatDisabled: false, - }; - - beforeEach(() => { - vi.resetAllMocks(); - - // Mock the useDevice hook - useDevice.mockReturnValue({ - config: { - device: mockDeviceConfig, - }, - setWorkingConfig: setWorkingConfigMock, - }); - - // Mock the useUnsafeRolesDialog hook - validateRoleSelectionMock.mockResolvedValue(true); - useUnsafeRolesDialog.mockReturnValue({ - validateRoleSelection: validateRoleSelectionMock, - }); - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - it("should render the Device form", () => { - render(); - expect(screen.getByTestId("dynamic-form")).toBeInTheDocument(); - }); - - it("should use the validateRoleSelection from the unsafe roles hook", () => { - render(); - expect(useUnsafeRolesDialog).toHaveBeenCalled(); - }); - - it("should call setWorkingConfig when form is submitted", async () => { - render(); - - fireEvent.click(screen.getByTestId("submit-button")); - - await waitFor(() => { - expect(setWorkingConfigMock).toHaveBeenCalledWith( - expect.objectContaining({ - payloadVariant: { - case: "device", - value: expect.objectContaining({ role: "CLIENT" }), - }, - }), - ); - }); - }); - - it("should create config with proper structure", async () => { - render(); - - // Simulate form submission - fireEvent.click(screen.getByTestId("submit-button")); - - await waitFor(() => { - expect(setWorkingConfigMock).toHaveBeenCalledWith( - expect.objectContaining({ - payloadVariant: { - case: "device", - value: expect.any(Object), - }, - }), - ); - }); - }); -}); diff --git a/src/components/PageComponents/Config/Network/Network.test.tsx b/src/components/PageComponents/Config/Network/Network.test.tsx deleted file mode 100644 index 8eacb277..00000000 --- a/src/components/PageComponents/Config/Network/Network.test.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { fireEvent, render, screen, waitFor } from "@testing-library/react"; -import { Network } from "@components/PageComponents/Config/Network/index.tsx"; -import { useDevice } from "@core/stores/deviceStore.ts"; -import { Protobuf } from "@meshtastic/core"; - -vi.mock("@core/stores/deviceStore", () => ({ - useDevice: vi.fn(), -})); - -vi.mock("@components/Form/DynamicForm", async () => { - const React = await import("react"); - const { useState } = React; - - return { - DynamicForm: ({ onSubmit, defaultValues }) => { - const [wifiEnabled, setWifiEnabled] = useState( - defaultValues.wifiEnabled ?? false, - ); - const [ssid, setSsid] = useState(defaultValues.wifiSsid ?? ""); - const [psk, setPsk] = useState(defaultValues.wifiPsk ?? ""); - - return ( -
{ - e.preventDefault(); - onSubmit({ - ...defaultValues, - wifiEnabled, - wifiSsid: ssid, - wifiPsk: psk, - }); - }} - data-testid="dynamic-form" - > - setWifiEnabled(e.target.checked)} - /> - setSsid(e.target.value)} - disabled={!wifiEnabled} - /> - setPsk(e.target.value)} - disabled={!wifiEnabled} - /> - -
- ); - }, - }; -}); - -describe("Network component", () => { - const setWorkingConfigMock = vi.fn(); - const mockNetworkConfig = { - wifiEnabled: false, - wifiSsid: "", - wifiPsk: "", - ntpServer: "", - ethEnabled: false, - addressMode: Protobuf.Config.Config_NetworkConfig_AddressMode.DHCP, - ipv4Config: { - ip: 0, - gateway: 0, - subnet: 0, - dns: 0, - }, - enabledProtocols: - Protobuf.Config.Config_NetworkConfig_ProtocolFlags.NO_BROADCAST, - rsyslogServer: "", - }; - - beforeEach(() => { - vi.resetAllMocks(); - - useDevice.mockReturnValue({ - config: { - network: mockNetworkConfig, - }, - setWorkingConfig: setWorkingConfigMock, - }); - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - it("should render the Network form", () => { - render(); - expect(screen.getByTestId("dynamic-form")).toBeInTheDocument(); - }); - - it("should disable SSID and PSK fields when wifi is off", () => { - render(); - expect(screen.getByLabelText("SSID")).toBeDisabled(); - expect(screen.getByLabelText("PSK")).toBeDisabled(); - }); - - it("should enable SSID and PSK when wifi is toggled on", async () => { - render(); - const toggle = screen.getByLabelText("WiFi Enabled"); - fireEvent.click(toggle); // turns wifiEnabled = true - - await waitFor(() => { - expect(screen.getByLabelText("SSID")).not.toBeDisabled(); - expect(screen.getByLabelText("PSK")).not.toBeDisabled(); - }); - }); - - it("should call setWorkingConfig with the right structure on submit", async () => { - render(); - - fireEvent.click(screen.getByTestId("submit-button")); - - await waitFor(() => { - expect(setWorkingConfigMock).toHaveBeenCalledWith( - expect.objectContaining({ - payloadVariant: { - case: "network", - value: expect.objectContaining({ - wifiEnabled: false, - wifiSsid: "", - wifiPsk: "", - ntpServer: "", - ethEnabled: false, - rsyslogServer: "", - }), - }, - }), - ); - }); - }); - - it("should submit valid data after enabling wifi and entering SSID and PSK", async () => { - render(); - fireEvent.click(screen.getByLabelText("WiFi Enabled")); - - fireEvent.change(screen.getByLabelText("SSID"), { - target: { value: "MySSID" }, - }); - - fireEvent.change(screen.getByLabelText("PSK"), { - target: { value: "MySecretPSK" }, - }); - - fireEvent.click(screen.getByTestId("submit-button")); - - await waitFor(() => { - expect(setWorkingConfigMock).toHaveBeenCalledWith( - expect.objectContaining({ - payloadVariant: { - case: "network", - value: expect.objectContaining({ - wifiEnabled: true, - wifiSsid: "MySSID", - wifiPsk: "MySecretPSK", - }), - }, - }), - ); - }); - }); -}); diff --git a/src/components/PageComponents/Connect/BLE.tsx b/src/components/PageComponents/Connect/BLE.tsx index a3458792..28aec612 100644 --- a/src/components/PageComponents/Connect/BLE.tsx +++ b/src/components/PageComponents/Connect/BLE.tsx @@ -7,6 +7,7 @@ import { subscribeAll } from "@core/subscriptions.ts"; import { randId } from "@core/utils/randId.ts"; import { TransportWebBluetooth } from "@meshtastic/transport-web-bluetooth"; import { MeshDevice } from "@meshtastic/core"; +import type { BluetoothDevice } from "web-bluetooth"; import { useCallback, useEffect, useState } from "react"; import { useMessageStore } from "@core/stores/messageStore/index.ts"; import { useTranslation } from "react-i18next"; @@ -77,7 +78,7 @@ export const BLE = ( if (exists === -1) { setBleDevices(bleDevices.concat(device)); } - }).catch((error) => { + }).catch((error: Error) => { console.error("Error requesting device:", error); setConnectionInProgress(false); }).finally(() => { diff --git a/src/components/PageComponents/Connect/HTTP.tsx b/src/components/PageComponents/Connect/HTTP.tsx index e1bca177..d92733af 100644 --- a/src/components/PageComponents/Connect/HTTP.tsx +++ b/src/components/PageComponents/Connect/HTTP.tsx @@ -66,7 +66,9 @@ export const HTTP = ( subscribeAll(device, connection, messageStore); closeDialog(); } catch (error) { - console.error("Connection error:", error); + if (error instanceof Error) { + console.error("Connection error:", error); + } // Capture all connection errors regardless of type setConnectionError({ host: data.ip, secure: data.tls }); setConnectionInProgress(false); diff --git a/src/components/PageComponents/Connect/Serial.tsx b/src/components/PageComponents/Connect/Serial.tsx index ff92c1e1..1303a016 100644 --- a/src/components/PageComponents/Connect/Serial.tsx +++ b/src/components/PageComponents/Connect/Serial.tsx @@ -9,7 +9,8 @@ import { MeshDevice } from "@meshtastic/core"; import { TransportWebSerial } from "@meshtastic/transport-web-serial"; import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useMessageStore } from "../../../core/stores/messageStore/index.ts"; +import type { SerialPort } from "w3c-web-serial"; +import { useMessageStore } from "@core/stores/messageStore/index.ts"; export const Serial = ( { closeDialog }: TabElementProps, @@ -22,13 +23,13 @@ export const Serial = ( const { t } = useTranslation(); const updateSerialPortList = useCallback(async () => { - setSerialPorts(await navigator?.serial.getPorts()); + setSerialPorts(await navigator.serial.getPorts()); }, []); - navigator?.serial?.addEventListener("connect", () => { + navigator.serial.addEventListener("connect", () => { updateSerialPortList(); }); - navigator?.serial?.addEventListener("disconnect", () => { + navigator.serial.addEventListener("disconnect", () => { updateSerialPortList(); }); useEffect(() => { @@ -89,7 +90,7 @@ export const Serial = ( await navigator.serial.requestPort().then((port) => { setSerialPorts(serialPorts.concat(port)); // No need to setConnectionInProgress(false) here if requestPort is quick - }).catch((error) => { + }).catch((error: Error) => { console.error("Error requesting port:", error); }).finally(() => { setConnectionInProgress(false); diff --git a/src/components/PageComponents/Messages/MessageItem.tsx b/src/components/PageComponents/Messages/MessageItem.tsx index 7a932a1d..ab509741 100644 --- a/src/components/PageComponents/Messages/MessageItem.tsx +++ b/src/components/PageComponents/Messages/MessageItem.tsx @@ -56,21 +56,21 @@ export const MessageItem = ({ message }: MessageItemProps) => { const MESSAGE_STATUS_MAP = useMemo( (): Record => ({ [MessageState.Ack]: { - displayText: t("message_item_status_delivered_displayText"), + displayText: t("deliveryStatus.deliveryStatus."), icon: CheckCircle2, - ariaLabel: t("message_item_status_delivered_ariaLabel"), + ariaLabel: t("deliveryStatus.delivered"), iconClassName: "text-green-500", }, [MessageState.Waiting]: { - displayText: t("message_item_status_waiting_displayText"), + displayText: t("deliveryStatus.waiting"), icon: CircleEllipsis, - ariaLabel: t("message_item_status_waiting_ariaLabel"), + ariaLabel: t("deliveryStatus.waiting"), iconClassName: "text-slate-400", }, [MessageState.Failed]: { - displayText: t("message_item_status_failed_displayText"), + displayText: t("deliveryStatus.failed"), icon: AlertCircle, - ariaLabel: t("message_item_status_failed_ariaLabel"), + ariaLabel: t("deliveryStatus.failed"), iconClassName: "text-red-500 dark:text-red-400", }, }), @@ -78,9 +78,9 @@ export const MessageItem = ({ message }: MessageItemProps) => { ); const UNKNOWN_STATUS = useMemo((): MessageStatusInfo => ({ - displayText: t("message_item_status_unknown_displayText"), + displayText: t("delveryStatus.unknown"), icon: AlertCircle, - ariaLabel: t("message_item_status_unknown_ariaLabel"), + ariaLabel: t("deliveryStatus.unknown"), iconClassName: "text-red-500 dark:text-red-400", }), [t]); diff --git a/src/components/PageComponents/Messages/TraceRoute.test.tsx b/src/components/PageComponents/Messages/TraceRoute.test.tsx index cfd9dc6a..9a0f7298 100644 --- a/src/components/PageComponents/Messages/TraceRoute.test.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.test.tsx @@ -2,29 +2,71 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { render, screen } from "@testing-library/react"; import { TraceRoute } from "@components/PageComponents/Messages/TraceRoute.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; -import type { Protobuf } from "@meshtastic/core"; +import { mockDeviceStore } from "@core/stores/deviceStore.mock.ts"; +import { Protobuf } from "@meshtastic/core"; vi.mock("@core/stores/deviceStore"); describe("TraceRoute", () => { + const fromUser = { + user: { + $typeName: "meshtastic.User", + longName: "Source Node", + publicKey: new Uint8Array([1, 2, 3]), + shortName: "Source", + hwModel: 1, + macaddr: new Uint8Array([0x01, 0x02, 0x03, 0x04]), + id: "source-node", + isLicensed: false, + role: Protobuf.Config.Config_DeviceConfig_Role["CLIENT"], + } as Protobuf.Mesh.NodeInfo["user"], + }; + + const toUser = { + user: { + $typeName: "meshtastic.User", + longName: "Destination Node", + publicKey: new Uint8Array([4, 5, 6]), + shortName: "Destination", + hwModel: 2, + macaddr: new Uint8Array([0x05, 0x06, 0x07, 0x08]), + id: "destination-node", + isLicensed: false, + role: Protobuf.Config.Config_DeviceConfig_Role["CLIENT"], + } as Protobuf.Mesh.NodeInfo["user"], + }; + const mockNodes = new Map([ [ 1, - { num: 1, user: { longName: "Node A" } } as Protobuf.Mesh.NodeInfo, + { + num: 1, + user: { longName: "Node A", $typeName: "meshtastic.User" }, + $typeName: "meshtastic.NodeInfo", + } as Protobuf.Mesh.NodeInfo, ], [ 2, - { num: 2, user: { longName: "Node B" } } as Protobuf.Mesh.NodeInfo, + { + num: 2, + user: { longName: "Node B", $typeName: "meshtastic.User" }, + $typeName: "meshtastic.NodeInfo", + } as Protobuf.Mesh.NodeInfo, ], [ 3, - { num: 3, user: { longName: "Node C" } } as Protobuf.Mesh.NodeInfo, + { + num: 3, + user: { longName: "Node C", $typeName: "meshtastic.User" }, + $typeName: "meshtastic.NodeInfo", + } as Protobuf.Mesh.NodeInfo, ], ]); beforeEach(() => { vi.resetAllMocks(); vi.mocked(useDevice).mockReturnValue({ + ...mockDeviceStore, getNode: (nodeNum: number): Protobuf.Mesh.NodeInfo | undefined => { return mockNodes.get(nodeNum); }, @@ -34,16 +76,15 @@ describe("TraceRoute", () => { it("renders the route to destination with SNR values", () => { render( , ); - expect(screen.getAllByText("Source Node")).toHaveLength(1); + expect(screen.getByText("Source Node")).toBeInTheDocument(); expect(screen.getByText("Destination Node")).toBeInTheDocument(); - expect(screen.getByText("Node A")).toBeInTheDocument(); expect(screen.getByText("Node B")).toBeInTheDocument(); @@ -56,8 +97,8 @@ describe("TraceRoute", () => { it("renders the route back when provided", () => { render( { />, ); + // Check for the translated title expect(screen.getByText("Route back:")).toBeInTheDocument(); + // With route back, both names appear twice expect(screen.getAllByText("Source Node")).toHaveLength(2); - expect(screen.getAllByText("Destination Node")).toHaveLength(2); - expect(screen.getByText("Node C")).toBeInTheDocument(); expect(screen.getByText("Node A")).toBeInTheDocument(); - - expect(screen.getByText("↓ 35dBm")).toBeInTheDocument(); - expect(screen.getByText("↓ 45dBm")).toBeInTheDocument(); + expect(screen.getByText("Node C")).toBeInTheDocument(); expect(screen.getByText("↓ 15dBm")).toBeInTheDocument(); expect(screen.getByText("↓ 25dBm")).toBeInTheDocument(); + expect(screen.getByText("↓ 35dBm")).toBeInTheDocument(); + expect(screen.getByText("↓ 45dBm")).toBeInTheDocument(); }); it("renders '??' for missing SNR values", () => { render( , ); expect(screen.getByText("Node A")).toBeInTheDocument(); - expect(screen.getAllByText("↓ ??dBm")).toHaveLength(2); - }); - - it("renders hop hex if node is not found", () => { - render( - , - ); - - expect(screen.getByText("↓ 5dBm")).toBeInTheDocument(); - expect(screen.getByText("↓ 15dBm")).toBeInTheDocument(); + // Check for translated '??' placeholder + expect(screen.getAllByText(/↓ \?\?dBm/)).toHaveLength(2); }); }); diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 6ad25952..a1d85aa6 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -3,9 +3,11 @@ import type { Protobuf } from "@meshtastic/core"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { useTranslation } from "react-i18next"; +type NodeUser = Pick; + export interface TraceRouteProps { - from?: Protobuf.Mesh.NodeInfo; - to?: Protobuf.Mesh.NodeInfo; + from: NodeUser; + to: NodeUser; route: Array; routeBack?: Array; snrTowards?: Array; @@ -14,14 +16,14 @@ export interface TraceRouteProps { interface RoutePathProps { title: string; - startNode?: Protobuf.Mesh.NodeInfo; - endNode?: Protobuf.Mesh.NodeInfo; + from: NodeUser; + to: NodeUser; path: number[]; snr?: number[]; } const RoutePath = ( - { title, startNode, endNode, path, snr }: RoutePathProps, + { title, from, to, path, snr }: RoutePathProps, ) => { const { getNode } = useDevice(); const { t } = useTranslation(); @@ -32,7 +34,7 @@ const RoutePath = ( className="ml-4 border-l-2 pl-2 border-l-slate-900 text-slate-900 dark:text-slate-100 dark:border-l-slate-100" >

{title}

-

{startNode?.user?.longName}

+

{from?.user?.longName}

↓ {snr?.[0] ?? t("unknown.num")} {t("unit.dbm")} @@ -49,7 +51,7 @@ const RoutePath = (

))} -

{endNode?.user?.longName}

+

{to?.user?.longName}

); }; @@ -67,16 +69,16 @@ export const TraceRoute = ({
{routeBack && routeBack.length > 0 && ( diff --git a/src/components/UI/Button.tsx b/src/components/UI/Button.tsx index ef5ab101..905eca30 100644 --- a/src/components/UI/Button.tsx +++ b/src/components/UI/Button.tsx @@ -46,44 +46,36 @@ export interface ButtonProps iconAlignment?: "left" | "right"; } -const Button = React.forwardRef( - ( - { - className, - variant, - size, - disabled, - icon, - iconAlignment = "left", - children, - ...props - }, - ref, - ) => { - return ( - - ); - }, -); -Button.displayName = "Button"; +const Button = ({ + className, + variant, + size, + disabled, + icon, + iconAlignment = "left", + children, + ...props +}: ButtonProps) => { + return ( + + ); +}; export { Button, buttonVariants }; diff --git a/src/components/UI/Checkbox/Checkbox.test.tsx b/src/components/UI/Checkbox/Checkbox.test.tsx index 7e5ba73d..e7badabe 100644 --- a/src/components/UI/Checkbox/Checkbox.test.tsx +++ b/src/components/UI/Checkbox/Checkbox.test.tsx @@ -23,18 +23,6 @@ vi.mock("@components/UI/Label.tsx", () => ({ ), })); -vi.mock("@core/utils/cn.ts", () => ({ - cn: (...args) => args.filter(Boolean).join(" "), -})); - -vi.mock("react", async () => { - const actual = await vi.importActual("react"); - return { - ...actual, - useId: () => "test-id", - }; -}); - describe("Checkbox", () => { beforeEach(cleanup); @@ -67,11 +55,6 @@ describe("Checkbox", () => { expect(screen.getByRole("checkbox").id).toBe("custom-id"); }); - it("generates id when not provided", () => { - render(); - expect(screen.getByRole("checkbox").id).toBe("test-id"); - }); - it("renders children in Label component", () => { render(Test Label); expect(screen.getByTestId("label-component")).toHaveTextContent( diff --git a/src/components/UI/Dialog.tsx b/src/components/UI/Dialog.tsx index 763e53e0..8a820077 100644 --- a/src/components/UI/Dialog.tsx +++ b/src/components/UI/Dialog.tsx @@ -58,9 +58,7 @@ DialogContent.displayName = DialogPrimitive.Content.displayName; const DialogClose = ({ className, ...props -}: DialogPrimitive.DialogCloseProps & React.RefAttributes & { - className?: string; -}) => ( +}: React.ComponentPropsWithoutRef) => ( React.ReactNode); className?: string; } diff --git a/src/components/generic/Filter/useFilterNode.ts b/src/components/generic/Filter/useFilterNode.ts index da3b7347..a55fbe85 100644 --- a/src/components/generic/Filter/useFilterNode.ts +++ b/src/components/generic/Filter/useFilterNode.ts @@ -1,153 +1,185 @@ import { Protobuf } from "@meshtastic/core"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; -import { useMemo } from "react"; +import { useCallback, useMemo } from "react"; export type FilterState = { nodeName: string; hopsAway: [number, number]; lastHeard: [number, number]; - isFavorite: boolean | undefined; // undefined -> don't filter - viaMqtt: boolean | undefined; // undefined -> don't filter + isFavorite: boolean | undefined; + viaMqtt: boolean | undefined; snr: [number, number]; channelUtilization: [number, number]; airUtilTx: [number, number]; batteryLevel: [number, number]; voltage: [number, number]; - role: (Protobuf.Config.Config_DeviceConfig_Role)[]; - hwModel: (Protobuf.Mesh.HardwareModel)[]; + role: Protobuf.Config.Config_DeviceConfig_Role[]; + hwModel: Protobuf.Mesh.HardwareModel[]; }; -export function useFilterNode() { - const defaultFilterValues = useMemo(() => ({ - nodeName: "", - hopsAway: [0, 7], - lastHeard: [0, 864000], // 0-10 days - isFavorite: undefined, - viaMqtt: undefined, - snr: [-20, 10], - channelUtilization: [0, 100], - airUtilTx: [0, 100], - batteryLevel: [0, 101], - voltage: [0, 5], - role: Object.values(Protobuf.Config.Config_DeviceConfig_Role).filter( - (v): v is Protobuf.Config.Config_DeviceConfig_Role => - typeof v === "number", - ), - hwModel: Object.values(Protobuf.Mesh.HardwareModel).filter( - (v): v is Protobuf.Mesh.HardwareModel => typeof v === "number", - ), - }), []); - - function nodeFilter( - node: Protobuf.Mesh.NodeInfo, - filterOverrides?: Partial, - ): boolean { - const filterState: FilterState = { - ...defaultFilterValues, - ...filterOverrides, - }; - - if (!node.user) return false; - - const nodeName = filterState.nodeName.toLowerCase(); - if ( - !( - node.user?.shortName.toLowerCase().includes(nodeName) || - node.user?.longName.toLowerCase().includes(nodeName) || - node?.num.toString().includes(nodeName) || - numberToHexUnpadded(node?.num).includes( - nodeName.replace(/!/g, ""), - ) - ) - ) return false; - - const hops = node?.hopsAway ?? 7; - if (hops < filterState.hopsAway[0] || hops > filterState.hopsAway[1]) { +const shallowEqualArray = (a: T[], b: T[]): boolean => { + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { return false; } - - const secondsAgo = Date.now() / 1000 - (node?.lastHeard ?? 0); - if ( - secondsAgo < filterState.lastHeard[0] || - ( - secondsAgo > filterState.lastHeard[1] && - filterState.lastHeard[1] !== defaultFilterValues.lastHeard[1] - ) - ) return false; - - if ( - typeof filterState.isFavorite !== "undefined" && - node.isFavorite !== filterState.isFavorite - ) return false; - - if ( - typeof filterState.viaMqtt !== "undefined" && - node.viaMqtt !== filterState.viaMqtt - ) return false; - - const snr = node?.snr ?? -20; - if ( - snr < filterState.snr[0] || - snr > filterState.snr[1] - ) return false; - - const channelUtilization = node?.deviceMetrics?.channelUtilization ?? 0; - if ( - channelUtilization < filterState.channelUtilization[0] || - channelUtilization > filterState.channelUtilization[1] - ) return false; - - const airUtilTx = node?.deviceMetrics?.airUtilTx ?? 0; - if ( - airUtilTx < filterState.airUtilTx[0] || - airUtilTx > filterState.airUtilTx[1] - ) return false; - - const batt = node?.deviceMetrics?.batteryLevel ?? 101; - if ( - batt < filterState.batteryLevel[0] || - batt > filterState.batteryLevel[1] - ) return false; - - const voltage = node?.deviceMetrics?.voltage ?? 0; - if ( - voltage < filterState.voltage[0] || - voltage > filterState.voltage[1] - ) return false; - - const role: Protobuf.Config.Config_DeviceConfig_Role = node.user?.role ?? - Protobuf.Config.Config_DeviceConfig_Role.CLIENT; - if (!filterState.role.includes(role)) return false; - - const hwModel: Protobuf.Mesh.HardwareModel = node.user?.hwModel ?? - Protobuf.Mesh.HardwareModel.UNSET; - if (!filterState.hwModel.includes(hwModel)) return false; - - // All conditions are true - return true; } + return true; +}; - // deno-lint-ignore no-explicit-any - function shallowEqualArray(a: any[], b: any[]) { - return a.length === b.length && a.every((v, i) => v === b[i]); - } +export function useFilterNode() { + const defaultFilterValues = useMemo( + () => ({ + nodeName: "", + hopsAway: [0, 7], + lastHeard: [0, 864000], // 0-10 days + isFavorite: undefined, + viaMqtt: undefined, + snr: [-20, 10], + channelUtilization: [0, 100], + airUtilTx: [0, 100], + batteryLevel: [0, 101], + voltage: [0, 5], + role: Object.values(Protobuf.Config.Config_DeviceConfig_Role).filter( + (v): v is Protobuf.Config.Config_DeviceConfig_Role => + typeof v === "number", + ), + hwModel: Object.values(Protobuf.Mesh.HardwareModel).filter( + (v): v is Protobuf.Mesh.HardwareModel => typeof v === "number", + ), + }), + [], + ); + + const nodeFilter = useCallback( + ( + node: Protobuf.Mesh.NodeInfo, + filterOverrides?: Partial, + ): boolean => { + const filterState: FilterState = { + ...defaultFilterValues, + ...filterOverrides, + }; + + if (!node.user) return false; + + const nodeName = filterState.nodeName.toLowerCase(); + if ( + nodeName && + !( + node.user?.shortName.toLowerCase().includes(nodeName) || + node.user?.longName.toLowerCase().includes(nodeName) || + node.num.toString().includes(nodeName) || + numberToHexUnpadded(node.num).includes(nodeName.replace(/!/g, "")) + ) + ) { + return false; + } + + const hops = node.hopsAway ?? 7; + if (hops < filterState.hopsAway[0] || hops > filterState.hopsAway[1]) { + return false; + } + + const secondsAgo = Date.now() / 1000 - (node.lastHeard ?? 0); + if ( + secondsAgo < filterState.lastHeard[0] || + (secondsAgo > filterState.lastHeard[1] && + filterState.lastHeard[1] !== defaultFilterValues.lastHeard[1]) + ) { + return false; + } + + if ( + typeof filterState.isFavorite !== "undefined" && + node.isFavorite !== filterState.isFavorite + ) { + return false; + } + + if ( + typeof filterState.viaMqtt !== "undefined" && + node.viaMqtt !== filterState.viaMqtt + ) { + return false; + } + + const snr = node.snr ?? -20; + if (snr < filterState.snr[0] || snr > filterState.snr[1]) return false; + + const channelUtilization = node.deviceMetrics?.channelUtilization ?? 0; + if ( + channelUtilization < filterState.channelUtilization[0] || + channelUtilization > filterState.channelUtilization[1] + ) { + return false; + } + + const airUtilTx = node.deviceMetrics?.airUtilTx ?? 0; + if ( + airUtilTx < filterState.airUtilTx[0] || + airUtilTx > filterState.airUtilTx[1] + ) { + return false; + } + + const batt = node.deviceMetrics?.batteryLevel ?? 101; + if ( + batt < filterState.batteryLevel[0] || + batt > filterState.batteryLevel[1] + ) { + return false; + } + + const voltage = node.deviceMetrics?.voltage ?? 0; + if ( + voltage < filterState.voltage[0] || + voltage > filterState.voltage[1] + ) { + return false; + } + + const role: Protobuf.Config.Config_DeviceConfig_Role = node.user.role ?? + Protobuf.Config.Config_DeviceConfig_Role.CLIENT; + if (!filterState.role.includes(role)) return false; + + const hwModel: Protobuf.Mesh.HardwareModel = node.user.hwModel ?? + Protobuf.Mesh.HardwareModel.UNSET; + if (!filterState.hwModel.includes(hwModel)) return false; + + return true; + }, + [defaultFilterValues], + ); + + const isFilterDirty = useCallback( + ( + current: FilterState, + overrides?: Partial, + ): boolean => { + const base: FilterState = overrides + ? { ...defaultFilterValues, ...overrides } + : defaultFilterValues; + + for (const key of Object.keys(base) as (keyof FilterState)[]) { + const currentValue = current[key]; + const defaultValue = base[key]; + + if (Array.isArray(defaultValue) && Array.isArray(currentValue)) { + if (!shallowEqualArray(currentValue, defaultValue)) { + return true; + } + } else if (currentValue !== defaultValue) { + return true; + } + } - function isFilterDirty( - current: FilterState, - overrides?: Partial, - ): boolean { - const base: FilterState = overrides - ? { ...defaultFilterValues, ...overrides } - : defaultFilterValues; - - return (Object.keys(base) as (keyof FilterState)[]).some((key) => { - const curr = current[key]; - const def = base[key]; - return Array.isArray(def) && Array.isArray(curr) - ? !shallowEqualArray(curr, def) - : curr !== def; - }); - } + return false; + }, + [defaultFilterValues], + ); return { nodeFilter, defaultFilterValues, isFilterDirty }; } diff --git a/src/components/generic/Table/index.test.tsx b/src/components/generic/Table/index.test.tsx index 727357f4..8062144b 100644 --- a/src/components/generic/Table/index.test.tsx +++ b/src/components/generic/Table/index.test.tsx @@ -1,142 +1,128 @@ import { describe, expect, it } from "vitest"; import { fireEvent, render, screen } from "@testing-library/react"; -import { Table } from "@components/generic/Table/index.tsx"; +import { DataRow, Heading, Table } from "@components/generic/Table/index.tsx"; import { TimeAgo } from "@components/generic/TimeAgo.tsx"; import { Mono } from "@components/generic/Mono.tsx"; // @ts-types="react" describe("Generic Table", () => { it("Can render an empty table.", () => { - render( - , - ); + render(
); expect(screen.getByRole("table")).toBeInTheDocument(); }); it("Can render a table with headers and no rows.", async () => { - render( -
, - ); + const headings: Heading[] = [ + { title: "Short Name", sortable: true }, + { title: "Last Heard", sortable: true }, + { title: "Connection", sortable: true }, + ]; + render(
); await screen.findByRole("table"); - expect(screen.getAllByRole("columnheader")).toHaveLength(9); + expect(screen.getAllByRole("columnheader")).toHaveLength(3); }); - // A simplified version of the rows in pages/Nodes.tsx for testing purposes - const mockDevicesWithShortNameAndConnection = [ + // Mock data representing devices + const mockDevices = [ { - user: { shortName: "TST1" }, + id: "TST1", + shortName: "TST1", hopsAway: 1, - lastHeard: Date.now() + 1000, + lastHeard: Date.now() - 3000, viaMqtt: false, }, { - user: { shortName: "TST2" }, + id: "TST2", + shortName: "TST2", hopsAway: 0, - lastHeard: Date.now() + 4000, + lastHeard: Date.now() - 1000, viaMqtt: true, + isFavorite: true, // Favorite device }, { - user: { shortName: "TST3" }, + id: "TST3", + shortName: "TST3", hopsAway: 4, - lastHeard: Date.now(), + lastHeard: Date.now() - 5000, viaMqtt: false, }, { - user: { shortName: "TST4" }, + id: "TST4", + shortName: "TST4", hopsAway: 3, - lastHeard: Date.now() + 2000, + lastHeard: Date.now() - 2000, viaMqtt: true, }, ]; - const mockRows = mockDevicesWithShortNameAndConnection.map((node) => [ -

{node.user.shortName}

, - - - , - - {node.lastHeard !== 0 - ? node.viaMqtt === false && node.hopsAway === 0 - ? "Direct" - : `${node.hopsAway?.toString()} ${ - node.hopsAway ?? 0 > 1 ? "hops" : "hop" - } away` - : "-"} - {node.viaMqtt === true ? ", via MQTT" : ""} - , - ]); + // Transform mock data into the format expected by the Table component + const mockRows: DataRow[] = mockDevices.map((node) => ({ + id: node.id, + isFavorite: node.isFavorite, + cells: [ + { + content: {node.shortName}, + sortValue: node.shortName, + }, + { + content: ( + + + + ), + sortValue: node.lastHeard, + }, + { + content: ( + + {node.lastHeard !== 0 + ? node.viaMqtt === false && node.hopsAway === 0 + ? "Direct" + : `${node.hopsAway} ${node.hopsAway > 1 ? "hops" : "hop"} away` + : "-"} + {node.viaMqtt ? ", via MQTT" : ""} + + ), + sortValue: node.hopsAway, + }, + ], + })); - it("Can sort rows appropriately.", async () => { - render( -
, - ); + const headings: Heading[] = [ + { title: "Short Name", sortable: true }, + { title: "Last Heard", sortable: true }, + { title: "Connection", sortable: true }, + ]; + + it("Can sort rows, keeping favorites at the top", async () => { + render(
); const renderedTable = await screen.findByRole("table"); const columnHeaders = screen.getAllByRole("columnheader"); expect(columnHeaders).toHaveLength(3); - // Will be sorted "Last heard" "asc" by default - expect( - [...renderedTable.querySelectorAll("[data-testshortname]")] - .map((el) => el.textContent) - .map((v) => v?.trim()) - .join(","), - ) - .toMatch("TST2,TST4,TST1,TST3"); - - fireEvent.click(columnHeaders[0]); + const getRenderedOrder = () => + [...renderedTable.querySelectorAll("[data-testid='short-name']")].map( + (el) => el.textContent?.trim(), + ); - // Re-sort by Short Name asc - expect( - [...renderedTable.querySelectorAll("[data-testshortname]")] - .map((el) => el.textContent) - .map((v) => v?.trim()) - .join(","), - ) - .toMatch("TST1,TST2,TST3,TST4"); + // Default sort: "Last Heard" desc. TST2 is favorite, so it's first. + // Then the rest are sorted by lastHeard timestamp (most recent first). + // Order of timestamps: TST2 (latest, but favorite), TST4, TST1, TST3 (oldest). + expect(getRenderedOrder()).toEqual(["TST2", "TST4", "TST1", "TST3"]); + // Click "Short Name" to sort asc fireEvent.click(columnHeaders[0]); + // TST2 is favorite, so it's first. Then TST1, TST3, TST4 alphabetically. + expect(getRenderedOrder()).toEqual(["TST2", "TST1", "TST3", "TST4"]); - // Re-sort by Short Name desc - expect( - [...renderedTable.querySelectorAll("[data-testshortname]")] - .map((el) => el.textContent) - .map((v) => v?.trim()) - .join(","), - ) - .toMatch("TST4,TST3,TST2,TST1"); + // Click "Short Name" again to sort desc + fireEvent.click(columnHeaders[0]); + // TST2 is favorite, so it's first. Then TST4, TST3, TST1 reverse alphabetically. + expect(getRenderedOrder()).toEqual(["TST2", "TST4", "TST3", "TST1"]); + // Click "Connection" to sort by hops asc fireEvent.click(columnHeaders[2]); - - // Re-sort by Hops Away - expect( - [...renderedTable.querySelectorAll("[data-testshortname]")] - .map((el) => el.textContent) - .map((v) => v?.trim()) - .join(","), - ) - .toMatch("TST2,TST1,TST4,TST3"); + // TST2 is favorite (and also has 0 hops). Then sorted by hops: TST1 (1), TST4 (3), TST3 (4). + expect(getRenderedOrder()).toEqual(["TST2", "TST1", "TST4", "TST3"]); }); }); diff --git a/src/components/generic/Table/index.tsx b/src/components/generic/Table/index.tsx index ae66a730..af699644 100755 --- a/src/components/generic/Table/index.tsx +++ b/src/components/generic/Table/index.tsx @@ -1,30 +1,32 @@ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; -import { useState } from "react"; +import { useMemo, useState } from "react"; import React from "react"; import { cn } from "@core/utils/cn.ts"; -interface FavoriteIconProps { - showFavorite: boolean; +export interface Heading { + title: string; + sortable: boolean; } -interface AvatarCellProps { - children: React.ReactElement; +interface Cell { + content: React.ReactNode; + sortValue: string | number; } -export interface TableProps { - headings: Heading[]; - rows: React.ReactElement[][]; +export interface DataRow { + id: string | number; + isFavorite?: boolean; + cells: Cell[]; } -export interface Heading { - title: string; - type: "blank" | "normal"; - sortable: boolean; +export interface TableProps { + headings: Heading[]; + rows: DataRow[]; } -function numericHops(hopsAway: string | unknown): number { - if (typeof hopsAway !== "string") { - return Number.MAX_SAFE_INTEGER; +function numericHops(hopsAway: string | number): number { + if (typeof hopsAway === "number") { + return hopsAway; } if (hopsAway.match(/direct/i)) { return 0; @@ -37,7 +39,7 @@ export const Table = ({ headings, rows }: TableProps) => { const [sortColumn, setSortColumn] = useState("Last Heard"); const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc"); - const headingSort = (title: string) => { + const handleSort = (title: string) => { if (sortColumn === title) { setSortOrder(sortOrder === "asc" ? "desc" : "asc"); } else { @@ -46,72 +48,36 @@ export const Table = ({ headings, rows }: TableProps) => { } }; - const getElement = (cell: React.ReactNode): React.ReactElement | null => { - if (!React.isValidElement(cell)) { - return null; - } - if (cell.type === React.Fragment) { - const childrenArray = React.Children.toArray(cell.props.children); - const firstElement = childrenArray.find((child) => - React.isValidElement(child) - ); - return (firstElement as React.ReactElement) ?? null; - } - // If not a fragment, return the element itself - return cell; - }; - - const sortedRows = rows.slice().sort((a, b) => { - if (!sortColumn) return 0; + const sortedRows = useMemo(() => { + if (!sortColumn) return rows; const columnIndex = headings.findIndex((h) => h.title === sortColumn); - if (columnIndex === -1) return 0; + if (columnIndex === -1) return rows; - const elementA = getElement(a[columnIndex]); - const elementB = getElement(b[columnIndex]); + return [...rows].sort((a, b) => { + if (a.isFavorite !== b.isFavorite) { + return a.isFavorite ? -1 : 1; + } - // Avatar contains the prop showFavorite which indicates isFavorite - const favA = a[0]?.props?.children?.props?.showFavorite ?? false; - const favB = b[0]?.props?.children?.props?.showFavorite ?? false; + const aCell = a.cells[columnIndex]; + const bCell = b.cells[columnIndex]; - // Always put favorites at the top - if (favA !== favB) return favA ? -1 : 1; + let aValue: string | number; + let bValue: string | number; - if (sortColumn === "Last Heard") { - const aTimestamp = elementA?.props?.children?.props?.timestamp ?? 0; - const bTimestamp = elementB?.props?.children?.props?.timestamp ?? 0; - if (aTimestamp < bTimestamp) return sortOrder === "asc" ? -1 : 1; - if (aTimestamp > bTimestamp) return sortOrder === "asc" ? 1 : -1; - return 0; - } + if (sortColumn === "Connection") { + aValue = numericHops(aCell.sortValue); + bValue = numericHops(bCell.sortValue); + } else { + aValue = aCell.sortValue; + bValue = bCell.sortValue; + } - if (sortColumn === "Connection") { - const aHopsStr = elementA?.props?.children[0]; - const bHopsStr = elementB?.props?.children[0]; - const aNumHops = numericHops(aHopsStr); - const bNumHops = numericHops(bHopsStr); - if (aNumHops < bNumHops) return sortOrder === "asc" ? -1 : 1; - if (aNumHops > bNumHops) return sortOrder === "asc" ? 1 : -1; + if (aValue < bValue) return sortOrder === "asc" ? -1 : 1; + if (aValue > bValue) return sortOrder === "asc" ? 1 : -1; return 0; - } - - const aValue = elementA?.props?.children; - const bValue = elementB?.props?.children; - const valA = aValue ?? ""; - const valB = bValue ?? ""; - - // Ensure consistent comparison for potentially different types - const compareA = typeof valA === "string" || typeof valA === "number" - ? valA - : String(valA); - const compareB = typeof valB === "string" || typeof valB === "number" - ? valB - : String(valB); - - if (compareA < compareB) return sortOrder === "asc" ? -1 : 1; - if (compareA > compareB) return sortOrder === "asc" ? 1 : -1; - return 0; - }); + }); + }, [rows, sortColumn, sortOrder, headings]); return (
@@ -121,17 +87,15 @@ export const Table = ({ headings, rows }: TableProps) => { - {sortedRows.map((row) => { - const firstCellKey = - (React.isValidElement(row[0]) && row[0].key !== null) - ? String(row[0].key) - : null; - const rowKey = firstCellKey ?? Math.random().toString(); // Use random only as last resort - - const isFavorite = row[0]?.props?.children?.props?.showFavorite ?? - false; - return ( - - {row.map((item, cellIndex) => { - const cellKey = `${rowKey}_${cellIndex}`; - return cellIndex === 0 - ? ( - - ) - : ( - - ); - })} - - ); - })} + {sortedRows.map((row) => ( + + {row.cells.map((cell, cellIndex) => + cellIndex === 0 + ? ( + + ) + : ( + + ) + )} + + ))}
heading.sortable && headingSort(heading.title)} + className={cn( + "py-2 pr-3 text-left", + heading.sortable && + "cursor-pointer hover:brightness-hover active:brightness-press", + )} + onClick={() => heading.sortable && handleSort(heading.title)} onKeyUp={(e) => { - if ( - heading.sortable && (e.key === "Enter" || e.key === " ") - ) { - headingSort(heading.title); + if (heading.sortable && (e.key === "Enter" || e.key === " ")) { + handleSort(heading.title); } }} tabIndex={heading.sortable ? 0 : -1} @@ -153,49 +117,37 @@ export const Table = ({ headings, rows }: TableProps) => {
- {item} - - {item} -
+ {cell.content} + + {cell.content} +
); diff --git a/src/core/hooks/useBrowserFeatureDetection.ts b/src/core/hooks/useBrowserFeatureDetection.ts index 3f2667f2..e792ca1b 100644 --- a/src/core/hooks/useBrowserFeatureDetection.ts +++ b/src/core/hooks/useBrowserFeatureDetection.ts @@ -10,8 +10,8 @@ interface BrowserSupport { export function useBrowserFeatureDetection(): BrowserSupport { const support = useMemo(() => { const features: [BrowserFeature, boolean][] = [ - ["Web Bluetooth", !!navigator?.bluetooth], - ["Web Serial", !!navigator?.serial], + ["Web Bluetooth", !!navigator.bluetooth], + ["Web Serial", !!navigator.serial], [ "Secure Context", globalThis.location.protocol === "https:" || diff --git a/src/core/hooks/useCookie.ts b/src/core/hooks/useCookie.ts index df3d9d82..24e97b01 100644 --- a/src/core/hooks/useCookie.ts +++ b/src/core/hooks/useCookie.ts @@ -1,9 +1,9 @@ -import Cookies, { type CookieAttributes } from "js-cookie"; +import Cookies from "js-cookie"; import { useCallback, useState } from "react"; interface CookieHookResult { value: T | undefined; - setCookie: (value: T, options?: CookieAttributes) => void; + setCookie: (value: T, options?: Cookies.CookieAttributes) => void; removeCookie: () => void; } @@ -22,7 +22,7 @@ function useCookie( }); const setCookie = useCallback( - (value: T, options?: CookieAttributes) => { + (value: T, options?: Cookies.CookieAttributes) => { try { Cookies.set(cookieName, JSON.stringify(value), options); setCookieValue(value); diff --git a/src/core/hooks/usePinnedItems.test.ts b/src/core/hooks/usePinnedItems.test.ts deleted file mode 100644 index 3741ffdb..00000000 --- a/src/core/hooks/usePinnedItems.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { act, renderHook } from "@testing-library/react"; -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { usePinnedItems } from "./usePinnedItems.ts"; - -const mockSetPinnedItems = vi.fn(); -const mockUseLocalStorage = vi.fn(); - -vi.mock("@core/hooks/useLocalStorage.ts", () => ({ - default: (...args) => mockUseLocalStorage(...args), -})); - -describe("usePinnedItems", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it("returns default pinnedItems and togglePinnedItem", () => { - mockUseLocalStorage.mockReturnValue([[], mockSetPinnedItems]); - - const { result } = renderHook(() => - usePinnedItems({ storageName: "test-storage" }) - ); - - expect(result.current.pinnedItems).toEqual([]); - expect(typeof result.current.togglePinnedItem).toBe("function"); - }); - - it("adds an item if it's not already pinned", () => { - mockUseLocalStorage.mockReturnValue([["item1"], mockSetPinnedItems]); - - const { result } = renderHook(() => - usePinnedItems({ storageName: "test-storage" }) - ); - - act(() => { - result.current.togglePinnedItem("item2"); - }); - - expect(mockSetPinnedItems).toHaveBeenCalledWith(expect.any(Function)); - - const updater = mockSetPinnedItems.mock.calls[0][0]; - const updated = updater(["item1"]); - - expect(updated).toEqual(["item1", "item2"]); - }); - - it("removes an item if it's already pinned", () => { - mockUseLocalStorage.mockReturnValue([ - ["item1", "item2"], - mockSetPinnedItems, - ]); - - const { result } = renderHook(() => - usePinnedItems({ storageName: "test-storage" }) - ); - - act(() => { - result.current.togglePinnedItem("item1"); - }); - - expect(mockSetPinnedItems).toHaveBeenCalledWith(expect.any(Function)); - - const updater = mockSetPinnedItems.mock.calls[0][0]; - const updated = updater(["item1", "item2"]); - - expect(updated).toEqual(["item2"]); - }); -}); diff --git a/src/core/stores/deviceStore.mock.ts b/src/core/stores/deviceStore.mock.ts new file mode 100644 index 00000000..fb97c9d3 --- /dev/null +++ b/src/core/stores/deviceStore.mock.ts @@ -0,0 +1,82 @@ +import { vi } from "vitest"; +import { type Device } from "./deviceStore.ts"; +import { Protobuf } from "@meshtastic/core"; + +/** + * You can spread this base mock in your tests and override only the + * properties relevant to a specific test case. + * + * @example + * vi.mocked(useDevice).mockReturnValue({ + * ...mockDeviceStore, + * getNode: (nodeNum) => mockNodes.get(nodeNum), + * }); + */ +export const mockDeviceStore: Device = { + id: 0, + status: 5 as const, + channels: new Map(), + config: {} as Protobuf.LocalOnly.LocalConfig, + moduleConfig: {} as Protobuf.LocalOnly.LocalModuleConfig, + workingConfig: [], + workingModuleConfig: [], + hardware: {} as Protobuf.Mesh.MyNodeInfo, + metadata: new Map(), + traceroutes: new Map(), + nodeErrors: new Map(), + connection: undefined, + activeNode: 0, + waypoints: [], + pendingSettingsChanges: false, + messageDraft: "", + unreadCounts: new Map(), + nodesMap: new Map(), + dialog: { + import: false, + QR: false, + shutdown: false, + reboot: false, + rebootOTA: false, + deviceName: false, + nodeRemoval: false, + pkiBackup: false, + nodeDetails: false, + unsafeRoles: false, + refreshKeys: false, + deleteMessages: false, + }, + setStatus: vi.fn(), + setConfig: vi.fn(), + setModuleConfig: vi.fn(), + setWorkingConfig: vi.fn(), + setWorkingModuleConfig: vi.fn(), + setHardware: vi.fn(), + setActiveNode: vi.fn(), + setPendingSettingsChanges: vi.fn(), + addChannel: vi.fn(), + addWaypoint: vi.fn(), + addNodeInfo: vi.fn(), + addUser: vi.fn(), + addPosition: vi.fn(), + addConnection: vi.fn(), + addTraceRoute: vi.fn(), + addMetadata: vi.fn(), + removeNode: vi.fn(), + setDialogOpen: vi.fn(), + getDialogOpen: vi.fn().mockReturnValue(false), + processPacket: vi.fn(), + setMessageDraft: vi.fn(), + setNodeError: vi.fn(), + clearNodeError: vi.fn(), + getNodeError: vi.fn().mockReturnValue(undefined), + hasNodeError: vi.fn().mockReturnValue(false), + incrementUnread: vi.fn(), + resetUnread: vi.fn(), + getNodes: vi.fn().mockReturnValue([]), + getNodesLength: vi.fn().mockReturnValue(0), + getNode: vi.fn().mockReturnValue(undefined), + getMyNode: vi.fn(), + sendAdminMessage: vi.fn(), + updateFavorite: vi.fn(), + updateIgnored: vi.fn(), +}; diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index d8b7b03d..488a5d5d 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -114,7 +114,7 @@ export const useDeviceStore = createStore((set, get) => ({ addDevice: (id: number) => { set( - produce((draft) => { + produce((draft) => { draft.devices.set(id, { id, status: Types.DeviceStatusEnum.DeviceDisconnected, @@ -151,7 +151,7 @@ export const useDeviceStore = createStore((set, get) => ({ setStatus: (status: Types.DeviceStatusEnum) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.status = status; @@ -161,7 +161,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setConfig: (config: Protobuf.Config.Config) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { switch (config.payloadVariant.case) { @@ -203,7 +203,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setModuleConfig: (config: Protobuf.ModuleConfig.ModuleConfig) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { switch (config.payloadVariant.case) { @@ -271,7 +271,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setWorkingConfig: (config: Protobuf.Config.Config) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; const index = device.workingConfig.findIndex( @@ -289,7 +289,7 @@ export const useDeviceStore = createStore((set, get) => ({ moduleConfig: Protobuf.ModuleConfig.ModuleConfig, ) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; const index = device.workingModuleConfig.findIndex( @@ -307,7 +307,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setHardware: (hardware: Protobuf.Mesh.MyNodeInfo) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.hardware = hardware; @@ -317,7 +317,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setPendingSettingsChanges: (state) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.pendingSettingsChanges = state; @@ -327,7 +327,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addChannel: (channel: Protobuf.Channel.Channel) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.channels.set(channel.index, channel); @@ -337,7 +337,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addWaypoint: (waypoint: Protobuf.Mesh.Waypoint) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { const index = device.waypoints.findIndex((wp) => @@ -354,7 +354,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addNodeInfo: (nodeInfo) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; @@ -364,7 +364,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setActiveNode: (node) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.activeNode = node; @@ -374,7 +374,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addUser: (user) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) { return; @@ -389,7 +389,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addPosition: (position) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) { return; @@ -404,7 +404,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addConnection: (connection) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.connection = connection; @@ -414,7 +414,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addMetadata: (from, metadata) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.metadata.set(from, metadata); @@ -424,7 +424,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, addTraceRoute: (traceroute) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; const routes = device.traceroutes.get(traceroute.from) ?? []; @@ -433,9 +433,9 @@ export const useDeviceStore = createStore((set, get) => ({ }), ); }, - removeNode: (nodeNum) => { + removeNode: (nodeNum: number) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) { return; @@ -446,7 +446,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setDialogOpen: (dialog: DialogVariant, open: boolean) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.dialog[dialog] = open; @@ -461,7 +461,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, processPacket(data: ProcessPacketParams) { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; const node = device.nodesMap.get(data.from); @@ -484,7 +484,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, setMessageDraft: (message: string) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.messageDraft = message; @@ -492,9 +492,9 @@ export const useDeviceStore = createStore((set, get) => ({ }), ); }, - setNodeError: (nodeNum, error) => { + setNodeError: (nodeNum: number, error: string) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.nodeErrors.set(nodeNum, { node: nodeNum, error }); @@ -504,7 +504,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, clearNodeError: (nodeNum: number) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (device) { device.nodeErrors.delete(nodeNum); @@ -524,7 +524,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, incrementUnread: (nodeNum: number) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; const currentCount = device.unreadCounts.get(nodeNum) ?? 0; @@ -534,7 +534,7 @@ export const useDeviceStore = createStore((set, get) => ({ }, resetUnread: (nodeNum: number) => { set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); if (!device) return; device.unreadCounts.set(nodeNum, 0); @@ -610,10 +610,12 @@ export const useDeviceStore = createStore((set, get) => ({ })); set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); const node = device?.nodesMap.get(nodeNum); - node.isFavorite = isFavorite; + if (node) { + node.isFavorite = isFavorite; + } }), ); }, @@ -631,10 +633,12 @@ export const useDeviceStore = createStore((set, get) => ({ })); set( - produce((draft) => { + produce((draft) => { const device = draft.devices.get(id); const node = device?.nodesMap.get(nodeNum); - node.isIgnored = isIgnored; + if (node) { + node.isIgnored = isIgnored; + } }), ); }, @@ -651,7 +655,7 @@ export const useDeviceStore = createStore((set, get) => ({ removeDevice: (id) => { set( - produce((draft) => { + produce((draft) => { draft.devices.delete(id); }), ); diff --git a/src/core/stores/storage/indexDB.ts b/src/core/stores/storage/indexDB.ts index d7d89342..ce2c2790 100644 --- a/src/core/stores/storage/indexDB.ts +++ b/src/core/stores/storage/indexDB.ts @@ -1,4 +1,4 @@ -import { PersistStorage, StateStorage } from "zustand/middleware"; +import { PersistStorage, StateStorage, StorageValue } from "zustand/middleware"; import { del, get, set } from "idb-keyval"; import { ChannelId, MessageLogMap } from "@core/stores/messageStore/types.ts"; @@ -56,18 +56,25 @@ const reviver: JsonReviver = (_, value) => { }; export const storageWithMapSupport: PersistStorage = { - getItem: async (name): Promise => { + getItem: async ( + name, + ): Promise | null> => { const str = await zustandIndexDBStorage.getItem(name); if (!str) return null; try { - const parsed = JSON.parse(str, reviver) as PersistedMessageState; + const parsed = JSON.parse(str, reviver) as StorageValue< + PersistedMessageState + >; return parsed; } catch (error) { console.error(`Error parsing persisted state (${name}):`, error); return null; } }, - setItem: async (name, newValue: PersistedMessageState): Promise => { + setItem: async ( + name, + newValue: StorageValue, + ): Promise => { try { const str = JSON.stringify(newValue, replacer); await zustandIndexDBStorage.setItem(name, str); diff --git a/src/core/utils/eventBus.test.ts b/src/core/utils/eventBus.test.ts index 6d2fc6ee..2d874066 100644 --- a/src/core/utils/eventBus.test.ts +++ b/src/core/utils/eventBus.test.ts @@ -4,7 +4,7 @@ import { eventBus } from "@core/utils/eventBus.ts"; describe("EventBus", () => { beforeEach(() => { // Reset event listeners before each test - eventBus.listeners = {}; + eventBus.offAll(); }); it("should register an event listener and trigger it on emit", () => { diff --git a/src/core/utils/eventBus.ts b/src/core/utils/eventBus.ts index 618ab5a6..75c48d8c 100644 --- a/src/core/utils/eventBus.ts +++ b/src/core/utils/eventBus.ts @@ -34,6 +34,14 @@ class EventBus { } } + public offAll(event?: T): void { + if (event) { + this.listeners[event] = []; + } else { + this.listeners = {}; + } + } + public emit(event: T, data: EventMap[T]): void { if (!this.listeners[event]) return; diff --git a/src/core/utils/ip.test.ts b/src/core/utils/ip.test.ts index 2da62e57..6208e6d3 100644 --- a/src/core/utils/ip.test.ts +++ b/src/core/utils/ip.test.ts @@ -60,7 +60,7 @@ describe("IP Address Conversion Functions", () => { for (const ip of testIps) { const int = convertIpAddressToInt(ip); expect(int).not.toBeNull(); - if (int !== null) { + if (int !== null && typeof int === "number") { const convertedBack = convertIntToIpAddress(int); expect(convertedBack).toBe(ip); } diff --git a/src/core/utils/sort.ts b/src/core/utils/sort.ts new file mode 100644 index 00000000..2d1494f0 --- /dev/null +++ b/src/core/utils/sort.ts @@ -0,0 +1,18 @@ +export function intlSort( + arr: T[], + order: "asc" | "desc" = "asc", + locale: Intl.Locale, +): T[] { + const collator = new Intl.Collator(locale, { sensitivity: "base" }); + + return arr.sort((a, b) => { + const stringA = String(a); + const stringB = String(b); + + if (order === "asc") { + return collator.compare(stringA, stringB); + } else { + return collator.compare(stringB, stringA); + } + }); +} diff --git a/src/core/utils/test.tsx b/src/core/utils/test.tsx deleted file mode 100644 index cb9906ae..00000000 --- a/src/core/utils/test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { - createMemoryHistory, - createRouter, - Outlet, - RootRoute, - Route, - RouterProvider, -} from "@tanstack/react-router"; -import { render as rtlRender, RenderOptions } from "@testing-library/react"; -import type { FunctionComponent, ReactElement, ReactNode } from "react"; - -// a root route for the test router. -const rootRoute = new RootRoute({ - component: () => ( - <> - - - ), -}); - -interface CustomRenderOptions extends Omit { - initialEntries?: string[]; - ui?: ReactElement; -} - -let currentRouter: ReturnType | null = null; - -/** - * Custom render function for testing components that need TanStack Router context. - * @param ui The main ReactElement to render (your component under test). - * @param options Custom render options including initialEntries for the router. - * @returns An object containing the testing-library render result and the router instance. - */ -const customRender = ( - ui: ReactElement, - options: CustomRenderOptions = {}, -) => { - const { initialEntries = ["/"], ...renderOptions } = options; - - // A specific route that renders the component under test (ui). - // It defaults to the first path in initialEntries or '/'. - const testComponentRoute = new Route({ - getParentRoute: () => rootRoute, - path: initialEntries[0] || "/", - component: () => ui, // The component passed to render will be the element for this route - }); - - const routeTree = rootRoute.addChildren([testComponentRoute]); - - const router = createRouter({ - history: createMemoryHistory({ initialEntries }), - routeTree, - // You can add default error components or other router options if needed for tests. - // defaultErrorComponent: ({ error }) =>
Test Error: {error.message}
, - }); - - currentRouter = router; // Store the router instance for access in tests - - const Wrapper: FunctionComponent<{ children?: ReactNode }> = ( - { children }, - ) => { - return ( - <> - - {children} - - ); - }; - - const renderResult = rtlRender(ui, { wrapper: Wrapper, ...renderOptions }); - - return { - ...renderResult, - router, - }; -}; - -export * from "@testing-library/react"; -export { customRender as render }; -export const getTestRouter = () => currentRouter; diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 4a43392f..f203dab3 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -35,7 +35,7 @@ i18next "default": ["en"], }, fallbackNS: ["common", "ui", "dialog"], - debug: import.meta.env.DEV, + debug: import.meta.env.MODE === "development", supportedLngs: supportedLanguages?.map((lang) => lang.code), ns: [ "channels", diff --git a/src/i18n/locales/en/commandPalette.json b/src/i18n/locales/en/commandPalette.json index 7b82e97b..1eed8987 100644 --- a/src/i18n/locales/en/commandPalette.json +++ b/src/i18n/locales/en/commandPalette.json @@ -1,7 +1,7 @@ { "emptyState": "No results found.", "page": { - "title": "Command Palette" + "title": "Command Menu" }, "pinGroup": { "label": "Pin command group" diff --git a/src/i18n/locales/en/ui.json b/src/i18n/locales/en/ui.json index 6f0b6aa3..7e2e4708 100644 --- a/src/i18n/locales/en/ui.json +++ b/src/i18n/locales/en/ui.json @@ -80,6 +80,12 @@ }, "showPassword": { "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" } }, "general": { diff --git a/src/index.css b/src/index.css index 1ae593b4..56103edb 100644 --- a/src/index.css +++ b/src/index.css @@ -3,6 +3,10 @@ @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)); +@view-transition { + navigation: auto; +} + @theme { --font-mono: Cascadia Code, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, diff --git a/src/pages/Dashboard/index.tsx b/src/pages/Dashboard/index.tsx index 69cfa2e2..6afc4546 100644 --- a/src/pages/Dashboard/index.tsx +++ b/src/pages/Dashboard/index.tsx @@ -4,14 +4,7 @@ import { useDeviceStore } from "@core/stores/deviceStore.ts"; import { Button } from "@components/UI/Button.tsx"; import { Separator } from "@components/UI/Seperator.tsx"; import { Subtle } from "@components/UI/Typography/Subtle.tsx"; -import { - BluetoothIcon, - ListPlusIcon, - NetworkIcon, - PlusIcon, - UsbIcon, - UsersIcon, -} from "lucide-react"; +import { ListPlusIcon, PlusIcon, UsersIcon } from "lucide-react"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import LanguageSwitcher from "@components/LanguageSwitcher.tsx"; @@ -60,32 +53,6 @@ export const Dashboard = () => { ?.longName ?? t("unknown.shortName")}

-
- {device.connection?.connType === "ble" && ( - <> - - {t( - "dashboard.connectionType_ble", - )} - - )} - {device.connection?.connType === "serial" && ( - <> - - {t( - "dashboard.connectionType_serial", - )} - - )} - {device.connection?.connType === "http" && ( - <> - - {t( - "dashboard.connectionType_network", - )} - - )} -
{ {t("dashboard.noDevicesTitle")} - {/* */} {t("dashboard.noDevicesDescription")} diff --git a/src/pages/Messages.test.tsx b/src/pages/Messages.test.tsx deleted file mode 100644 index 46fc0115..00000000 --- a/src/pages/Messages.test.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { fireEvent, render, screen } from "@testing-library/react"; -import { MessagesPage } from "./Messages.tsx"; -import { useDevice } from "../core/stores/deviceStore.ts"; -import { Protobuf } from "@meshtastic/core"; - -vi.mock("../core/stores/deviceStore", () => ({ - useDevice: vi.fn(), -})); - -const mockUseDevice = { - channels: new Map([ - [0, { - index: 0, - settings: { name: "Primary" }, - role: Protobuf.Channel.Channel_Role.PRIMARY, - }], - ]), - nodes: new Map([ - [0, { - num: 0, - user: { longName: "Test Node 0", shortName: "TN0", publicKey: "0000" }, - }], - [1111, { - num: 1111, - user: { longName: "Test Node 1", shortName: "TN1", publicKey: "12345" }, - }], - [2222, { - num: 2222, - user: { longName: "Test Node 2", shortName: "TN2", publicKey: "67890" }, - }], - [3333, { - num: 3333, - user: { longName: "Test Node 3", shortName: "TN3", publicKey: "11111" }, - }], - ]), - hardware: { myNodeNum: 1 }, - messages: { broadcast: new Map(), direct: new Map() }, - metadata: new Map(), - unreadCounts: new Map([[1111, 3], [2222, 10]]), - resetUnread: vi.fn(), - hasNodeError: vi.fn(), -}; - -describe.skip("Messages Page", () => { - beforeEach(() => { - vi.mocked(useDevice).mockReturnValue(mockUseDevice); - }); - - it("sorts unreads to the top", () => { - render(); - const buttonOrder = screen.getAllByRole("button").filter((b) => - b.textContent.includes("Test Node") - ); - expect(buttonOrder[0].textContent).toContain("TN2Test Node 210"); - expect(buttonOrder[1].textContent).toContain("TN1Test Node 13"); - expect(buttonOrder[2].textContent).toContain("TN0Test Node 0"); - expect(buttonOrder[3].textContent).toContain("TN3Test Node 3"); - }); - - it("updates unread when active chat changes", () => { - render(); - const nodeButton = - screen.getAllByRole("button").filter((b) => - b.textContent.includes("TN1Test Node 13") - )[0]; - fireEvent.click(nodeButton); - expect(mockUseDevice.resetUnread).toHaveBeenCalledWith(1111, 0); - }); - - it("does not update the incorrect node", () => { - render(); - const nodeButton = - screen.getAllByRole("button").filter((b) => - b.textContent.includes("TN1Test Node 1") - )[0]; - fireEvent.click(nodeButton); - expect(mockUseDevice.resetUnread).toHaveBeenCalledWith(1111, 0); - expect(mockUseDevice.unreadCounts.get(2222)).toBe(10); - }); -}); diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 7e58d9ab..6a13fb35 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -28,9 +28,19 @@ import { Input } from "@components/UI/Input.tsx"; import { randId } from "@core/utils/randId.ts"; import { useTranslation } from "react-i18next"; import { useNavigate, useParams } from "@tanstack/react-router"; +import { messagesWithParamsRoute } from "@app/routes.tsx"; type NodeInfoWithUnread = Protobuf.Mesh.NodeInfo & { unreadCount: number }; +function SelectMessageChat() { + const { t } = useTranslation("messages"); + return ( +
+ {t("selectChatPrompt.text", { ns: "messages" })} +
+ ); +} + export const MessagesPage = () => { const { channels, @@ -46,7 +56,9 @@ export const MessagesPage = () => { getMessages, setMessageState, } = useMessageStore(); - const params = useParams({ from: "", shouldThrow: false }); + + const { type, chatId } = useParams({ from: messagesWithParamsRoute.id }); + const navigate = useNavigate(); const { toast } = useToast(); const { isCollapsed } = useSidebar(); @@ -54,34 +66,33 @@ export const MessagesPage = () => { const { t } = useTranslation(["messages", "channels", "ui"]); const deferredSearch = useDeferredValue(searchTerm); - const chatType = params.type === "direct" + const navigateToChat = useCallback((type: MessageType, id: string) => { + const typeParam = type === MessageType.Direct ? "direct" : "broadcast"; + navigate({ to: `/messages/${typeParam}/${id}` }); + }, [navigate]); + + const chatType = type === "direct" ? MessageType.Direct - : params.type === "broadcast" - ? MessageType.Broadcast - : undefined; - const activeChat = params.chatId ? Number(params.chatId) : undefined; + : MessageType.Broadcast; + const numericChatId = Number(chatId); const allChannels = Array.from(channels.values()); const filteredChannels = allChannels.filter( (ch) => ch.role !== Protobuf.Channel.Channel_Role.DISABLED, ); - const currentChannel = channels.get(activeChat); - const otherNode = getNode(activeChat); - - const isDirect = chatType === MessageType.Direct; - const isBroadcast = chatType === MessageType.Broadcast; - - const navigateToChat = useCallback((type: MessageType, chatId: number) => { - const typeParam = type === MessageType.Direct ? "direct" : "broadcast"; - navigate({ to: `/messages/${typeParam}/${chatId}` }); - }, [navigate]); useEffect(() => { - if (!params.type && !params.chatId && filteredChannels.length > 0) { + if (!type && !chatId && filteredChannels.length > 0) { const defaultChannel = filteredChannels[0]; - navigateToChat(MessageType.Broadcast, defaultChannel.index); + navigateToChat(MessageType.Broadcast, defaultChannel.index.toString()); } - }, [params.type, params.chatId, filteredChannels, navigateToChat]); + }, [type, chatId, filteredChannels, navigateToChat]); + + const currentChannel = channels.get(numericChatId); + const otherNode = getNode(numericChatId); + + const isDirect = chatType === MessageType.Direct; + const isBroadcast = chatType === MessageType.Broadcast; const filteredNodes = (): NodeInfoWithUnread[] => { const lowerCaseSearchTerm = deferredSearch.toLowerCase(); @@ -104,12 +115,8 @@ export const MessagesPage = () => { }; const sendText = useCallback(async (message: string) => { - const isDirect = chatType === MessageType.Direct; - const toValue = isDirect ? activeChat : MessageType.Broadcast; - - const channelValue = isDirect - ? Types.ChannelNumber.Primary - : activeChat ?? 0; + const toValue = isDirect ? numericChatId : MessageType.Broadcast; + const channelValue = isDirect ? Types.ChannelNumber.Primary : numericChatId; let messageId: number | undefined; @@ -123,16 +130,16 @@ export const MessagesPage = () => { if (messageId !== undefined) { if (chatType === MessageType.Broadcast) { setMessageState({ - type: chatType, + type: MessageType.Broadcast, channelId: channelValue, messageId, newState: MessageState.Ack, }); } else { setMessageState({ - type: chatType, + type: MessageType.Direct, nodeA: getMyNodeNum(), - nodeB: activeChat, + nodeB: numericChatId, messageId, newState: MessageState.Ack, }); @@ -145,23 +152,29 @@ export const MessagesPage = () => { const failedId = messageId ?? randId(); if (chatType === MessageType.Broadcast) { setMessageState({ - type: chatType, + type: MessageType.Broadcast, channelId: channelValue, messageId: failedId, newState: MessageState.Failed, }); - } else { // MessageType.Direct - const failedId = messageId ?? randId(); + } else { setMessageState({ - type: chatType, + type: MessageType.Direct, nodeA: getMyNodeNum(), - nodeB: activeChat, + nodeB: numericChatId, messageId: failedId, newState: MessageState.Failed, }); } } - }, [activeChat, chatType, connection, getMyNodeNum, setMessageState]); + }, [ + numericChatId, + chatId, + chatType, + connection, + getMyNodeNum, + setMessageState, + ]); const renderChatContent = () => { switch (chatType) { @@ -170,7 +183,7 @@ export const MessagesPage = () => { ); @@ -180,16 +193,12 @@ export const MessagesPage = () => { messages={getMessages({ type: MessageType.Direct, nodeA: getMyNodeNum(), - nodeB: activeChat, + nodeB: numericChatId, }).reverse()} /> ); default: - return ( -
- {t("selectChatPrompt.text", { ns: "messages" })} -
- ); + return ; } }; @@ -210,10 +219,10 @@ export const MessagesPage = () => { index: channel.index, ns: "channels", }))} - active={activeChat === channel.index && + active={numericChatId === channel.index && chatType === MessageType.Broadcast} onClick={() => { - navigateToChat(MessageType.Broadcast, channel.index); + navigateToChat(MessageType.Broadcast, channel.index.toString()); resetUnread(channel.index); }} > @@ -228,11 +237,12 @@ export const MessagesPage = () => { ), [ filteredChannels, unreadCounts, - activeChat, + numericChatId, chatType, isCollapsed, navigateToChat, resetUnread, + t, ]); const rightSidebar = useMemo( @@ -262,10 +272,10 @@ export const MessagesPage = () => { label={node.user?.longName ?? t("unknown.shortName")} count={node.unreadCount > 0 ? node.unreadCount : undefined} - active={activeChat === node.num && + active={numericChatId === node.num && chatType === MessageType.Direct} onClick={() => { - navigateToChat(MessageType.Direct, node.num); + navigateToChat(MessageType.Direct, node.num.toString()); resetUnread(node.num); }} > @@ -285,11 +295,12 @@ export const MessagesPage = () => { [ filteredNodes, searchTerm, - activeChat, + numericChatId, chatType, navigateToChat, resetUnread, hasNodeError, + t, ], ); @@ -330,7 +341,7 @@ export const MessagesPage = () => { {(isBroadcast || isDirect) ? ( diff --git a/src/pages/Nodes.tsx b/src/pages/Nodes/index.tsx similarity index 54% rename from src/pages/Nodes.tsx rename to src/pages/Nodes/index.tsx index c349cde3..8400ca2a 100644 --- a/src/pages/Nodes.tsx +++ b/src/pages/Nodes/index.tsx @@ -3,7 +3,11 @@ import { TracerouteResponseDialog } from "@app/components/Dialog/TracerouteRespo import { Sidebar } from "@components/Sidebar.tsx"; import { Avatar } from "@components/UI/Avatar.tsx"; import { Mono } from "@components/generic/Mono.tsx"; -import { Table } from "@components/generic/Table/index.tsx"; +import { + type DataRow, + type Heading, + Table, +} from "@components/generic/Table/index.tsx"; import { TimeAgo } from "@components/generic/TimeAgo.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { useAppStore } from "@core/stores/appStore.ts"; @@ -93,6 +97,123 @@ const NodesPage = (): JSX.Element => { setDialogOpen("nodeDetails", true); } + const tableHeadings: Heading[] = [ + { title: "", sortable: false }, + { title: t("nodesTable.headings.longName"), sortable: true }, + { title: t("nodesTable.headings.connection"), sortable: true }, + { title: t("nodesTable.headings.lastHeard"), sortable: true }, + { title: t("nodesTable.headings.encryption"), sortable: false }, + { title: t("unit.snr"), sortable: true }, + { title: t("nodesTable.headings.model"), sortable: true }, + { title: t("nodesTable.headings.macAddress"), sortable: true }, + ]; + + const tableRows: DataRow[] = filteredNodes.map((node) => { + const macAddress = base16 + .stringify(node.user?.macaddr ?? []) + .match(/.{1,2}/g) + ?.join(":") ?? t("unknown.shortName"); + + return { + id: node.num, + isFavorite: node.isFavorite, + cells: [ + { + content: ( + + ), + sortValue: node.user?.shortName ?? "", // Non-sortable column + }, + { + content: ( +

handleNodeInfoDialog(node.num)} + onKeyUp={(evt) => { + evt.key === "Enter" && handleNodeInfoDialog(node.num); + }} + className="cursor-pointer underline ml-2 whitespace-break-spaces" + tabIndex={0} + role="button" + > + {node.user?.longName ?? numberToHexUnpadded(node.num)} +

+ ), + sortValue: node.user?.longName ?? numberToHexUnpadded(node.num), + }, + { + content: ( + + {node.hopsAway !== undefined + ? node?.viaMqtt === false && node.hopsAway === 0 + ? t("nodesTable.connectionStatus.direct") + : `${node.hopsAway?.toString()} ${ + node.hopsAway ?? 0 > 1 + ? t("unit.hop.plural") + : t("unit.hops_one") + } ${t("nodesTable.connectionStatus.away")}` + : t("nodesTable.connectionStatus.unknown")} + {node?.viaMqtt === true + ? t("nodesTable.connectionStatus.viaMqtt") + : ""} + + ), + sortValue: node.hopsAway ?? Number.MAX_SAFE_INTEGER, + }, + { + content: ( + + {node.lastHeard === 0 + ?

{t("nodesTable.lastHeardStatus.never")}

+ : } +
+ ), + sortValue: node.lastHeard, + }, + { + content: ( + + {node.user?.publicKey && node.user?.publicKey.length > 0 + ? + : } + + ), + sortValue: "", // Non-sortable column + }, + { + content: ( + + {node.snr} + {t("unit.dbm")}/ + {Math.min( + Math.max((node.snr + 10) * 5, 0), + 100, + )}%/{/* Percentage */} + {(node.snr + 10) * 5} + {t("unit.raw")} + + ), + sortValue: node.snr, + }, + { + content: ( + + {Protobuf.Mesh.HardwareModel[node.user?.hwModel ?? 0]} + + ), + sortValue: Protobuf.Mesh.HardwareModel[node.user?.hwModel ?? 0], + }, + { + content: {macAddress}, + sortValue: macAddress, + }, + ], + }; + }); + return ( <> {
[ -
- -
, -

handleNodeInfoDialog(node.num)} - onKeyUp={(evt) => { - evt.key === "Enter" && handleNodeInfoDialog(node.num); - }} - className="cursor-pointer underline ml-2 whitespace-break-spaces" - tabIndex={0} - role="button" - > - {node.user?.longName ?? numberToHexUnpadded(node.num)} -

, - - {node.hopsAway !== undefined - ? node?.viaMqtt === false && node.hopsAway === 0 - ? t("nodesTable.connectionStatus.direct") - : `${node.hopsAway?.toString()} ${ - node.hopsAway ?? 0 > 1 - ? t("unit.hop.plural") - : t("unit.hops_one") - } ${t("nodesTable.connectionStatus.away")}` - : t("nodesTable.connectionStatus.unknown")} - {node?.viaMqtt === true - ? t("nodesTable.connectionStatus.viaMqtt") - : ""} - , - - {node.lastHeard === 0 - ?

{t("nodesTable.lastHeardStatus.never")}

- : } -
, - - {node.user?.publicKey && node.user?.publicKey.length > 0 - ? - : } - , - - {node.snr} - {t("unit.dbm")}/ - {Math.min( - Math.max((node.snr + 10) * 5, 0), - 100, - )}%/{/* Percentage */} - {(node.snr + 10) * 5} - {t("unit.raw")} - , - - {Protobuf.Mesh.HardwareModel[node.user?.hwModel ?? 0]} - , - - {base16 - .stringify(node.user?.macaddr ?? []) - .match(/.{1,2}/g) - ?.join(":") ?? t("unknown.shortName")} - , - ])} + headings={tableHeadings} + rows={tableRows} /> () - -/* ROUTE_MANIFEST_START -{ - "routes": { - "__root__": { - "filePath": "__root.tsx", - "children": [] - } - } -} -ROUTE_MANIFEST_END */ diff --git a/src/routes.tsx b/src/routes.tsx index f936fd12..6cdbb7da 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -4,10 +4,11 @@ import MessagesPage from "@pages/Messages.tsx"; import MapPage from "@pages/Map/index.tsx"; import ConfigPage from "@pages/Config/index.tsx"; import ChannelsPage from "@pages/Channels.tsx"; -import NodesPage from "@pages/Nodes.tsx"; +import NodesPage from "@pages/Nodes/index.tsx"; import { createRootRoute } from "@tanstack/react-router"; import { App } from "./App.tsx"; import { DialogManager } from "@components/Dialog/DialogManager.tsx"; +import { z } from "zod"; const rootRoute = createRootRoute({ component: App, @@ -27,12 +28,42 @@ const messagesRoute = createRoute({ getParentRoute: () => rootRoute, path: "/messages", component: MessagesPage, + beforeLoad: ({ params }) => { + const DEFAULT_CHANNEL = 0; + + if (Object.values(params).length === 0) { + throw redirect({ + to: `/messages/broadcast/${DEFAULT_CHANNEL}`, + replace: true, + }); + } + }, +}); + +const chatIdSchema = z.string().refine((val) => { + const num = Number(val); + if (isNaN(num) || !Number.isInteger(num)) { + return false; + } + + const isChannelId = num >= 0 && num <= 10; + const isNodeId = num >= 1000000000 && num <= 9999999999; + + return isChannelId || isNodeId; +}, { + message: "Chat ID must be a channel (0-10) or a valid node ID.", }); -const messagesWithParamsRoute = createRoute({ +export const messagesWithParamsRoute = createRoute({ getParentRoute: () => rootRoute, path: "/messages/$type/$chatId", component: MessagesPage, + parseParams: (params) => ({ + type: z.enum(["direct", "broadcast"], { + errorMap: () => ({ message: 'Type must be "direct" or "broadcast".' }), + }).parse(params.type), + chatId: chatIdSchema.parse(params.chatId), + }), }); const mapRoute = createRoute({ diff --git a/src/tests/setupTests.ts b/src/tests/setup.ts similarity index 100% rename from src/tests/setupTests.ts rename to src/tests/setup.ts diff --git a/src/tests/test-utils.tsx b/src/tests/test-utils.tsx new file mode 100644 index 00000000..e28d5a11 --- /dev/null +++ b/src/tests/test-utils.tsx @@ -0,0 +1,37 @@ +import { ReactElement } from "react"; +import { render, RenderOptions } from "@testing-library/react"; +import { + createMemoryHistory, + createRouter, + RouterProvider, +} from "@tanstack/react-router"; +import "../i18n/config.ts"; +import { routeTree } from "../routeTree.gen.ts"; + +import { DeviceWrapper } from "@app/DeviceWrapper.tsx"; + +const Providers = () => { + const memoryHistory = createMemoryHistory({ + initialEntries: ["/"], + }); + + const router = createRouter({ + routeTree, + history: memoryHistory, + }); + + return ( + + + + ); +}; + +const renderWithProviders = ( + ui: ReactElement, + options?: Omit, +) => render(ui, { wrapper: Providers, ...options }); + +export * from "@testing-library/react"; + +export { renderWithProviders as render }; diff --git a/vite-env.d.ts b/vite-env.d.ts new file mode 100644 index 00000000..484e03a4 --- /dev/null +++ b/vite-env.d.ts @@ -0,0 +1,11 @@ +/// + +interface ImportMetaEnv { + readonly env: { + readonly VITE_COMMIT_HASH: string; + }; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/vite.config.ts b/vite.config.ts index 05daf0e3..83bba01f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -32,9 +32,9 @@ export default defineConfig({ targets: [ { src: "src/i18n/locales/**/*", - dest: "src/i18n/locales" - } - ] + dest: "src/i18n/locales", + }, + ], }), ], define: { diff --git a/vitest.config.ts b/vitest.config.ts index 537096e0..ec6d3d71 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,6 +3,8 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vitest/config"; import { enableMapSet } from "immer"; +import process from "node:process"; + enableMapSet(); export default defineConfig({ plugins: [ @@ -25,6 +27,6 @@ export default defineConfig({ restoreMocks: true, root: path.resolve(process.cwd(), "./src"), include: ["**/*.{test,spec}.{ts,tsx}"], - setupFiles: ["./src/tests/setupTests.ts", "./src/core/utils/test.tsx"], + setupFiles: ["./src/tests/setup.ts"], }, }); From 48862141dcd6ffc1bc735ef92414e41ceb04d91b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 20:10:08 -0400 Subject: [PATCH 04/37] chore(deps): bump tj-actions/changed-files in /.github/workflows (#650) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 44 to 46. - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/v44...v46) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-version: '46' dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 29451318..18c727b8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -33,7 +33,7 @@ jobs: - name: Get changed files id: changed-files - uses: tj-actions/changed-files@v44 + uses: tj-actions/changed-files@v46 with: files: | **/*.ts From 78e1d1f81a5fb06252545ee68855ffcf3d5b3bcb Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Thu, 12 Jun 2025 20:14:59 -0400 Subject: [PATCH 05/37] fix: updated mqtt description (#647) --- src/i18n/locales/en/moduleConfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i18n/locales/en/moduleConfig.json b/src/i18n/locales/en/moduleConfig.json index bca3468e..caacbe17 100644 --- a/src/i18n/locales/en/moduleConfig.json +++ b/src/i18n/locales/en/moduleConfig.json @@ -253,12 +253,12 @@ "description": "MQTT root topic to use for default/custom servers" }, "proxyToClientEnabled": { - "label": "Proxy to Client Enabled", - "description": "Use the client's internet connection for MQTT (feature only active in mobile apps)" + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." }, "mapReportingEnabled": { "label": "Map Reporting Enabled", - "description": "Enable or disable map reporting" + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." }, "mapReportSettings": { "publishIntervalSecs": { From 26d5c0a08a33cad9a5d6aa20fc1fb2e0ade32b42 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Thu, 12 Jun 2025 20:15:43 -0400 Subject: [PATCH 06/37] feat: added i18n translator & developer guides (#646) --- .github/pull_request_template.md | 3 +- CONTRIBUTING_I18N_DEVELOPER_GUIDE.md | 112 +++++++++++++++++++++++++++ CONTRIBUTING_TRANSLATIONS.md | 31 ++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 CONTRIBUTING_I18N_DEVELOPER_GUIDE.md create mode 100644 CONTRIBUTING_TRANSLATIONS.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c44eaa18..d3fe3f05 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -46,4 +46,5 @@ Check all that apply. If an item doesn't apply to your PR, you can leave it unch - [ ] Code follows project style guidelines - [ ] Documentation has been updated or added - [ ] Tests have been added or updated -- [ ] All i18n translation labels have been added/updated +- [ ] All i18n translation labels have been added (read + CONTRIBUTING_I18N_DEVELOPER_GUIDE.md for more details) diff --git a/CONTRIBUTING_I18N_DEVELOPER_GUIDE.md b/CONTRIBUTING_I18N_DEVELOPER_GUIDE.md new file mode 100644 index 00000000..0b900de6 --- /dev/null +++ b/CONTRIBUTING_I18N_DEVELOPER_GUIDE.md @@ -0,0 +1,112 @@ +# i18n Developer Guide + +When developing new components, all user-facing text must be added as an i18n +key and rendered using our translation functions. This ensures your UI can be +translated into multiple languages. + +## Adding New i18n Keys + +### Search Before Creating + +Before adding a new key, please perform a quick search to see if one that fits +your needs already exists. Many common labels like "Save," "Cancel," "Name," +"Description," "Loading...," or "Error" are likely already present, especially +in the common.json namespace. Reusing existing keys prevents duplication and +ensures consistency across the application. Using your code editor's search +function across the /src/i18n/locales/en/ directory is an effective way to do +this. + +### Key Naming and Structure Rules + +To maintain consistency and ease of use, please adhere to the following rules +when creating new keys in the JSON files. + +- **Keys are camelCase:** `exampleKey`, `anotherExampleKey`. +- **Avoid Deep Nesting:** One or two levels of nesting are acceptable for + grouping related keys (e.g., all labels for a specific menu). However, nesting + deeper than two levels should be avoided to maintain readability and ease of + use. + - **Good (1 level):** + ```json + "buttons": { + "save": "Save", + "cancel": "Cancel" + } + ``` + - **Acceptable (2 levels):** + ```json + "userMenu": { + "items": { + "profile": "Profile", + "settings": "Settings" + } + } + ``` + - **Avoid (3+ levels):** + ```json + "userMenu": { + "items": { + "actions": { + "viewProfile": "View Profile" + } + } + } + ``` +- **Organize for Retrieval, Not UI Layout:** Keys should be named logically for + easy retrieval, not to mirror the layout of your component. + +### Namespace Rules + +We use namespaces to organize keys. All source keys are added to the English +(`en`) files located at `/src/i18n/locales/en/`. Place your new keys in the +appropriate file based on these rules: + +- `common.json`: + - All button labels (`save`, `cancel`, `submit`, etc.). + - Any text that is repeated and used throughout the application (e.g., + "Loading...", "Error"). +- `ui.json`: + - Labels and text specific to a distinct UI element or view that isn't a + dialog or a config page. +- `dialog.json`: + - All text specific to modal dialogs (titles, body text, prompts). +- `messages.json`: + - Text specifically related to the messaging interface. +- `deviceConfig.json` & `moduleConfig.json`: + - Labels and descriptions for the settings on the Device and Module + configuration pages. + +## Using i18n Keys in Components + +We use the `useTranslation` hook from `react-i18next` to access the translation +function, `t`. + +### Default Namespaces + +Our i18next configuration has fallback namespaces configured which includes +`common`, `ui`, and `dialog`. This means you **do not** need to explicitly +specify these namespaces when calling the hook. The system will automatically +check these files for your key. + +For any keys in `common.json`, `ui.json`, or `dialog.json`, you can instantiate +the hook simply: + +```typescript +import { useTranslation } from "react-i18next"; + +// In your component +const { t } = useTranslation(["messages"]); + +// Usage +return

{t("someMessageLabel")}

; +``` + +You can also specify the namespace on a per-call basis using the options object. +This is useful if a component primarily uses a default namespace but needs a +single key from another. + +```typescript +const { t } = useTranslation(); + +return

{t("someMessageLabel", { ns: "messages" })}

; +``` diff --git a/CONTRIBUTING_TRANSLATIONS.md b/CONTRIBUTING_TRANSLATIONS.md new file mode 100644 index 00000000..66a7d646 --- /dev/null +++ b/CONTRIBUTING_TRANSLATIONS.md @@ -0,0 +1,31 @@ +# Contributing Translations + +Thank you for your interest in making the Meshtastic Web Client accessible to a +global audience! Your translation efforts are greatly appreciated. + +## Our Translation Platform: Crowdin + +We manage all our translations through a platform called +[Crowdin](https://crowdin.com/). This allows for a collaborative and streamlined +translation process. All translation work should be done on our Crowdin project, +not directly in the code repository via Pull Requests. + +### How to Get Started + +1. **Create a Crowdin Account:** If you don't already have one, sign up for a + free account on Crowdin. +2. **Join Our Project:** Please ask for a link to our specific Crowdin project + on the Meshtastic Discord. +3. **Request Translator Role:** Once you have an account, join the Meshtastic + Discord and notify an admin in the `#web` channel. They will grant you the + necessary permissions to start translating. +4. **Start Translating:** Once you have your role, you can begin translating the + source labels into your native language directly on the Crowdin platform. + +### Language Activation + +A new language will only be added to the web client and appear in the language +picker once its translation is 100% complete on Crowdin. The repository +maintainers will handle this process once the milestone is reached. + +Thank you for helping us bring Meshtastic to more users around the world! From 6cc69869042b5616dbffe12fe9f6c37850280b8c Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 16 Jun 2025 09:39:13 -0400 Subject: [PATCH 07/37] fix: remove service worker (#654) --- vite.config.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/vite.config.ts b/vite.config.ts index 83bba01f..dcccf7a0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,17 +17,17 @@ try { export default defineConfig({ plugins: [ react(), - VitePWA({ - registerType: "autoUpdate", - strategies: "generateSW", - devOptions: { - enabled: false, - }, - workbox: { - cleanupOutdatedCaches: true, - sourcemap: true, - }, - }), + // VitePWA({ + // registerType: "autoUpdate", + // strategies: "generateSW", + // devOptions: { + // enabled: true, + // }, + // workbox: { + // cleanupOutdatedCaches: true, + // sourcemap: true, + // }, + // }), viteStaticCopy({ targets: [ { From fad1b984bf3d76d49653c60381767a72a512f2d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 09:41:50 -0400 Subject: [PATCH 08/37] chore(i18n): New Crowdin Translations by GitHub Action (#653) Co-authored-by: Crowdin Bot --- src/i18n/locales/cs-CZ/channels.json | 69 ++++ src/i18n/locales/cs-CZ/commandPalette.json | 50 +++ src/i18n/locales/cs-CZ/common.json | 119 ++++++ src/i18n/locales/cs-CZ/dashboard.json | 12 + src/i18n/locales/cs-CZ/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/cs-CZ/dialog.json | 159 ++++++++ src/i18n/locales/cs-CZ/messages.json | 40 ++ src/i18n/locales/cs-CZ/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/cs-CZ/nodes.json | 51 +++ src/i18n/locales/cs-CZ/ui.json | 201 +++++++++ src/i18n/locales/de-DE/channels.json | 69 ++++ src/i18n/locales/de-DE/commandPalette.json | 50 +++ src/i18n/locales/de-DE/common.json | 119 ++++++ src/i18n/locales/de-DE/dashboard.json | 12 + src/i18n/locales/de-DE/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/de-DE/dialog.json | 159 ++++++++ src/i18n/locales/de-DE/messages.json | 40 ++ src/i18n/locales/de-DE/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/de-DE/nodes.json | 51 +++ src/i18n/locales/de-DE/ui.json | 201 +++++++++ src/i18n/locales/es-ES/channels.json | 69 ++++ src/i18n/locales/es-ES/commandPalette.json | 50 +++ src/i18n/locales/es-ES/common.json | 119 ++++++ src/i18n/locales/es-ES/dashboard.json | 12 + src/i18n/locales/es-ES/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/es-ES/dialog.json | 159 ++++++++ src/i18n/locales/es-ES/messages.json | 40 ++ src/i18n/locales/es-ES/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/es-ES/nodes.json | 51 +++ src/i18n/locales/es-ES/ui.json | 201 +++++++++ src/i18n/locales/fi-FI/channels.json | 69 ++++ src/i18n/locales/fi-FI/commandPalette.json | 50 +++ src/i18n/locales/fi-FI/common.json | 119 ++++++ src/i18n/locales/fi-FI/dashboard.json | 12 + src/i18n/locales/fi-FI/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/fi-FI/dialog.json | 159 ++++++++ src/i18n/locales/fi-FI/messages.json | 40 ++ src/i18n/locales/fi-FI/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/fi-FI/nodes.json | 51 +++ src/i18n/locales/fi-FI/ui.json | 201 +++++++++ src/i18n/locales/fr-FR/channels.json | 69 ++++ src/i18n/locales/fr-FR/commandPalette.json | 50 +++ src/i18n/locales/fr-FR/common.json | 119 ++++++ src/i18n/locales/fr-FR/dashboard.json | 12 + src/i18n/locales/fr-FR/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/fr-FR/dialog.json | 159 ++++++++ src/i18n/locales/fr-FR/messages.json | 40 ++ src/i18n/locales/fr-FR/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/fr-FR/nodes.json | 51 +++ src/i18n/locales/fr-FR/ui.json | 201 +++++++++ src/i18n/locales/it-IT/channels.json | 69 ++++ src/i18n/locales/it-IT/commandPalette.json | 50 +++ src/i18n/locales/it-IT/common.json | 119 ++++++ src/i18n/locales/it-IT/dashboard.json | 12 + src/i18n/locales/it-IT/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/it-IT/dialog.json | 159 ++++++++ src/i18n/locales/it-IT/messages.json | 40 ++ src/i18n/locales/it-IT/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/it-IT/nodes.json | 51 +++ src/i18n/locales/it-IT/ui.json | 201 +++++++++ src/i18n/locales/ja-JP/channels.json | 69 ++++ src/i18n/locales/ja-JP/commandPalette.json | 50 +++ src/i18n/locales/ja-JP/common.json | 119 ++++++ src/i18n/locales/ja-JP/dashboard.json | 12 + src/i18n/locales/ja-JP/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/ja-JP/dialog.json | 159 ++++++++ src/i18n/locales/ja-JP/messages.json | 40 ++ src/i18n/locales/ja-JP/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/ja-JP/nodes.json | 51 +++ src/i18n/locales/ja-JP/ui.json | 201 +++++++++ src/i18n/locales/nl-NL/channels.json | 69 ++++ src/i18n/locales/nl-NL/commandPalette.json | 50 +++ src/i18n/locales/nl-NL/common.json | 119 ++++++ src/i18n/locales/nl-NL/dashboard.json | 12 + src/i18n/locales/nl-NL/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/nl-NL/dialog.json | 159 ++++++++ src/i18n/locales/nl-NL/messages.json | 40 ++ src/i18n/locales/nl-NL/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/nl-NL/nodes.json | 51 +++ src/i18n/locales/nl-NL/ui.json | 201 +++++++++ src/i18n/locales/pt-PT/channels.json | 69 ++++ src/i18n/locales/pt-PT/commandPalette.json | 50 +++ src/i18n/locales/pt-PT/common.json | 119 ++++++ src/i18n/locales/pt-PT/dashboard.json | 12 + src/i18n/locales/pt-PT/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/pt-PT/dialog.json | 159 ++++++++ src/i18n/locales/pt-PT/messages.json | 40 ++ src/i18n/locales/pt-PT/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/pt-PT/nodes.json | 51 +++ src/i18n/locales/pt-PT/ui.json | 201 +++++++++ src/i18n/locales/sv-SE/channels.json | 69 ++++ src/i18n/locales/sv-SE/commandPalette.json | 50 +++ src/i18n/locales/sv-SE/common.json | 119 ++++++ src/i18n/locales/sv-SE/dashboard.json | 12 + src/i18n/locales/sv-SE/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/sv-SE/dialog.json | 159 ++++++++ src/i18n/locales/sv-SE/messages.json | 40 ++ src/i18n/locales/sv-SE/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/sv-SE/nodes.json | 51 +++ src/i18n/locales/sv-SE/ui.json | 201 +++++++++ src/i18n/locales/tr-TR/channels.json | 69 ++++ src/i18n/locales/tr-TR/commandPalette.json | 50 +++ src/i18n/locales/tr-TR/common.json | 119 ++++++ src/i18n/locales/tr-TR/dashboard.json | 12 + src/i18n/locales/tr-TR/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/tr-TR/dialog.json | 159 ++++++++ src/i18n/locales/tr-TR/messages.json | 40 ++ src/i18n/locales/tr-TR/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/tr-TR/nodes.json | 51 +++ src/i18n/locales/tr-TR/ui.json | 201 +++++++++ src/i18n/locales/uk-UA/channels.json | 69 ++++ src/i18n/locales/uk-UA/commandPalette.json | 50 +++ src/i18n/locales/uk-UA/common.json | 119 ++++++ src/i18n/locales/uk-UA/dashboard.json | 12 + src/i18n/locales/uk-UA/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/uk-UA/dialog.json | 159 ++++++++ src/i18n/locales/uk-UA/messages.json | 40 ++ src/i18n/locales/uk-UA/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/uk-UA/nodes.json | 51 +++ src/i18n/locales/uk-UA/ui.json | 201 +++++++++ src/i18n/locales/zh-CN/channels.json | 69 ++++ src/i18n/locales/zh-CN/commandPalette.json | 50 +++ src/i18n/locales/zh-CN/common.json | 119 ++++++ src/i18n/locales/zh-CN/dashboard.json | 12 + src/i18n/locales/zh-CN/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/zh-CN/dialog.json | 159 ++++++++ src/i18n/locales/zh-CN/messages.json | 40 ++ src/i18n/locales/zh-CN/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/zh-CN/nodes.json | 51 +++ src/i18n/locales/zh-CN/ui.json | 201 +++++++++ src/i18n/locales/zh-TW/channels.json | 69 ++++ src/i18n/locales/zh-TW/commandPalette.json | 50 +++ src/i18n/locales/zh-TW/common.json | 119 ++++++ src/i18n/locales/zh-TW/dashboard.json | 12 + src/i18n/locales/zh-TW/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/zh-TW/dialog.json | 159 ++++++++ src/i18n/locales/zh-TW/messages.json | 40 ++ src/i18n/locales/zh-TW/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/zh-TW/nodes.json | 51 +++ src/i18n/locales/zh-TW/ui.json | 201 +++++++++ 140 files changed, 22078 insertions(+) create mode 100644 src/i18n/locales/cs-CZ/channels.json create mode 100644 src/i18n/locales/cs-CZ/commandPalette.json create mode 100644 src/i18n/locales/cs-CZ/common.json create mode 100644 src/i18n/locales/cs-CZ/dashboard.json create mode 100644 src/i18n/locales/cs-CZ/deviceConfig.json create mode 100644 src/i18n/locales/cs-CZ/dialog.json create mode 100644 src/i18n/locales/cs-CZ/messages.json create mode 100644 src/i18n/locales/cs-CZ/moduleConfig.json create mode 100644 src/i18n/locales/cs-CZ/nodes.json create mode 100644 src/i18n/locales/cs-CZ/ui.json create mode 100644 src/i18n/locales/de-DE/channels.json create mode 100644 src/i18n/locales/de-DE/commandPalette.json create mode 100644 src/i18n/locales/de-DE/common.json create mode 100644 src/i18n/locales/de-DE/dashboard.json create mode 100644 src/i18n/locales/de-DE/deviceConfig.json create mode 100644 src/i18n/locales/de-DE/dialog.json create mode 100644 src/i18n/locales/de-DE/messages.json create mode 100644 src/i18n/locales/de-DE/moduleConfig.json create mode 100644 src/i18n/locales/de-DE/nodes.json create mode 100644 src/i18n/locales/de-DE/ui.json create mode 100644 src/i18n/locales/es-ES/channels.json create mode 100644 src/i18n/locales/es-ES/commandPalette.json create mode 100644 src/i18n/locales/es-ES/common.json create mode 100644 src/i18n/locales/es-ES/dashboard.json create mode 100644 src/i18n/locales/es-ES/deviceConfig.json create mode 100644 src/i18n/locales/es-ES/dialog.json create mode 100644 src/i18n/locales/es-ES/messages.json create mode 100644 src/i18n/locales/es-ES/moduleConfig.json create mode 100644 src/i18n/locales/es-ES/nodes.json create mode 100644 src/i18n/locales/es-ES/ui.json create mode 100644 src/i18n/locales/fi-FI/channels.json create mode 100644 src/i18n/locales/fi-FI/commandPalette.json create mode 100644 src/i18n/locales/fi-FI/common.json create mode 100644 src/i18n/locales/fi-FI/dashboard.json create mode 100644 src/i18n/locales/fi-FI/deviceConfig.json create mode 100644 src/i18n/locales/fi-FI/dialog.json create mode 100644 src/i18n/locales/fi-FI/messages.json create mode 100644 src/i18n/locales/fi-FI/moduleConfig.json create mode 100644 src/i18n/locales/fi-FI/nodes.json create mode 100644 src/i18n/locales/fi-FI/ui.json create mode 100644 src/i18n/locales/fr-FR/channels.json create mode 100644 src/i18n/locales/fr-FR/commandPalette.json create mode 100644 src/i18n/locales/fr-FR/common.json create mode 100644 src/i18n/locales/fr-FR/dashboard.json create mode 100644 src/i18n/locales/fr-FR/deviceConfig.json create mode 100644 src/i18n/locales/fr-FR/dialog.json create mode 100644 src/i18n/locales/fr-FR/messages.json create mode 100644 src/i18n/locales/fr-FR/moduleConfig.json create mode 100644 src/i18n/locales/fr-FR/nodes.json create mode 100644 src/i18n/locales/fr-FR/ui.json create mode 100644 src/i18n/locales/it-IT/channels.json create mode 100644 src/i18n/locales/it-IT/commandPalette.json create mode 100644 src/i18n/locales/it-IT/common.json create mode 100644 src/i18n/locales/it-IT/dashboard.json create mode 100644 src/i18n/locales/it-IT/deviceConfig.json create mode 100644 src/i18n/locales/it-IT/dialog.json create mode 100644 src/i18n/locales/it-IT/messages.json create mode 100644 src/i18n/locales/it-IT/moduleConfig.json create mode 100644 src/i18n/locales/it-IT/nodes.json create mode 100644 src/i18n/locales/it-IT/ui.json create mode 100644 src/i18n/locales/ja-JP/channels.json create mode 100644 src/i18n/locales/ja-JP/commandPalette.json create mode 100644 src/i18n/locales/ja-JP/common.json create mode 100644 src/i18n/locales/ja-JP/dashboard.json create mode 100644 src/i18n/locales/ja-JP/deviceConfig.json create mode 100644 src/i18n/locales/ja-JP/dialog.json create mode 100644 src/i18n/locales/ja-JP/messages.json create mode 100644 src/i18n/locales/ja-JP/moduleConfig.json create mode 100644 src/i18n/locales/ja-JP/nodes.json create mode 100644 src/i18n/locales/ja-JP/ui.json create mode 100644 src/i18n/locales/nl-NL/channels.json create mode 100644 src/i18n/locales/nl-NL/commandPalette.json create mode 100644 src/i18n/locales/nl-NL/common.json create mode 100644 src/i18n/locales/nl-NL/dashboard.json create mode 100644 src/i18n/locales/nl-NL/deviceConfig.json create mode 100644 src/i18n/locales/nl-NL/dialog.json create mode 100644 src/i18n/locales/nl-NL/messages.json create mode 100644 src/i18n/locales/nl-NL/moduleConfig.json create mode 100644 src/i18n/locales/nl-NL/nodes.json create mode 100644 src/i18n/locales/nl-NL/ui.json create mode 100644 src/i18n/locales/pt-PT/channels.json create mode 100644 src/i18n/locales/pt-PT/commandPalette.json create mode 100644 src/i18n/locales/pt-PT/common.json create mode 100644 src/i18n/locales/pt-PT/dashboard.json create mode 100644 src/i18n/locales/pt-PT/deviceConfig.json create mode 100644 src/i18n/locales/pt-PT/dialog.json create mode 100644 src/i18n/locales/pt-PT/messages.json create mode 100644 src/i18n/locales/pt-PT/moduleConfig.json create mode 100644 src/i18n/locales/pt-PT/nodes.json create mode 100644 src/i18n/locales/pt-PT/ui.json create mode 100644 src/i18n/locales/sv-SE/channels.json create mode 100644 src/i18n/locales/sv-SE/commandPalette.json create mode 100644 src/i18n/locales/sv-SE/common.json create mode 100644 src/i18n/locales/sv-SE/dashboard.json create mode 100644 src/i18n/locales/sv-SE/deviceConfig.json create mode 100644 src/i18n/locales/sv-SE/dialog.json create mode 100644 src/i18n/locales/sv-SE/messages.json create mode 100644 src/i18n/locales/sv-SE/moduleConfig.json create mode 100644 src/i18n/locales/sv-SE/nodes.json create mode 100644 src/i18n/locales/sv-SE/ui.json create mode 100644 src/i18n/locales/tr-TR/channels.json create mode 100644 src/i18n/locales/tr-TR/commandPalette.json create mode 100644 src/i18n/locales/tr-TR/common.json create mode 100644 src/i18n/locales/tr-TR/dashboard.json create mode 100644 src/i18n/locales/tr-TR/deviceConfig.json create mode 100644 src/i18n/locales/tr-TR/dialog.json create mode 100644 src/i18n/locales/tr-TR/messages.json create mode 100644 src/i18n/locales/tr-TR/moduleConfig.json create mode 100644 src/i18n/locales/tr-TR/nodes.json create mode 100644 src/i18n/locales/tr-TR/ui.json create mode 100644 src/i18n/locales/uk-UA/channels.json create mode 100644 src/i18n/locales/uk-UA/commandPalette.json create mode 100644 src/i18n/locales/uk-UA/common.json create mode 100644 src/i18n/locales/uk-UA/dashboard.json create mode 100644 src/i18n/locales/uk-UA/deviceConfig.json create mode 100644 src/i18n/locales/uk-UA/dialog.json create mode 100644 src/i18n/locales/uk-UA/messages.json create mode 100644 src/i18n/locales/uk-UA/moduleConfig.json create mode 100644 src/i18n/locales/uk-UA/nodes.json create mode 100644 src/i18n/locales/uk-UA/ui.json create mode 100644 src/i18n/locales/zh-CN/channels.json create mode 100644 src/i18n/locales/zh-CN/commandPalette.json create mode 100644 src/i18n/locales/zh-CN/common.json create mode 100644 src/i18n/locales/zh-CN/dashboard.json create mode 100644 src/i18n/locales/zh-CN/deviceConfig.json create mode 100644 src/i18n/locales/zh-CN/dialog.json create mode 100644 src/i18n/locales/zh-CN/messages.json create mode 100644 src/i18n/locales/zh-CN/moduleConfig.json create mode 100644 src/i18n/locales/zh-CN/nodes.json create mode 100644 src/i18n/locales/zh-CN/ui.json create mode 100644 src/i18n/locales/zh-TW/channels.json create mode 100644 src/i18n/locales/zh-TW/commandPalette.json create mode 100644 src/i18n/locales/zh-TW/common.json create mode 100644 src/i18n/locales/zh-TW/dashboard.json create mode 100644 src/i18n/locales/zh-TW/deviceConfig.json create mode 100644 src/i18n/locales/zh-TW/dialog.json create mode 100644 src/i18n/locales/zh-TW/messages.json create mode 100644 src/i18n/locales/zh-TW/moduleConfig.json create mode 100644 src/i18n/locales/zh-TW/nodes.json create mode 100644 src/i18n/locales/zh-TW/ui.json diff --git a/src/i18n/locales/cs-CZ/channels.json b/src/i18n/locales/cs-CZ/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/cs-CZ/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/cs-CZ/commandPalette.json b/src/i18n/locales/cs-CZ/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/cs-CZ/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/cs-CZ/common.json b/src/i18n/locales/cs-CZ/common.json new file mode 100644 index 00000000..dd918f3b --- /dev/null +++ b/src/i18n/locales/cs-CZ/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Použít", + "backupKey": "Backup Key", + "cancel": "Zrušit", + "clearMessages": "Clear Messages", + "close": "Zavřít", + "confirm": "Confirm", + "delete": "Smazat", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Zpráva", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Odstranit", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Uložit", + "scanQr": "Naskenovat QR kód", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/cs-CZ/dashboard.json b/src/i18n/locales/cs-CZ/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/cs-CZ/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/cs-CZ/deviceConfig.json b/src/i18n/locales/cs-CZ/deviceConfig.json new file mode 100644 index 00000000..6e5cb4e0 --- /dev/null +++ b/src/i18n/locales/cs-CZ/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Zařízení", + "tabDisplay": "Obrazovka", + "tabLora": "LoRa", + "tabNetwork": "Síť", + "tabPosition": "Pozice", + "tabPower": "Napájení", + "tabSecurity": "Zabezpečení" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Dvojité klepnutí jako stisk tlačítka" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX časové pásmo" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Režim opětovného vysílání" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Nastavení Bluetooth", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Povoleno" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Režim párování" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Šířka pásma" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignorovat MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Předvolba modemu" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK do MQTT" + }, + "overrideDutyCycle": { + "description": "Přepsat střídu", + "label": "Přepsat střídu" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Povoleno" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway/Brána" + }, + "ip": { + "description": "IP Address", + "label": "IP adresa" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Podsíť" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Povoleno" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Konfigurace" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Časová značka", + "unset": "Zrušit nastavení", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Povolit úsporný režim" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Nastavení napájení" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Soukromý klíč" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Veřejný klíč" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/cs-CZ/dialog.json b/src/i18n/locales/cs-CZ/dialog.json new file mode 100644 index 00000000..cf2c0735 --- /dev/null +++ b/src/i18n/locales/cs-CZ/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Sériová komunikace", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Zpráva", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Napětí", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Jste si jistý?" + } +} diff --git a/src/i18n/locales/cs-CZ/messages.json b/src/i18n/locales/cs-CZ/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/cs-CZ/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/cs-CZ/moduleConfig.json b/src/i18n/locales/cs-CZ/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/cs-CZ/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/cs-CZ/nodes.json b/src/i18n/locales/cs-CZ/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/cs-CZ/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/cs-CZ/ui.json b/src/i18n/locales/cs-CZ/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/cs-CZ/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/de-DE/channels.json b/src/i18n/locales/de-DE/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/de-DE/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/de-DE/commandPalette.json b/src/i18n/locales/de-DE/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/de-DE/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/de-DE/common.json b/src/i18n/locales/de-DE/common.json new file mode 100644 index 00000000..6ee355ad --- /dev/null +++ b/src/i18n/locales/de-DE/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Anwenden", + "backupKey": "Schlüssel sichern", + "cancel": "Abbrechen", + "clearMessages": "Nachrichten löschen", + "close": "Schließen", + "confirm": "Bestätigen", + "delete": "Löschen", + "dismiss": "Tastatur ausblenden", + "download": "Herunterladen", + "export": "Exportieren", + "generate": "Erzeugen", + "regenerate": "Neu erzeugen", + "import": "Importieren", + "message": "Nachricht", + "now": "Jetzt", + "ok": "Ok", + "print": "Drucken", + "rebootOtaNow": "Neustart in den OTA Modus", + "remove": "Entfernen", + "requestNewKeys": "Neue Schlüssel anfordern", + "requestPosition": "Standort anfordern", + "reset": "Zurücksetzen", + "save": "Speichern", + "scanQr": "QR Code scannen", + "traceRoute": "Route verfolgen" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web-Applikation" + }, + "loading": "Wird geladen...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Sprung", + "plural": "Sprünge" + }, + "hopsAway": { + "one": "{{count}} Sprung entfernt", + "plural": "{{count}} Sprünge entfernt", + "unknown": "Sprungweite unbekannt" + }, + "megahertz": "MHz", + "raw": "Einheitslos", + "meter": { + "one": "Meter", + "plural": "Meter", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/de-DE/dashboard.json b/src/i18n/locales/de-DE/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/de-DE/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/de-DE/deviceConfig.json b/src/i18n/locales/de-DE/deviceConfig.json new file mode 100644 index 00000000..9bd24e95 --- /dev/null +++ b/src/i18n/locales/de-DE/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Einstellungen", + "tabBluetooth": "Bluetooth", + "tabDevice": "Gerät", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Netzwerk", + "tabPosition": "Standort", + "tabPower": "Leistung", + "tabSecurity": "Sicherheit" + }, + "sidebar": { + "label": "Module" + }, + "device": { + "title": "Geräteeinstellungen", + "description": "Einstellungen für dieses Gerät", + "buttonPin": { + "description": "GPIO für Taste überschreiben", + "label": "GPIO Taste" + }, + "buzzerPin": { + "description": "GPIO für Summer überschreiben", + "label": "GPIO Summer" + }, + "disableTripleClick": { + "description": "Dreifachklicken deaktivieren", + "label": "Dreifachklicken deaktivieren" + }, + "doubleTapAsButtonPress": { + "description": "Doppeltes Tippen als Taste verwenden", + "label": "Doppelklick als Tastendruck" + }, + "ledHeartbeatDisabled": { + "description": "Die Herzschlag LED deaktivieren", + "label": "Herzschlag LED deaktivieren" + }, + "nodeInfoBroadcastInterval": { + "description": "Häufigkeit der Übertragung von Knoteninformationen", + "label": "Knoteninfo Übertragungsintervall" + }, + "posixTimezone": { + "description": "Zeichenfolge der POSIX Zeitzone für dieses Gerät", + "label": "POSIX Zeitzone" + }, + "rebroadcastMode": { + "description": "Wie Weiterleitungen behandelt werden", + "label": "Weiterleitungsmodus" + }, + "role": { + "description": "In welche Rolle das Gerät im Netz arbeitet", + "label": "Rolle" + } + }, + "bluetooth": { + "title": "Bluetooth Einstellungen", + "description": "Einstellungen für das Bluetooth Modul", + "note": "Hinweis: Einige Geräte (ESP32) können nicht gleichzeitig Bluetooth und WLAN verwenden.", + "enabled": { + "description": "Bluetooth aktivieren oder deaktivieren", + "label": "Aktiviert" + }, + "pairingMode": { + "description": "PIN Nummer Auswahlverhalten", + "label": "Kopplungsmodus" + }, + "pin": { + "description": "PIN Nummer zum Verbinden verwenden", + "label": "PIN Nummer" + } + }, + "display": { + "description": "Einstellungen für die Geräteanzeige", + "title": "Anzeigeeinstellungen", + "headingBold": { + "description": "Überschrifttext fett darstellen", + "label": "Fette Überschrift" + }, + "carouselDelay": { + "description": "Bestimmt wie schnell die Fenster durch gewechselt werden", + "label": "Karussellverzögerung" + }, + "compassNorthTop": { + "description": "Norden im Kompass immer oben anzeigen", + "label": "Kompass Norden oben" + }, + "displayMode": { + "description": "Variante des Anzeigelayout", + "label": "Anzeigemodus" + }, + "displayUnits": { + "description": "Zeige metrische oder imperiale Einheiten", + "label": "Anzeigeeinheiten" + }, + "flipScreen": { + "description": "Anzeige um 180 Grad drehen", + "label": "Anzeige drehen" + }, + "gpsDisplayUnits": { + "description": "Anzeigeformat der Koordinaten", + "label": "GPS Anzeigeformat" + }, + "oledType": { + "description": "Art des OLED Anzeige, die an dem Gerät angeschlossen ist", + "label": "OLED Typ" + }, + "screenTimeout": { + "description": "Anzeige nach dieser Zeit automatisch ausschalten", + "label": "Anzeigeabschaltung" + }, + "twelveHourClock": { + "description": "12-Stunden Format benutzen", + "label": "12-Stunden Uhr" + }, + "wakeOnTapOrMotion": { + "description": "Gerät durch Tippen oder Bewegung aufwecken", + "label": "Aufwachen durch Tippen oder Bewegung" + } + }, + "lora": { + "title": "Netzeinstellungen", + "description": "Einstellungen für das LoRa Netz", + "bandwidth": { + "description": "Kanalbandbreite in MHz", + "label": "Bandbreite" + }, + "boostedRxGain": { + "description": "Erhöhte Empfangsverstärkung", + "label": "Erhöhte Empfangsverstärkung" + }, + "codingRate": { + "description": "Kodierrate", + "label": "Fehlerkorrektur" + }, + "frequencyOffset": { + "description": "Frequenzversatz zur Kalibrierung von Oszillatorfehlern", + "label": "Frequenzversatz" + }, + "frequencySlot": { + "description": "LoRa Frequenzschlitz", + "label": "Frequenzschlitz" + }, + "hopLimit": { + "description": "Maximale Sprungweite", + "label": "Sprungweite" + }, + "ignoreMqtt": { + "description": "MQTT Nachrichten nicht über das Netz weiterleiten", + "label": "MQTT ignorieren" + }, + "modemPreset": { + "description": "Modem Voreinstellung die verwendet wird", + "label": "Modem Voreinstellungen" + }, + "okToMqtt": { + "description": "Wenn auf aktiviert, zeigt diese Einstellung an, dass der Benutzer das Weiterleiten von Nachrichten über MQTT akzeptiert. Wenn deaktiviert, werden entfernte Knoten aufgefordert, Nachrichten nicht über MQTT weiterzuleiten", + "label": "OK für MQTT" + }, + "overrideDutyCycle": { + "description": "Duty-Cycle überschreiben", + "label": "Duty-Cycle überschreiben" + }, + "overrideFrequency": { + "description": "Sendefrequenz überschreiben (MHz)", + "label": "Sendefrequenz überschreiben" + }, + "region": { + "description": "Legt die Region für Ihren Knoten fest", + "label": "Region" + }, + "spreadingFactor": { + "description": "Anzahl der Symbole zur Kodierung der Nutzdaten", + "label": "Spreizfaktor" + }, + "transmitEnabled": { + "description": "Sender (TX) des LoRa Funkgerätes aktivieren/deaktivieren", + "label": "Senden aktiviert" + }, + "transmitPower": { + "description": "Maximale Sendeleistung", + "label": "Sendeleistung" + }, + "usePreset": { + "description": "Eine der vordefinierten Modem Voreinstellungen verwenden", + "label": "Voreinstellung verwenden" + }, + "meshSettings": { + "description": "Einstellungen für das LoRa Netz", + "label": "Netzeinstellungen" + }, + "waveformSettings": { + "description": "Einstellungen für die LoRa Wellenform", + "label": "Einstellungen der Wellenform" + }, + "radioSettings": { + "label": "Radio-Einstellungen", + "description": "Einstellungen für das LoRa Funkgerät" + } + }, + "network": { + "title": "WLAN Einstellungen", + "description": "WLAN Funkeinstellungen", + "note": "Hinweis: Einige Geräte (ESP32) können nicht gleichzeitig Bluetooth und WLAN verwenden.", + "addressMode": { + "description": "Auswahl der IP Adressenzuweisung", + "label": "IP Adressenmodus" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Aktivieren oder deaktivieren sie den Ethernet Anschluss", + "label": "Aktiviert" + }, + "gateway": { + "description": "Standard Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Netzwerkpasswort", + "label": "PSK" + }, + "ssid": { + "description": "Netzwerkname", + "label": "SSID" + }, + "subnet": { + "description": "Subnetzmaske", + "label": "Subnetz" + }, + "wifiEnabled": { + "description": "Aktivieren oder deaktivieren Sie die WLAN Übertragung", + "label": "Aktiviert" + }, + "meshViaUdp": { + "label": "Netz über UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Einstellung des Ethernet Ports", + "label": "Ethernet Einstellung" + }, + "ipConfigSettings": { + "description": "Einstellung der IP Adresse", + "label": "IP Adresseinstellungen" + }, + "ntpConfigSettings": { + "description": "NTP Server Einstellungen", + "label": "NTP Einstellungen" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog Einstellung", + "label": "Rsyslog Einstellung" + }, + "udpConfigSettings": { + "description": "UDP über Netz Einstellung", + "label": "UDP Konfiguration" + } + }, + "position": { + "title": "Standorteinstellung", + "description": "Einstellungen für das Standortmodul", + "broadcastInterval": { + "description": "Wie oft Ihr Standort über das Netz gesendet wird", + "label": "Übertragungsintervall" + }, + "enablePin": { + "description": "Überschreiben des GPIO der das GPS-Modul aktiviert", + "label": "GPIO GPS aktivieren" + }, + "fixedPosition": { + "description": "GPS Standort nicht senden, sondern manuell angegeben", + "label": "Fester Standort" + }, + "gpsMode": { + "description": "Einstellung, ob GPS des Geräts aktiviert, deaktiviert oder nicht vorhanden ist", + "label": "GPS Modus" + }, + "gpsUpdateInterval": { + "description": "Wie oft ein GPS Standort ermittelt werden soll", + "label": "GPS Aktualisierungsintervall" + }, + "positionFlags": { + "description": "Optionalen, die bei der Zusammenstellung von Standortnachrichten enthalten sein sollen. Je mehr Optionen ausgewählt werden, desto größer wird die Nachricht und die längere Übertragungszeit erhöht das Risiko für einen Nachrichtenverlust.", + "label": "Standort Optionen" + }, + "receivePin": { + "description": "GPIO Pin für serielles Empfangen (RX) des GPS-Moduls überschreiben", + "label": "GPIO Empfangen" + }, + "smartPositionEnabled": { + "description": "Standort nur verschicken, wenn eine sinnvolle Standortänderung stattgefunden hat", + "label": "Intelligenten Standort aktivieren" + }, + "smartPositionMinDistance": { + "description": "Mindestabstand (in Meter), die vor dem Senden einer Standortaktualisierung zurückgelegt werden muss", + "label": "Minimale Entfernung für intelligenten Standort" + }, + "smartPositionMinInterval": { + "description": "Minimales Intervall (in Sekunden), das vor dem Senden einer Standortaktualisierung vergangen sein muss", + "label": "Minimales Intervall für intelligenten Standort" + }, + "transmitPin": { + "description": "GPIO Pin für serielles Senden (TX) des GPS-Moduls überschreiben", + "label": "GPIO Senden" + }, + "intervalsSettings": { + "description": "Wie oft Standortaktualisierungen gesendet werden", + "label": "Intervalle" + }, + "flags": { + "placeholder": "Standort Optionen auswählen", + "altitude": "Höhe", + "altitudeGeoidalSeparation": "Geoidale Höhentrennung", + "altitudeMsl": "Höhe in Bezug auf Meeresspiegel", + "dop": "Dilution of Präzision (DOP) PDOP standardmäßig verwenden", + "hdopVdop": "Wenn DOP gesetzt ist, wird HDOP / VDOP anstelle von PDOP verwendet", + "numSatellites": "Anzahl Satelliten", + "sequenceNumber": "Sequenznummer", + "timestamp": "Zeitstempel", + "unset": "Nicht konfiguriert", + "vehicleHeading": "Fahrzeugsteuerkurs", + "vehicleSpeed": "Fahrzeuggeschwindigkeit" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Zur Optimierung der Genauigkeit bei der Akkuspannunsmessung", + "label": "ADC Multiplikationsfaktor" + }, + "ina219Address": { + "description": "Adresse des INA219 Stromsensors", + "label": "INA219 Adresse" + }, + "lightSleepDuration": { + "description": "Wie lange das Gerät im leichten Schlafmodus ist", + "label": "Dauer leichter Schlafmodus" + }, + "minimumWakeTime": { + "description": "Minimale Zeitspanne für die das Gerät aktiv bleibt, nachdem es eine Nachricht empfangen hat", + "label": "Minimale Aufwachzeit" + }, + "noConnectionBluetoothDisabled": { + "description": "Wenn das Gerät keine Bluetooth Verbindung erhält, wird der BLE Funk nach dieser Zeit deaktiviert", + "label": "Keine Verbindung, Bluetooth deaktiviert" + }, + "powerSavingEnabled": { + "description": "Auswählen, wenn aus einer Stromquelle mit niedriger Kapazität (z.B Solar) betrieben wird, um den Stromverbrauch so weit wie möglich zu minimieren.", + "label": "Energiesparmodus aktivieren" + }, + "shutdownOnBatteryDelay": { + "description": "Verzögerung bis zum Abschalten der Knoten sich im Akkubetrieb befindet. 0 für unbegrenzt", + "label": "Verzögerung Akkuabschaltung" + }, + "superDeepSleepDuration": { + "description": "Wie lange das Gerät im supertiefen Schlafmodus ist", + "label": "Dauer Supertiefschlaf" + }, + "powerConfigSettings": { + "description": "Einstellungen für das Energiemodul", + "label": "Power Konfiguration" + }, + "sleepSettings": { + "description": "Einstellungen Ruhezustand für das Energiemodul", + "label": "Einstellung Ruhezustand" + } + }, + "security": { + "description": "Sicherheitseinstellungen", + "title": "Sicherheitseinstellungen", + "button_backupKey": "Schlüssel sichern", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Veraltete Administrierung erlauben" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Debug-Protokoll API aktivieren" + }, + "managed": { + "description": "Wenn aktiviert, können die Geräteeinstellungen nur von einem entfernten Administratorknoten über administrative Nachrichten geändert werden. Aktivieren Sie diese Option nur, wenn mindestens ein geeigneter Administratorknoten eingerichtet, und desen öffentlicher Schlüssel wird in einem der obigen Felder gespeichert wurde.", + "label": "Verwaltet" + }, + "privateKey": { + "description": "Wird verwendet, um einen gemeinsamen Schlüssel mit einem entfernten Gerät zu erstellen", + "label": "Privater Schlüssel" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Öffentlicher Schlüssel" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Erster Admin-Schlüssel" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Zweiter Admin-Schlüssel" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serielle Ausgabe aktiviert" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Dritter Admin-Schlüssel" + }, + "adminSettings": { + "description": "Administrator Einstellungen", + "label": "Administrator Einstellungen" + }, + "loggingSettings": { + "description": "Einstellungen für die Protokollierung", + "label": "Protokolleinstellungen" + } + } +} diff --git a/src/i18n/locales/de-DE/dialog.json b/src/i18n/locales/de-DE/dialog.json new file mode 100644 index 00000000..85b03e0e --- /dev/null +++ b/src/i18n/locales/de-DE/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "Diese Aktion wird den Nachrichtenverlauf löschen. Dies kann nicht rückgängig gemacht werden. Sind Sie sicher, dass Sie fortfahren möchten?", + "title": "Alle Nachrichten löschen" + }, + "deviceName": { + "description": "Das Gerät wird neu gestartet, sobald die Einstellung gespeichert ist.", + "longName": "Langer Name", + "shortName": "Kurzname", + "title": "Gerätename ändern" + }, + "import": { + "description": "Die aktuelle LoRa Einstellung wird überschrieben.", + "error": { + "invalidUrl": "Ungültige Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Kanalsammlung / QR-Code URL", + "channels": "Channels:", + "usePreset": "Voreinstellung verwenden?", + "title": "Kanalsammlung importieren" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Standort: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Vorab verteilten Schlüssel (PSK) neu erstellen?", + "description": "Sind Sie sicher, dass Sie den vorab verteilten Schlüssel neu erstellen möchten?", + "regenerate": "Neu erstellen" + }, + "newDeviceDialog": { + "title": "Neues Gerät verbinden", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seriell", + "useHttps": "HTTPS verwenden", + "connecting": "Connecting...", + "connect": "Verbindung herstellen", + "connectionFailedAlert": { + "title": "Verbindung fehlgeschlagen", + "descriptionPrefix": "Verbindung zum Gerät fehlgeschlagen. ", + "httpsHint": "Wenn Sie HTTPS verwenden, müssen Sie möglicherweise zuerst ein selbstsigniertes Zertifikat akzeptieren. ", + "openLinkPrefix": "Öffnen Sie ", + "openLinkSuffix": "in einem neuen Tab", + "acceptTlsWarningSuffix": ", akzeptieren Sie alle TLS-Warnungen, wenn Sie dazu aufgefordert werden, dann versuchen Sie es erneut", + "learnMoreLink": "Mehr erfahren" + }, + "httpConnection": { + "label": "IP Adresse/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "Noch keine Geräte gekoppelt.", + "newDeviceButton": "Neues Gerät", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "Noch keine Geräte gekoppelt.", + "newDeviceButton": "Neues Gerät" + }, + "validation": { + "requiresFeatures": "Dieser Verbindungstyp erfordert <0>. Bitte verwenden Sie einen unterstützten Browser, wie Chrome oder Edge.", + "requiresSecureContext": "Diese Anwendung erfordert einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost.", + "additionallyRequiresSecureContext": "Zusätzlich erfordert es einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost." + } + }, + "nodeDetails": { + "message": "Nachricht", + "requestPosition": "Standort anfordern", + "traceRoute": "Route verfolgen", + "airTxUtilization": "Auslastung Sendezeit", + "allRawMetrics": "Alle Rohdaten", + "batteryLevel": "Akkustand", + "channelUtilization": "Kanalauslastung", + "details": "Details:", + "deviceMetrics": "Gerätekennzahlen:", + "hardware": "Hardware: ", + "lastHeard": "Zuletzt gehört: ", + "nodeHexPrefix": "Knoten ID: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Spannung", + "title": "Knotendetails für {{identifier}}", + "ignoreNode": "Knoten ignorieren", + "removeNode": "Knoten entfernen", + "unignoreNode": "Knoten akzeptieren" + }, + "pkiBackup": { + "description": "Wir empfehlen die regelmäßige Sicherung Ihrer Schlüsseldaten. Möchten Sie jetzt sicheren?", + "loseKeysWarning": "Wenn Sie Ihre Schlüssel verlieren, müssen Sie Ihr Gerät zurücksetzen.", + "secureBackup": "Es ist wichtig, dass Sie Ihre öffentlichen und privaten Schlüssel sichern und diese sicher speichern!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Schlüssel sichern" + }, + "pkiRegenerate": { + "description": "Sind Sie sicher, dass Sie Schlüsselpaar neu erstellen möchten?", + "title": "Schlüsselpaar neu erstellen" + }, + "qr": { + "addChannels": "Kanäle hinzufügen", + "replaceChannels": "Kanäle ersetzen", + "description": "Die aktuelle LoRa Einstellung wird ebenfalls geteilt.", + "sharableUrl": "Teilbare URL", + "title": "QR Code Erzeugen" + }, + "rebootOta": { + "title": "Neustart planen", + "description": "Startet den verbundenen Knoten nach einer Verzögerung in den OTA (Over-the-Air) Modus.", + "enterDelay": "Verzögerung eingeben (Sek.)", + "scheduled": "Neustart wurde geplant" + }, + "reboot": { + "title": "Neustart planen", + "description": "Startet den verbundenen Knoten nach x Minuten neu." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "Dies entfernt den Knoten vom Gerät und fordert neue Schlüssel an.", + "keyMismatchReasonSuffix": ". Dies liegt daran, dass der aktuelle öffentliche Schlüssel des entfernten Knotens nicht mit dem zuvor gespeicherten Schlüssel für diesen Knoten übereinstimmt.", + "unableToSendDmPrefix": "Ihr Knoten kann keine Direktnachricht an folgenden Knoten senden: " + }, + "acceptNewKeys": "Neue Schlüssel akzeptieren", + "title": "Schlüsselfehler - {{identifier}}" + }, + "removeNode": { + "description": "Sind Sie sicher, dass Sie diesen Knoten entfernen möchten?", + "title": "Knoten entfernen?" + }, + "shutdown": { + "title": "Herunterfahren planen", + "description": "Schaltet den verbundenen Knoten nach x Minuten aus." + }, + "traceRoute": { + "routeToDestination": "Route zum Ziel:", + "routeBack": "Route zurück:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Ja, ich weiß, was ich tue!", + "conjunction": " und der Blog-Beitrag über ", + "postamble": " und verstehen die Auswirkungen einer Veränderung der Rolle.", + "preamble": "Ich habe die", + "choosingRightDeviceRole": "Wahl der richtigen Geräterolle", + "deviceRoleDocumentation": "Dokumentation der Geräterolle", + "title": "Bist Du sicher?" + } +} diff --git a/src/i18n/locales/de-DE/messages.json b/src/i18n/locales/de-DE/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/de-DE/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/de-DE/moduleConfig.json b/src/i18n/locales/de-DE/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/de-DE/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/de-DE/nodes.json b/src/i18n/locales/de-DE/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/de-DE/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/de-DE/ui.json b/src/i18n/locales/de-DE/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/de-DE/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/es-ES/channels.json b/src/i18n/locales/es-ES/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/es-ES/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/es-ES/commandPalette.json b/src/i18n/locales/es-ES/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/es-ES/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/es-ES/common.json b/src/i18n/locales/es-ES/common.json new file mode 100644 index 00000000..e5da6d9f --- /dev/null +++ b/src/i18n/locales/es-ES/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Aplique", + "backupKey": "Backup Key", + "cancel": "Cancelar", + "clearMessages": "Clear Messages", + "close": "Cerrar", + "confirm": "Confirm", + "delete": "Eliminar", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Mensaje", + "now": "Now", + "ok": "Vale", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Quitar", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reiniciar", + "save": "Guardar", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/es-ES/dashboard.json b/src/i18n/locales/es-ES/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/es-ES/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/es-ES/deviceConfig.json b/src/i18n/locales/es-ES/deviceConfig.json new file mode 100644 index 00000000..dfa21d26 --- /dev/null +++ b/src/i18n/locales/es-ES/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Dispositivo", + "tabDisplay": "Pantalla", + "tabLora": "LoRa", + "tabNetwork": "Red", + "tabPosition": "Posición", + "tabPower": "Energía", + "tabSecurity": "Seguridad" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Modo de emparejamiento" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Región" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configuración UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Sin configurar", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Clave privada" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Clave Pública" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/es-ES/dialog.json b/src/i18n/locales/es-ES/dialog.json new file mode 100644 index 00000000..97f12d8f --- /dev/null +++ b/src/i18n/locales/es-ES/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Mensaje", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Tensión", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "¿Estás seguro?" + } +} diff --git a/src/i18n/locales/es-ES/messages.json b/src/i18n/locales/es-ES/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/es-ES/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/es-ES/moduleConfig.json b/src/i18n/locales/es-ES/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/es-ES/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/es-ES/nodes.json b/src/i18n/locales/es-ES/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/es-ES/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/es-ES/ui.json b/src/i18n/locales/es-ES/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/es-ES/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/fi-FI/channels.json b/src/i18n/locales/fi-FI/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/fi-FI/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/fi-FI/commandPalette.json b/src/i18n/locales/fi-FI/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/fi-FI/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/fi-FI/common.json b/src/i18n/locales/fi-FI/common.json new file mode 100644 index 00000000..ed81cf16 --- /dev/null +++ b/src/i18n/locales/fi-FI/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Hyväksy", + "backupKey": "Varmuuskopioi avain", + "cancel": "Peruuta", + "clearMessages": "Tyhjennä viestit", + "close": "Sulje", + "confirm": "Vahvista", + "delete": "Poista", + "dismiss": "Hylkää", + "download": "Lataa", + "export": "Vie", + "generate": "Luo", + "regenerate": "Luo uudelleen", + "import": "Tuo", + "message": "Viesti", + "now": "Nyt", + "ok": "OK", + "print": "Tulosta", + "rebootOtaNow": "Käynnistä uudelleen OTA-tilaan nyt", + "remove": "Poista", + "requestNewKeys": "Pyydä uudet avaimet", + "requestPosition": "Pyydä sijaintia", + "reset": "Palauta", + "save": "Tallenna", + "scanQr": "Skannaa QR-koodi", + "traceRoute": "Reitinselvitys" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Ladataan...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hyppy", + "plural": "Hyppyä" + }, + "hopsAway": { + "one": "{{count}} hypyn päässä", + "plural": "{{count}} hypyn päässä", + "unknown": "Hyppyjen määrä tuntematon" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/fi-FI/dashboard.json b/src/i18n/locales/fi-FI/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/fi-FI/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/fi-FI/deviceConfig.json b/src/i18n/locales/fi-FI/deviceConfig.json new file mode 100644 index 00000000..a42db3e8 --- /dev/null +++ b/src/i18n/locales/fi-FI/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Asetukset", + "tabBluetooth": "Bluetooth", + "tabDevice": "Laite", + "tabDisplay": "Näyttö", + "tabLora": "LoRa", + "tabNetwork": "Verkko", + "tabPosition": "Sijainti", + "tabPower": "Virta", + "tabSecurity": "Turvallisuus" + }, + "sidebar": { + "label": "Moduulit" + }, + "device": { + "title": "Laitteen asetukset", + "description": "Laitteen asetukset", + "buttonPin": { + "description": "Painikkeen pinnin ohitus", + "label": "Painikkeen pinni" + }, + "buzzerPin": { + "description": "Summerin pinnin ohitus", + "label": "Summerin pinni" + }, + "disableTripleClick": { + "description": "Poista kolmoisklikkaus käytöstä", + "label": "Poista kolmoisklikkaus käytöstä" + }, + "doubleTapAsButtonPress": { + "description": "Käsittele kaksoisnapautus painikkeen painalluksena", + "label": "Kaksoisnapautus painikkeen painalluksena" + }, + "ledHeartbeatDisabled": { + "description": "Poista ledin vilkkuminen käytöstä", + "label": "Ledin vilkkuminen poistettu käytöstä" + }, + "nodeInfoBroadcastInterval": { + "description": "Kuinka usein laitteen tiedot lähetetään verkkoon", + "label": "Laitteen tietojen lähetyksen aikaväli" + }, + "posixTimezone": { + "description": "POSIX-aikavyöhykkeen merkkijono laitetta varten", + "label": "POSIX-aikavyöhyke" + }, + "rebroadcastMode": { + "description": "Kuinka uudelleenlähetyksiä käsitellään", + "label": "Uudelleenlähetyksen tila" + }, + "role": { + "description": "Mikä rooli laitteella on mesh-verkossa", + "label": "Rooli" + } + }, + "bluetooth": { + "title": "Bluetooth asetukset", + "description": "Bluetooth moduulin asetukset", + "note": "Huomautus: Jotkin laitteet (ESP32) eivät voi käyttää bluetoothia sekä WiFiä samanaikaisesti.", + "enabled": { + "description": "Ota Bluetooth käyttöön tai poista käytöstä", + "label": "Käytössä" + }, + "pairingMode": { + "description": "PIN-koodin valinnan käyttäytyminen.", + "label": "Paritustila" + }, + "pin": { + "description": "Bluetooth PIN-koodi, jota käytetään pariliitettäessä", + "label": "PIN" + } + }, + "display": { + "description": "Laitteen näytön asetukset", + "title": "Näyttöasetukset", + "headingBold": { + "description": "Lihavoi otsikkoteksti", + "label": "Lihavoitu otsikko" + }, + "carouselDelay": { + "description": "Kuinka nopeasti ikkunat kulkevat", + "label": "Karusellin Viive" + }, + "compassNorthTop": { + "description": "Kiinnitä pohjoinen kompassin yläreunaan", + "label": "Kompassin pohjoinen ylhäällä" + }, + "displayMode": { + "description": "Näytön asettelun vaihtoehdot", + "label": "Näyttötila" + }, + "displayUnits": { + "description": "Näytä metriset tai imperiaaliset yksiköt", + "label": "Näyttöyksiköt" + }, + "flipScreen": { + "description": "Käännä näyttöä 180 astetta", + "label": "Käännä näyttö" + }, + "gpsDisplayUnits": { + "description": "Koordinaattien näyttömuoto", + "label": "GPS näyttöyksiköt" + }, + "oledType": { + "description": "Laitteeseen liitetyn OLED-näytön tyyppi", + "label": "OLED-tyyppi" + }, + "screenTimeout": { + "description": "Sammuta näyttö tämän ajan jälkeen", + "label": "Näytön aikakatkaisu" + }, + "twelveHourClock": { + "description": "Käytä 12 tunnin kelloa", + "label": "12 tunnin kello" + }, + "wakeOnTapOrMotion": { + "description": "Herätä laite napauttamalla tai liikkeestä", + "label": "Herätä napauttamalla tai liikkeellä" + } + }, + "lora": { + "title": "Mesh-verkon asetukset", + "description": "LoRa-verkon asetukset", + "bandwidth": { + "description": "Kanavan kaistanleveys MHz", + "label": "Kaistanleveys" + }, + "boostedRxGain": { + "description": "RX tehostettu vahvistus", + "label": "RX tehostettu vahvistus" + }, + "codingRate": { + "description": "Koodausnopeuden nimittäjä", + "label": "Koodausnopeus" + }, + "frequencyOffset": { + "description": "Taajuuskorjaus kalibrointivirheiden korjaamiseksi", + "label": "Taajuuspoikkeama" + }, + "frequencySlot": { + "description": "LoRa-taajuuden kanavanumero", + "label": "Taajuuspaikka" + }, + "hopLimit": { + "description": "Maksimimäärä hyppyjä", + "label": "Hyppyraja" + }, + "ignoreMqtt": { + "description": "Älä välitä MQTT-viestejä mesh-verkon yli", + "label": "Ohita MQTT" + }, + "modemPreset": { + "description": "Käytössä olevan modeemin esiasetus", + "label": "Modeemin esiasetus" + }, + "okToMqtt": { + "description": "Kun asetetaan arvoksi true, tämä asetus tarkoittaa, että käyttäjä hyväksyy paketin lähettämisen MQTT:lle. Jos asetetaan arvoksi false, etälaitteita pyydetään olemaan välittämättä paketteja MQTT:lle", + "label": "MQTT päällä" + }, + "overrideDutyCycle": { + "description": "Ohita käyttöaste (Duty Cycle)", + "label": "Ohita käyttöaste (Duty Cycle)" + }, + "overrideFrequency": { + "description": "Käytä mukautettua taajuutta", + "label": "Mukautettu taajuus" + }, + "region": { + "description": "Asettaa alueen laitteelle", + "label": "Alue" + }, + "spreadingFactor": { + "description": "Ilmaisee symbolia kohden lähetettävien taajuuksien määrän", + "label": "Levennyskerroin" + }, + "transmitEnabled": { + "description": "LoRa-radion lähetyksen (TX) käyttöönotto tai poiskytkentä", + "label": "Lähetys käytössä" + }, + "transmitPower": { + "description": "Suurin lähetysteho", + "label": "Lähetysteho" + }, + "usePreset": { + "description": "Käytä ennalta määriteltyä modeemin esiasetusta", + "label": "Käytä esiasetusta" + }, + "meshSettings": { + "description": "LoRa-verkon asetukset", + "label": "Mesh-verkon asetukset" + }, + "waveformSettings": { + "description": "LoRa-aaltomuodon asetukset", + "label": "Signaalimuodon asetukset" + }, + "radioSettings": { + "label": "Radioasetukset", + "description": "LoRa-laitteen asetukset" + } + }, + "network": { + "title": "WiFi-asetukset", + "description": "WiFi-radion asetukset", + "note": "Huomautus: Jotkin laitteet (ESP32) eivät voi käyttää sekä Bluetoothia että WiFiä samanaikaisesti.", + "addressMode": { + "description": "Osoitteen määrityksen valinta", + "label": "Osoitetila" + }, + "dns": { + "description": "DNS-palvelin", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Ota käyttöön tai poista käytöstä ethernet-portti", + "label": "Käytössä" + }, + "gateway": { + "description": "Oletusyhdyskäytävä", + "label": "Yhdyskäytävä" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Verkon salasana", + "label": "PSK" + }, + "ssid": { + "description": "Verkon nimi", + "label": "SSID" + }, + "subnet": { + "description": "Aliverkon peite", + "label": "Aliverkko" + }, + "wifiEnabled": { + "description": "Ota WiFi käyttöön tai poista se käytöstä", + "label": "Käytössä" + }, + "meshViaUdp": { + "label": "Mesh UDP:n kautta" + }, + "ntpServer": { + "label": "NTP-palvelin" + }, + "rsyslogServer": { + "label": "Rsyslog-palvelin" + }, + "ethernetConfigSettings": { + "description": "Ethernet-portin asetukset", + "label": "Ethernet-asetukset" + }, + "ipConfigSettings": { + "description": "IP-osoitteen asetukset", + "label": "IP-osoitteen asetukset" + }, + "ntpConfigSettings": { + "description": "NTP-asetukset", + "label": "NTP-asetukset" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog määritykset", + "label": "Rsyslog määritykset" + }, + "udpConfigSettings": { + "description": "UDP-yhdeyden asetukset", + "label": "UDP-asetukset" + } + }, + "position": { + "title": "Sijainnin asetukset", + "description": "Sijaintimoduulin asetukset", + "broadcastInterval": { + "description": "Kuinka usein sijainti lähetetään mesh-verkon yli", + "label": "Lähetyksen aikaväli" + }, + "enablePin": { + "description": "GPS-moduulin käyttöönottopinnin korvaus", + "label": "Ota pinni käytöön" + }, + "fixedPosition": { + "description": "Älä raportoi GPS-sijaintia, vaan käytä manuaalisesti määritettyä sijaintia", + "label": "Kiinteä sijainti" + }, + "gpsMode": { + "description": "Määritä, onko laitteen GPS käytössä, pois päältä vai puuttuuko se kokonaan", + "label": "GSP-tila" + }, + "gpsUpdateInterval": { + "description": "Kuinka usein GPS-paikannus suoritetaan", + "label": "GPS-päivitysväli" + }, + "positionFlags": { + "description": "Valinnaiset kentät, jotka voidaan sisällyttää sijaintiviesteihin. Mitä enemmän kenttiä valitaan, sitä suurempi viesti on, mikä johtaa pidempään lähetysaikaan ja suurempaan pakettihäviöriskiin.", + "label": "Sijaintimerkinnät" + }, + "receivePin": { + "description": "GPS-moduulin käyttöönottopinnin korvaus", + "label": "Vastaanoton pinni" + }, + "smartPositionEnabled": { + "description": "Lähetä sijainti vain, kun sijainnissa on tapahtunut merkittävä muutos", + "label": "Ota älykäs sijainti käyttöön" + }, + "smartPositionMinDistance": { + "description": "Vähimmäisetäisyys (metreinä), joka on kuljettava ennen sijaintipäivityksen lähettämistä", + "label": "Älykkään sijainnin minimietäisyys" + }, + "smartPositionMinInterval": { + "description": "Lyhin aikaväli (sekunteina), joka on kuluttava ennen sijaintipäivityksen lähettämistä", + "label": "Älykkään sijainnin vähimmäisetäisyys" + }, + "transmitPin": { + "description": "GPS-moduulin käyttöönottopinnin korvaus", + "label": "Lähetyksen pinni" + }, + "intervalsSettings": { + "description": "Kuinka usein sijaintipäivitykset lähetetään", + "label": "Aikaväli" + }, + "flags": { + "placeholder": "Valitse sijaintiasetukset...", + "altitude": "Korkeus", + "altitudeGeoidalSeparation": "Korkeuden geoidinen erotus", + "altitudeMsl": "Korkeus on mitattu merenpinnan tasosta", + "dop": "Tarkkuuden heikkenemä (DOP), oletuksena käytetään PDOP-arvoa", + "hdopVdop": "Jos DOP on asetettu, käytä HDOP- ja VDOP-arvoja PDOP:n sijaan", + "numSatellites": "Satelliittien määrä", + "sequenceNumber": "Sekvenssinumero", + "timestamp": "Aikaleima", + "unset": "Ei yhdistetty", + "vehicleHeading": "Ajoneuvon suunta", + "vehicleSpeed": "Ajoneuvon nopeus" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Käytetään akun jännitteen lukeman säätämiseen", + "label": "Korvaava AD-muuntimen kerroin" + }, + "ina219Address": { + "description": "Akkunäytön INA219 osoite", + "label": "INA219 Osoite" + }, + "lightSleepDuration": { + "description": "Kuinka kauan laite on kevyessä lepotilassa", + "label": "Kevyen lepotilan kesto" + }, + "minimumWakeTime": { + "description": "Vähimmäisaika, jonka laite pysyy hereillä paketin vastaanoton jälkeen", + "label": "Minimi heräämisaika" + }, + "noConnectionBluetoothDisabled": { + "description": "Jos laite ei saa Bluetooth-yhteyttä, BLE-radio poistetaan käytöstä tämän ajan kuluttua", + "label": "Ei yhteyttä. Bluetooth on pois käytöstä" + }, + "powerSavingEnabled": { + "description": "Valitse, jos laite saa virtaa matalavirtalähteestä (esim. aurinkopaneeli), jolloin virrankulutusta minimoidaan mahdollisimman paljon.", + "label": "Ota virransäästötila käyttöön" + }, + "shutdownOnBatteryDelay": { + "description": "Sammuta laite automaattisesti tämän ajan kuluttua akkukäytöllä, 0 tarkoittaa toistaiseksi päällä", + "label": "Viive laitteen sammuttamisessa akkukäytöllä" + }, + "superDeepSleepDuration": { + "description": "Kuinka pitkään laite on supersyvässä lepotilassa", + "label": "Supersyvän lepotilan kesto" + }, + "powerConfigSettings": { + "description": "Virtamoduulin asetukset", + "label": "Virran asetukset" + }, + "sleepSettings": { + "description": "Virtamoduulin lepotila-asetukset", + "label": "Lepotilan asetukset" + } + }, + "security": { + "description": "Turvallisuuskokoonpanon asetukset", + "title": "Turvallisuusasetukset", + "button_backupKey": "Varmuuskopioi avain", + "adminChannelEnabled": { + "description": "Salli saapuva laitteen ohjaus suojaamattoman vanhan admin-kanavan kautta", + "label": "Salli vanha admin ylläpitäjä" + }, + "enableDebugLogApi": { + "description": "Lähetä reaaliaikainen debug-loki sarjaportin kautta, katso ja vie laitteen lokitiedostot, joista sijaintitiedot on poistettu, Bluetoothin kautta", + "label": "Ota käyttöön virheenkorjauslokin API-rajapinta" + }, + "managed": { + "description": "Jos tämä on käytössä, laitteen asetuksia voi muuttaa vain etäadmin-laitteen hallintaviestien kautta. Älä ota tätä käyttöön, ellei vähintään yhtä sopivaa etäadmin-laitetta ole määritetty ja julkinen avain ei ole tallennettu johonkin yllä olevista kentistä.", + "label": "Hallinnoitu" + }, + "privateKey": { + "description": "Käytetään jaetun avaimen luomiseen etälaitteen kanssa", + "label": "Yksityinen avain" + }, + "publicKey": { + "description": "Lähetetään muille mesh-verkon laitteille, jotta ne voivat laskea jaetun salaisen avaimen", + "label": "Julkinen avain" + }, + "primaryAdminKey": { + "description": "Ensisijainen julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", + "label": "Ensisijainen järjestelmänvalvojan avain" + }, + "secondaryAdminKey": { + "description": "Toissijainen julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", + "label": "Toissijainen järjestelmänvalvojan avain" + }, + "serialOutputEnabled": { + "description": "Sarjakonsoli Stream API:n yli", + "label": "Sarjaulostulo Käytössä" + }, + "tertiaryAdminKey": { + "description": "Kolmas julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", + "label": "Kolmas järjestelmänvalvojan hallinta-avain" + }, + "adminSettings": { + "description": "Järjestelmänvalvojan asetukset", + "label": "Ylläpitäjän asetukset" + }, + "loggingSettings": { + "description": "Kirjautumisen asetukset", + "label": "Kirjautumisen asetukset" + } + } +} diff --git a/src/i18n/locales/fi-FI/dialog.json b/src/i18n/locales/fi-FI/dialog.json new file mode 100644 index 00000000..777330d4 --- /dev/null +++ b/src/i18n/locales/fi-FI/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "Tämä toiminto poistaa kaiken viestihistorian. Toimintoa ei voi perua. Haluatko varmasti jatkaa?", + "title": "Tyhjennä kaikki viestit" + }, + "deviceName": { + "description": "Laite käynnistyy uudelleen, kun asetus on tallennettu.", + "longName": "Pitkä nimi", + "shortName": "Lyhytnimi", + "title": "Vaihda laitteen nimi" + }, + "import": { + "description": "Nykyinen LoRa-asetus ylikirjoitetaan.", + "error": { + "invalidUrl": "Virheellinen Meshtastic verkko-osoite" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Kanavan asetus / QR-koodin URL-osoite", + "channels": "Channels:", + "usePreset": "Käytä esiasetusta?", + "title": "Tuo kanava-asetukset" + }, + "locationResponse": { + "altitude": "Korkeus: ", + "coordinates": "Koordinaatit: ", + "title": "Sijainti: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Luodaanko ennalta jaettu avain uudelleen?", + "description": "Haluatko varmasti luoda ennalta jaetun avaimen uudelleen?", + "regenerate": "Luo uudelleen" + }, + "newDeviceDialog": { + "title": "Yhdistä uuteen laitteeseen", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Sarjaliitäntä", + "useHttps": "Käytä HTTPS", + "connecting": "Connecting...", + "connect": "Yhdistä", + "connectionFailedAlert": { + "title": "Yhteys epäonnistui", + "descriptionPrefix": "Laitteeseen ei saatu yhteyttä. ", + "httpsHint": "Jos käytät HTTPS:ää, sinun on ehkä ensin hyväksyttävä itse allekirjoitettu varmenne. ", + "openLinkPrefix": "Avaa ", + "openLinkSuffix": " uuteen välilehteen", + "acceptTlsWarningSuffix": ", hyväksy mahdolliset TLS-varoitukset, jos niitä ilmenee ja yritä sitten uudelleen.", + "learnMoreLink": "Lue lisää" + }, + "httpConnection": { + "label": "IP-osoite / isäntänimi", + "placeholder": "000.000.000 / meshtastinen.paikallinen" + }, + "serialConnection": { + "noDevicesPaired": "Yhtään laitetta ei ole vielä yhdistetty.", + "newDeviceButton": "Uusi laite", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "Yhtään laitetta ei ole vielä yhdistetty.", + "newDeviceButton": "Uusi laite" + }, + "validation": { + "requiresFeatures": "Tämä yhteystyyppi vaatii <0>. Käytä tuettua selainta, kuten Chromea tai Edgeä.", + "requiresSecureContext": "Tämä sovellus vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia.", + "additionallyRequiresSecureContext": "Lisäksi se vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia." + } + }, + "nodeDetails": { + "message": "Viesti", + "requestPosition": "Pyydä sijaintia", + "traceRoute": "Reitinselvitys", + "airTxUtilization": "Ilmatien TX käyttöaste", + "allRawMetrics": "Kaikki raakatiedot:", + "batteryLevel": "Akun varaus", + "channelUtilization": "Kanavan käyttöaste", + "details": "Details:", + "deviceMetrics": "Laitteen mittausloki:", + "hardware": "Hardware: ", + "lastHeard": "Viimeksi kuultu: ", + "nodeHexPrefix": "Laitteen Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Jännite", + "title": "Tiedot laitteelle {{identifier}}", + "ignoreNode": "Älä huomioi laitetta", + "removeNode": "Poista laite", + "unignoreNode": "Poista laitteen ohitus käytöstä" + }, + "pkiBackup": { + "description": "Suosittelemme avaintietojen säännöllistä varmuuskopiointia. Haluatko varmuuskopioida nyt?", + "loseKeysWarning": "Jos menetät avaimesi, sinun täytyy palauttaa laite tehdasasetuksiin.", + "secureBackup": "On tärkeää varmuuskopioida julkiset ja yksityiset avaimet ja säilyttää niiden varmuuskopioita turvallisesti!", + "footer": "=== AVAIMIEN LOPPU ===", + "header": "=== MESHTASTIC AVAIMET {{longName}} ({{shortName}}) LAITTEELLE ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_avaimet_{{longName}}_{{shortName}}.txt", + "title": "Varmuuskopioi avaimet" + }, + "pkiRegenerate": { + "description": "Haluatko varmasti luoda avainparin uudelleen?", + "title": "Luo avainpari uudelleen" + }, + "qr": { + "addChannels": "Lisää kanavia", + "replaceChannels": "Korvaa kanavia", + "description": "Nykyinen LoRa-kokoonpano tullaan myös jakamaan.", + "sharableUrl": "Jaettava URL", + "title": "Generoi QR-koodi" + }, + "rebootOta": { + "title": "Ajasta uudelleenkäynnistys", + "description": "Käynnistä yhdistetty laite uudelleen viiveen jälkeen OTA-tilaan (langaton päivitys).", + "enterDelay": "Anna viive (sekuntia)", + "scheduled": "Uudelleenkäynnistys on ajastettu" + }, + "reboot": { + "title": "Ajasta uudelleenkäynnistys", + "description": "Käynnistä yhdistetty laite x minuutin jälkeen." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "Tämä poistaa laitteen laitteesta ja pyytää uusia avaimia.", + "keyMismatchReasonSuffix": ". Tämä johtuu siitä, että etälaitteen nykyinen julkinen avain ei vastaa aiemmin tallennettua avainta tälle laitteelle.", + "unableToSendDmPrefix": "Laitteesi ei pysty lähettämään suoraa viestiä laitteelle: " + }, + "acceptNewKeys": "Hyväksy uudet avaimet", + "title": "Avaimet eivät täsmää - {{identifier}}" + }, + "removeNode": { + "description": "Haluatko varmasti poistaa tämän laitteen?", + "title": "Poista laite?" + }, + "shutdown": { + "title": "Ajasta sammutus", + "description": "Sammuta yhdistetty laite x minuutin päästä." + }, + "traceRoute": { + "routeToDestination": "Reitin määränpää:", + "routeBack": "Reitti takaisin:" + }, + "tracerouteResponse": { + "title": "Reitinselvitys: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Kyllä, tiedän mitä teen", + "conjunction": " ja blogikirjoitukset ", + "postamble": " ja ymmärrän roolin muuttamisen vaikutukset.", + "preamble": "Olen lukenut ", + "choosingRightDeviceRole": "Valitse laitteelle oikea rooli", + "deviceRoleDocumentation": "Roolien dokumentaatio laitteelle", + "title": "Oletko varma?" + } +} diff --git a/src/i18n/locales/fi-FI/messages.json b/src/i18n/locales/fi-FI/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/fi-FI/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/fi-FI/moduleConfig.json b/src/i18n/locales/fi-FI/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/fi-FI/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/fi-FI/nodes.json b/src/i18n/locales/fi-FI/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/fi-FI/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/fi-FI/ui.json b/src/i18n/locales/fi-FI/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/fi-FI/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/fr-FR/channels.json b/src/i18n/locales/fr-FR/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/fr-FR/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/fr-FR/commandPalette.json b/src/i18n/locales/fr-FR/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/fr-FR/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/fr-FR/common.json b/src/i18n/locales/fr-FR/common.json new file mode 100644 index 00000000..fad4c941 --- /dev/null +++ b/src/i18n/locales/fr-FR/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Appliquer", + "backupKey": "Backup Key", + "cancel": "Annuler", + "clearMessages": "Clear Messages", + "close": "Fermer", + "confirm": "Confirm", + "delete": "Effacer", + "dismiss": "Annuler", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "D'accord", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Supprimer", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Réinitialiser", + "save": "Sauvegarder", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/fr-FR/dashboard.json b/src/i18n/locales/fr-FR/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/fr-FR/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/fr-FR/deviceConfig.json b/src/i18n/locales/fr-FR/deviceConfig.json new file mode 100644 index 00000000..d98bc2a7 --- /dev/null +++ b/src/i18n/locales/fr-FR/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Appareil", + "tabDisplay": "Écran", + "tabLora": "LoRa", + "tabNetwork": "Réseau", + "tabPosition": "Position", + "tabPower": "Alimentation", + "tabSecurity": "Sécurité" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "Zone horaire POSIX" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Rôle" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Activé" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Mode d'appariement" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bande Passante" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignorer MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK vers MQTT" + }, + "overrideDutyCycle": { + "description": "Ne pas prendre en compte la limite d'utilisation", + "label": "Ne pas prendre en compte la limite d'utilisation" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Région" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Activé" + }, + "gateway": { + "description": "Default Gateway", + "label": "Passerelle" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Sous-réseau" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Activé" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configuration UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Horodatage", + "unset": "Désactivé", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Activer le mode économie d'énergie" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Configuration de l'alimentation" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Clé privée" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Clé publique" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/fr-FR/dialog.json b/src/i18n/locales/fr-FR/dialog.json new file mode 100644 index 00000000..b7b9c962 --- /dev/null +++ b/src/i18n/locales/fr-FR/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Série", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Tension", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Générer un QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Êtes-vous sûr ?" + } +} diff --git a/src/i18n/locales/fr-FR/messages.json b/src/i18n/locales/fr-FR/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/fr-FR/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/fr-FR/moduleConfig.json b/src/i18n/locales/fr-FR/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/fr-FR/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/fr-FR/nodes.json b/src/i18n/locales/fr-FR/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/fr-FR/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/fr-FR/ui.json b/src/i18n/locales/fr-FR/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/fr-FR/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/it-IT/channels.json b/src/i18n/locales/it-IT/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/it-IT/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/it-IT/commandPalette.json b/src/i18n/locales/it-IT/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/it-IT/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/it-IT/common.json b/src/i18n/locales/it-IT/common.json new file mode 100644 index 00000000..665205de --- /dev/null +++ b/src/i18n/locales/it-IT/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Applica", + "backupKey": "Backup Key", + "cancel": "Annulla", + "clearMessages": "Clear Messages", + "close": "Chiudi", + "confirm": "Confirm", + "delete": "Elimina", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Importa", + "message": "Messaggio", + "now": "Now", + "ok": "Ok", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Elimina", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Salva", + "scanQr": "Scansiona codice QR", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/it-IT/dashboard.json b/src/i18n/locales/it-IT/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/it-IT/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/it-IT/deviceConfig.json b/src/i18n/locales/it-IT/deviceConfig.json new file mode 100644 index 00000000..6ca4ef4d --- /dev/null +++ b/src/i18n/locales/it-IT/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Dispositivo", + "tabDisplay": "Schermo", + "tabLora": "LoRa", + "tabNetwork": "Rete", + "tabPosition": "Posizione", + "tabPower": "Alimentazione", + "tabSecurity": "Sicurezza" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Ruolo" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Modalità abbinamento" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Larghezza di banda" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignora MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Configurazione Modem" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK per MQTT" + }, + "overrideDutyCycle": { + "description": "Ignora limite di Duty Cycle", + "label": "Ignora limite di Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Regione" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configurazione UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Data e ora", + "unset": "Non impostato", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Abilita modalità risparmio energetico" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Configurazione Alimentazione" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Chiave Privata" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Chiave Pubblica" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/it-IT/dialog.json b/src/i18n/locales/it-IT/dialog.json new file mode 100644 index 00000000..6c0197a4 --- /dev/null +++ b/src/i18n/locales/it-IT/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seriale", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Messaggio", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Tensione", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Sei sicuro?" + } +} diff --git a/src/i18n/locales/it-IT/messages.json b/src/i18n/locales/it-IT/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/it-IT/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/it-IT/moduleConfig.json b/src/i18n/locales/it-IT/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/it-IT/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/it-IT/nodes.json b/src/i18n/locales/it-IT/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/it-IT/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/it-IT/ui.json b/src/i18n/locales/it-IT/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/it-IT/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/ja-JP/channels.json b/src/i18n/locales/ja-JP/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/ja-JP/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/ja-JP/commandPalette.json b/src/i18n/locales/ja-JP/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/ja-JP/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/ja-JP/common.json b/src/i18n/locales/ja-JP/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/ja-JP/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/ja-JP/dashboard.json b/src/i18n/locales/ja-JP/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/ja-JP/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/ja-JP/deviceConfig.json b/src/i18n/locales/ja-JP/deviceConfig.json new file mode 100644 index 00000000..68bd011d --- /dev/null +++ b/src/i18n/locales/ja-JP/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "接続するデバイスを選択", + "tabDisplay": "表示", + "tabLora": "LoRa", + "tabNetwork": "ネットワーク", + "tabPosition": "位置", + "tabPower": "電源", + "tabSecurity": "セキュリティ" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/ja-JP/dialog.json b/src/i18n/locales/ja-JP/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/ja-JP/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/ja-JP/messages.json b/src/i18n/locales/ja-JP/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/ja-JP/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/ja-JP/moduleConfig.json b/src/i18n/locales/ja-JP/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/ja-JP/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/ja-JP/nodes.json b/src/i18n/locales/ja-JP/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/ja-JP/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/ja-JP/ui.json b/src/i18n/locales/ja-JP/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/ja-JP/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/nl-NL/channels.json b/src/i18n/locales/nl-NL/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/nl-NL/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/nl-NL/commandPalette.json b/src/i18n/locales/nl-NL/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/nl-NL/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/nl-NL/common.json b/src/i18n/locales/nl-NL/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/nl-NL/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/nl-NL/dashboard.json b/src/i18n/locales/nl-NL/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/nl-NL/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/nl-NL/deviceConfig.json b/src/i18n/locales/nl-NL/deviceConfig.json new file mode 100644 index 00000000..9c72f6f1 --- /dev/null +++ b/src/i18n/locales/nl-NL/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Apparaat", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/nl-NL/dialog.json b/src/i18n/locales/nl-NL/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/nl-NL/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/nl-NL/messages.json b/src/i18n/locales/nl-NL/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/nl-NL/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/nl-NL/moduleConfig.json b/src/i18n/locales/nl-NL/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/nl-NL/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/nl-NL/nodes.json b/src/i18n/locales/nl-NL/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/nl-NL/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/nl-NL/ui.json b/src/i18n/locales/nl-NL/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/nl-NL/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/pt-PT/channels.json b/src/i18n/locales/pt-PT/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/pt-PT/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/pt-PT/commandPalette.json b/src/i18n/locales/pt-PT/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/pt-PT/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/pt-PT/common.json b/src/i18n/locales/pt-PT/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/pt-PT/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/pt-PT/dashboard.json b/src/i18n/locales/pt-PT/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/pt-PT/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/pt-PT/deviceConfig.json b/src/i18n/locales/pt-PT/deviceConfig.json new file mode 100644 index 00000000..31f72bf4 --- /dev/null +++ b/src/i18n/locales/pt-PT/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Dispositivo", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/pt-PT/dialog.json b/src/i18n/locales/pt-PT/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/pt-PT/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/pt-PT/messages.json b/src/i18n/locales/pt-PT/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/pt-PT/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/pt-PT/moduleConfig.json b/src/i18n/locales/pt-PT/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/pt-PT/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/pt-PT/nodes.json b/src/i18n/locales/pt-PT/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/pt-PT/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/pt-PT/ui.json b/src/i18n/locales/pt-PT/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/pt-PT/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/sv-SE/channels.json b/src/i18n/locales/sv-SE/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/sv-SE/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/sv-SE/commandPalette.json b/src/i18n/locales/sv-SE/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/sv-SE/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/sv-SE/common.json b/src/i18n/locales/sv-SE/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/sv-SE/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/sv-SE/dashboard.json b/src/i18n/locales/sv-SE/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/sv-SE/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/sv-SE/deviceConfig.json b/src/i18n/locales/sv-SE/deviceConfig.json new file mode 100644 index 00000000..0c25a4cd --- /dev/null +++ b/src/i18n/locales/sv-SE/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Enhet", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Moduler" + }, + "device": { + "title": "Enhetsinställningar", + "description": "Settings for the device", + "buttonPin": { + "description": "Stift för knapp", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Stift för summer", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Inaktivera trippeltryck", + "label": "Inaktivera trippeltryck" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Inaktivera blinkande LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "Hur ofta nod-info ska sändas", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "POSIX-tidszonsträng för enheten", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "Hur enheten hanterar återutsändning", + "label": "Återutsändningsläge" + }, + "role": { + "description": "Vilken roll enheten har på nätet", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth-inställningar", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Aktivera eller inaktivera Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Metod för parkoppling", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Variant på displaylayout", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Vänd skärmen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "Koordinatformat" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/sv-SE/dialog.json b/src/i18n/locales/sv-SE/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/sv-SE/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/sv-SE/messages.json b/src/i18n/locales/sv-SE/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/sv-SE/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/sv-SE/moduleConfig.json b/src/i18n/locales/sv-SE/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/sv-SE/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/sv-SE/nodes.json b/src/i18n/locales/sv-SE/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/sv-SE/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/sv-SE/ui.json b/src/i18n/locales/sv-SE/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/sv-SE/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/tr-TR/channels.json b/src/i18n/locales/tr-TR/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/tr-TR/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/tr-TR/commandPalette.json b/src/i18n/locales/tr-TR/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/tr-TR/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/tr-TR/common.json b/src/i18n/locales/tr-TR/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/tr-TR/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/tr-TR/dashboard.json b/src/i18n/locales/tr-TR/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/tr-TR/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/tr-TR/deviceConfig.json b/src/i18n/locales/tr-TR/deviceConfig.json new file mode 100644 index 00000000..f18e84ea --- /dev/null +++ b/src/i18n/locales/tr-TR/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Cihaz", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Modüller" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/tr-TR/dialog.json b/src/i18n/locales/tr-TR/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/tr-TR/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/tr-TR/messages.json b/src/i18n/locales/tr-TR/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/tr-TR/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/tr-TR/moduleConfig.json b/src/i18n/locales/tr-TR/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/tr-TR/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/tr-TR/nodes.json b/src/i18n/locales/tr-TR/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/tr-TR/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/tr-TR/ui.json b/src/i18n/locales/tr-TR/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/tr-TR/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/uk-UA/channels.json b/src/i18n/locales/uk-UA/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/uk-UA/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/uk-UA/commandPalette.json b/src/i18n/locales/uk-UA/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/uk-UA/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/uk-UA/common.json b/src/i18n/locales/uk-UA/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/uk-UA/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/uk-UA/dashboard.json b/src/i18n/locales/uk-UA/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/uk-UA/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/uk-UA/deviceConfig.json b/src/i18n/locales/uk-UA/deviceConfig.json new file mode 100644 index 00000000..193c5494 --- /dev/null +++ b/src/i18n/locales/uk-UA/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Device", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/uk-UA/dialog.json b/src/i18n/locales/uk-UA/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/uk-UA/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/uk-UA/messages.json b/src/i18n/locales/uk-UA/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/uk-UA/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/uk-UA/moduleConfig.json b/src/i18n/locales/uk-UA/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/uk-UA/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/uk-UA/nodes.json b/src/i18n/locales/uk-UA/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/uk-UA/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/uk-UA/ui.json b/src/i18n/locales/uk-UA/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/uk-UA/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/zh-CN/channels.json b/src/i18n/locales/zh-CN/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/zh-CN/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/zh-CN/commandPalette.json b/src/i18n/locales/zh-CN/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/zh-CN/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/zh-CN/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/zh-CN/dashboard.json b/src/i18n/locales/zh-CN/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/zh-CN/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/zh-CN/deviceConfig.json b/src/i18n/locales/zh-CN/deviceConfig.json new file mode 100644 index 00000000..2812b2c0 --- /dev/null +++ b/src/i18n/locales/zh-CN/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "设备", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "转播模式" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/zh-CN/dialog.json b/src/i18n/locales/zh-CN/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/zh-CN/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/zh-CN/messages.json b/src/i18n/locales/zh-CN/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/zh-CN/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/zh-CN/moduleConfig.json b/src/i18n/locales/zh-CN/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/zh-CN/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/zh-CN/nodes.json b/src/i18n/locales/zh-CN/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/zh-CN/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/zh-CN/ui.json b/src/i18n/locales/zh-CN/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/zh-CN/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/zh-TW/channels.json b/src/i18n/locales/zh-TW/channels.json new file mode 100644 index 00000000..535b8e6b --- /dev/null +++ b/src/i18n/locales/zh-TW/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Name", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/zh-TW/commandPalette.json b/src/i18n/locales/zh-TW/commandPalette.json new file mode 100644 index 00000000..1eed8987 --- /dev/null +++ b/src/i18n/locales/zh-TW/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Map", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json new file mode 100644 index 00000000..8c434125 --- /dev/null +++ b/src/i18n/locales/zh-TW/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Apply", + "backupKey": "Backup Key", + "cancel": "Cancel", + "clearMessages": "Clear Messages", + "close": "Close", + "confirm": "Confirm", + "delete": "Delete", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remove", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Save", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/zh-TW/dashboard.json b/src/i18n/locales/zh-TW/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/zh-TW/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/zh-TW/deviceConfig.json b/src/i18n/locales/zh-TW/deviceConfig.json new file mode 100644 index 00000000..f95b32fd --- /dev/null +++ b/src/i18n/locales/zh-TW/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "设备", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "模組" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Unset", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/zh-TW/dialog.json b/src/i18n/locales/zh-TW/dialog.json new file mode 100644 index 00000000..6bc70259 --- /dev/null +++ b/src/i18n/locales/zh-TW/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/zh-TW/messages.json b/src/i18n/locales/zh-TW/messages.json new file mode 100644 index 00000000..101d3a0c --- /dev/null +++ b/src/i18n/locales/zh-TW/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Send" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/zh-TW/moduleConfig.json b/src/i18n/locales/zh-TW/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/zh-TW/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/zh-TW/nodes.json b/src/i18n/locales/zh-TW/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/zh-TW/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/zh-TW/ui.json b/src/i18n/locales/zh-TW/ui.json new file mode 100644 index 00000000..28342071 --- /dev/null +++ b/src/i18n/locales/zh-TW/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Map", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Language", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Dark", + "light": "Light", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} From 0b6ae0ce3263bb75043eedae752758841747b4f1 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 16 Jun 2025 15:14:59 -0400 Subject: [PATCH 09/37] fix: update crowdin config (#658) --- crowdin.yml | 2 +- src/components/LanguageSwitcher.tsx | 4 +- src/core/hooks/useLang.ts | 12 +- src/i18n/config.ts | 30 +- src/i18n/locales/cs-CZ/channels.json | 69 ---- src/i18n/locales/cs-CZ/commandPalette.json | 50 --- src/i18n/locales/cs-CZ/common.json | 119 ------ src/i18n/locales/cs-CZ/dashboard.json | 12 - src/i18n/locales/cs-CZ/deviceConfig.json | 428 -------------------- src/i18n/locales/cs-CZ/dialog.json | 159 -------- src/i18n/locales/cs-CZ/messages.json | 40 -- src/i18n/locales/cs-CZ/moduleConfig.json | 448 --------------------- src/i18n/locales/cs-CZ/nodes.json | 51 --- src/i18n/locales/cs-CZ/ui.json | 201 --------- src/i18n/locales/de-DE/channels.json | 69 ---- src/i18n/locales/de-DE/commandPalette.json | 50 --- src/i18n/locales/de-DE/common.json | 119 ------ src/i18n/locales/de-DE/dashboard.json | 12 - src/i18n/locales/de-DE/deviceConfig.json | 428 -------------------- src/i18n/locales/de-DE/dialog.json | 159 -------- src/i18n/locales/de-DE/messages.json | 40 -- src/i18n/locales/de-DE/moduleConfig.json | 448 --------------------- src/i18n/locales/de-DE/nodes.json | 51 --- src/i18n/locales/de-DE/ui.json | 201 --------- src/i18n/locales/es-ES/channels.json | 69 ---- src/i18n/locales/es-ES/commandPalette.json | 50 --- src/i18n/locales/es-ES/common.json | 119 ------ src/i18n/locales/es-ES/dashboard.json | 12 - src/i18n/locales/es-ES/deviceConfig.json | 428 -------------------- src/i18n/locales/es-ES/dialog.json | 159 -------- src/i18n/locales/es-ES/messages.json | 40 -- src/i18n/locales/es-ES/moduleConfig.json | 448 --------------------- src/i18n/locales/es-ES/nodes.json | 51 --- src/i18n/locales/es-ES/ui.json | 201 --------- src/i18n/locales/fi-FI/channels.json | 69 ---- src/i18n/locales/fi-FI/commandPalette.json | 50 --- src/i18n/locales/fi-FI/common.json | 119 ------ src/i18n/locales/fi-FI/dashboard.json | 12 - src/i18n/locales/fi-FI/deviceConfig.json | 428 -------------------- src/i18n/locales/fi-FI/dialog.json | 159 -------- src/i18n/locales/fi-FI/messages.json | 40 -- src/i18n/locales/fi-FI/moduleConfig.json | 448 --------------------- src/i18n/locales/fi-FI/nodes.json | 51 --- src/i18n/locales/fi-FI/ui.json | 201 --------- src/i18n/locales/fr-FR/channels.json | 69 ---- src/i18n/locales/fr-FR/commandPalette.json | 50 --- src/i18n/locales/fr-FR/common.json | 119 ------ src/i18n/locales/fr-FR/dashboard.json | 12 - src/i18n/locales/fr-FR/deviceConfig.json | 428 -------------------- src/i18n/locales/fr-FR/dialog.json | 159 -------- src/i18n/locales/fr-FR/messages.json | 40 -- src/i18n/locales/fr-FR/moduleConfig.json | 448 --------------------- src/i18n/locales/fr-FR/nodes.json | 51 --- src/i18n/locales/fr-FR/ui.json | 201 --------- src/i18n/locales/it-IT/channels.json | 69 ---- src/i18n/locales/it-IT/commandPalette.json | 50 --- src/i18n/locales/it-IT/common.json | 119 ------ src/i18n/locales/it-IT/dashboard.json | 12 - src/i18n/locales/it-IT/deviceConfig.json | 428 -------------------- src/i18n/locales/it-IT/dialog.json | 159 -------- src/i18n/locales/it-IT/messages.json | 40 -- src/i18n/locales/it-IT/moduleConfig.json | 448 --------------------- src/i18n/locales/it-IT/nodes.json | 51 --- src/i18n/locales/it-IT/ui.json | 201 --------- src/i18n/locales/ja-JP/channels.json | 69 ---- src/i18n/locales/ja-JP/commandPalette.json | 50 --- src/i18n/locales/ja-JP/common.json | 119 ------ src/i18n/locales/ja-JP/dashboard.json | 12 - src/i18n/locales/ja-JP/deviceConfig.json | 428 -------------------- src/i18n/locales/ja-JP/dialog.json | 159 -------- src/i18n/locales/ja-JP/messages.json | 40 -- src/i18n/locales/ja-JP/moduleConfig.json | 448 --------------------- src/i18n/locales/ja-JP/nodes.json | 51 --- src/i18n/locales/ja-JP/ui.json | 201 --------- src/i18n/locales/nl-NL/channels.json | 69 ---- src/i18n/locales/nl-NL/commandPalette.json | 50 --- src/i18n/locales/nl-NL/common.json | 119 ------ src/i18n/locales/nl-NL/dashboard.json | 12 - src/i18n/locales/nl-NL/deviceConfig.json | 428 -------------------- src/i18n/locales/nl-NL/dialog.json | 159 -------- src/i18n/locales/nl-NL/messages.json | 40 -- src/i18n/locales/nl-NL/moduleConfig.json | 448 --------------------- src/i18n/locales/nl-NL/nodes.json | 51 --- src/i18n/locales/nl-NL/ui.json | 201 --------- src/i18n/locales/pt-PT/channels.json | 69 ---- src/i18n/locales/pt-PT/commandPalette.json | 50 --- src/i18n/locales/pt-PT/common.json | 119 ------ src/i18n/locales/pt-PT/dashboard.json | 12 - src/i18n/locales/pt-PT/deviceConfig.json | 428 -------------------- src/i18n/locales/pt-PT/dialog.json | 159 -------- src/i18n/locales/pt-PT/messages.json | 40 -- src/i18n/locales/pt-PT/moduleConfig.json | 448 --------------------- src/i18n/locales/pt-PT/nodes.json | 51 --- src/i18n/locales/pt-PT/ui.json | 201 --------- src/i18n/locales/sv-SE/channels.json | 69 ---- src/i18n/locales/sv-SE/commandPalette.json | 50 --- src/i18n/locales/sv-SE/common.json | 119 ------ src/i18n/locales/sv-SE/dashboard.json | 12 - src/i18n/locales/sv-SE/deviceConfig.json | 428 -------------------- src/i18n/locales/sv-SE/dialog.json | 159 -------- src/i18n/locales/sv-SE/messages.json | 40 -- src/i18n/locales/sv-SE/moduleConfig.json | 448 --------------------- src/i18n/locales/sv-SE/nodes.json | 51 --- src/i18n/locales/sv-SE/ui.json | 201 --------- src/i18n/locales/tr-TR/channels.json | 69 ---- src/i18n/locales/tr-TR/commandPalette.json | 50 --- src/i18n/locales/tr-TR/common.json | 119 ------ src/i18n/locales/tr-TR/dashboard.json | 12 - src/i18n/locales/tr-TR/deviceConfig.json | 428 -------------------- src/i18n/locales/tr-TR/dialog.json | 159 -------- src/i18n/locales/tr-TR/messages.json | 40 -- src/i18n/locales/tr-TR/moduleConfig.json | 448 --------------------- src/i18n/locales/tr-TR/nodes.json | 51 --- src/i18n/locales/tr-TR/ui.json | 201 --------- src/i18n/locales/uk-UA/channels.json | 69 ---- src/i18n/locales/uk-UA/commandPalette.json | 50 --- src/i18n/locales/uk-UA/common.json | 119 ------ src/i18n/locales/uk-UA/dashboard.json | 12 - src/i18n/locales/uk-UA/deviceConfig.json | 428 -------------------- src/i18n/locales/uk-UA/dialog.json | 159 -------- src/i18n/locales/uk-UA/messages.json | 40 -- src/i18n/locales/uk-UA/moduleConfig.json | 448 --------------------- src/i18n/locales/uk-UA/nodes.json | 51 --- src/i18n/locales/uk-UA/ui.json | 201 --------- src/i18n/locales/zh-CN/channels.json | 69 ---- src/i18n/locales/zh-CN/commandPalette.json | 50 --- src/i18n/locales/zh-CN/common.json | 119 ------ src/i18n/locales/zh-CN/dashboard.json | 12 - src/i18n/locales/zh-CN/deviceConfig.json | 428 -------------------- src/i18n/locales/zh-CN/dialog.json | 159 -------- src/i18n/locales/zh-CN/messages.json | 40 -- src/i18n/locales/zh-CN/moduleConfig.json | 448 --------------------- src/i18n/locales/zh-CN/nodes.json | 51 --- src/i18n/locales/zh-CN/ui.json | 201 --------- src/i18n/locales/zh-TW/channels.json | 69 ---- src/i18n/locales/zh-TW/commandPalette.json | 50 --- src/i18n/locales/zh-TW/common.json | 119 ------ src/i18n/locales/zh-TW/dashboard.json | 12 - src/i18n/locales/zh-TW/deviceConfig.json | 428 -------------------- src/i18n/locales/zh-TW/dialog.json | 159 -------- src/i18n/locales/zh-TW/messages.json | 40 -- src/i18n/locales/zh-TW/moduleConfig.json | 448 --------------------- src/i18n/locales/zh-TW/nodes.json | 51 --- src/i18n/locales/zh-TW/ui.json | 201 --------- src/tests/setup.ts | 3 - 145 files changed, 31 insertions(+), 22098 deletions(-) delete mode 100644 src/i18n/locales/cs-CZ/channels.json delete mode 100644 src/i18n/locales/cs-CZ/commandPalette.json delete mode 100644 src/i18n/locales/cs-CZ/common.json delete mode 100644 src/i18n/locales/cs-CZ/dashboard.json delete mode 100644 src/i18n/locales/cs-CZ/deviceConfig.json delete mode 100644 src/i18n/locales/cs-CZ/dialog.json delete mode 100644 src/i18n/locales/cs-CZ/messages.json delete mode 100644 src/i18n/locales/cs-CZ/moduleConfig.json delete mode 100644 src/i18n/locales/cs-CZ/nodes.json delete mode 100644 src/i18n/locales/cs-CZ/ui.json delete mode 100644 src/i18n/locales/de-DE/channels.json delete mode 100644 src/i18n/locales/de-DE/commandPalette.json delete mode 100644 src/i18n/locales/de-DE/common.json delete mode 100644 src/i18n/locales/de-DE/dashboard.json delete mode 100644 src/i18n/locales/de-DE/deviceConfig.json delete mode 100644 src/i18n/locales/de-DE/dialog.json delete mode 100644 src/i18n/locales/de-DE/messages.json delete mode 100644 src/i18n/locales/de-DE/moduleConfig.json delete mode 100644 src/i18n/locales/de-DE/nodes.json delete mode 100644 src/i18n/locales/de-DE/ui.json delete mode 100644 src/i18n/locales/es-ES/channels.json delete mode 100644 src/i18n/locales/es-ES/commandPalette.json delete mode 100644 src/i18n/locales/es-ES/common.json delete mode 100644 src/i18n/locales/es-ES/dashboard.json delete mode 100644 src/i18n/locales/es-ES/deviceConfig.json delete mode 100644 src/i18n/locales/es-ES/dialog.json delete mode 100644 src/i18n/locales/es-ES/messages.json delete mode 100644 src/i18n/locales/es-ES/moduleConfig.json delete mode 100644 src/i18n/locales/es-ES/nodes.json delete mode 100644 src/i18n/locales/es-ES/ui.json delete mode 100644 src/i18n/locales/fi-FI/channels.json delete mode 100644 src/i18n/locales/fi-FI/commandPalette.json delete mode 100644 src/i18n/locales/fi-FI/common.json delete mode 100644 src/i18n/locales/fi-FI/dashboard.json delete mode 100644 src/i18n/locales/fi-FI/deviceConfig.json delete mode 100644 src/i18n/locales/fi-FI/dialog.json delete mode 100644 src/i18n/locales/fi-FI/messages.json delete mode 100644 src/i18n/locales/fi-FI/moduleConfig.json delete mode 100644 src/i18n/locales/fi-FI/nodes.json delete mode 100644 src/i18n/locales/fi-FI/ui.json delete mode 100644 src/i18n/locales/fr-FR/channels.json delete mode 100644 src/i18n/locales/fr-FR/commandPalette.json delete mode 100644 src/i18n/locales/fr-FR/common.json delete mode 100644 src/i18n/locales/fr-FR/dashboard.json delete mode 100644 src/i18n/locales/fr-FR/deviceConfig.json delete mode 100644 src/i18n/locales/fr-FR/dialog.json delete mode 100644 src/i18n/locales/fr-FR/messages.json delete mode 100644 src/i18n/locales/fr-FR/moduleConfig.json delete mode 100644 src/i18n/locales/fr-FR/nodes.json delete mode 100644 src/i18n/locales/fr-FR/ui.json delete mode 100644 src/i18n/locales/it-IT/channels.json delete mode 100644 src/i18n/locales/it-IT/commandPalette.json delete mode 100644 src/i18n/locales/it-IT/common.json delete mode 100644 src/i18n/locales/it-IT/dashboard.json delete mode 100644 src/i18n/locales/it-IT/deviceConfig.json delete mode 100644 src/i18n/locales/it-IT/dialog.json delete mode 100644 src/i18n/locales/it-IT/messages.json delete mode 100644 src/i18n/locales/it-IT/moduleConfig.json delete mode 100644 src/i18n/locales/it-IT/nodes.json delete mode 100644 src/i18n/locales/it-IT/ui.json delete mode 100644 src/i18n/locales/ja-JP/channels.json delete mode 100644 src/i18n/locales/ja-JP/commandPalette.json delete mode 100644 src/i18n/locales/ja-JP/common.json delete mode 100644 src/i18n/locales/ja-JP/dashboard.json delete mode 100644 src/i18n/locales/ja-JP/deviceConfig.json delete mode 100644 src/i18n/locales/ja-JP/dialog.json delete mode 100644 src/i18n/locales/ja-JP/messages.json delete mode 100644 src/i18n/locales/ja-JP/moduleConfig.json delete mode 100644 src/i18n/locales/ja-JP/nodes.json delete mode 100644 src/i18n/locales/ja-JP/ui.json delete mode 100644 src/i18n/locales/nl-NL/channels.json delete mode 100644 src/i18n/locales/nl-NL/commandPalette.json delete mode 100644 src/i18n/locales/nl-NL/common.json delete mode 100644 src/i18n/locales/nl-NL/dashboard.json delete mode 100644 src/i18n/locales/nl-NL/deviceConfig.json delete mode 100644 src/i18n/locales/nl-NL/dialog.json delete mode 100644 src/i18n/locales/nl-NL/messages.json delete mode 100644 src/i18n/locales/nl-NL/moduleConfig.json delete mode 100644 src/i18n/locales/nl-NL/nodes.json delete mode 100644 src/i18n/locales/nl-NL/ui.json delete mode 100644 src/i18n/locales/pt-PT/channels.json delete mode 100644 src/i18n/locales/pt-PT/commandPalette.json delete mode 100644 src/i18n/locales/pt-PT/common.json delete mode 100644 src/i18n/locales/pt-PT/dashboard.json delete mode 100644 src/i18n/locales/pt-PT/deviceConfig.json delete mode 100644 src/i18n/locales/pt-PT/dialog.json delete mode 100644 src/i18n/locales/pt-PT/messages.json delete mode 100644 src/i18n/locales/pt-PT/moduleConfig.json delete mode 100644 src/i18n/locales/pt-PT/nodes.json delete mode 100644 src/i18n/locales/pt-PT/ui.json delete mode 100644 src/i18n/locales/sv-SE/channels.json delete mode 100644 src/i18n/locales/sv-SE/commandPalette.json delete mode 100644 src/i18n/locales/sv-SE/common.json delete mode 100644 src/i18n/locales/sv-SE/dashboard.json delete mode 100644 src/i18n/locales/sv-SE/deviceConfig.json delete mode 100644 src/i18n/locales/sv-SE/dialog.json delete mode 100644 src/i18n/locales/sv-SE/messages.json delete mode 100644 src/i18n/locales/sv-SE/moduleConfig.json delete mode 100644 src/i18n/locales/sv-SE/nodes.json delete mode 100644 src/i18n/locales/sv-SE/ui.json delete mode 100644 src/i18n/locales/tr-TR/channels.json delete mode 100644 src/i18n/locales/tr-TR/commandPalette.json delete mode 100644 src/i18n/locales/tr-TR/common.json delete mode 100644 src/i18n/locales/tr-TR/dashboard.json delete mode 100644 src/i18n/locales/tr-TR/deviceConfig.json delete mode 100644 src/i18n/locales/tr-TR/dialog.json delete mode 100644 src/i18n/locales/tr-TR/messages.json delete mode 100644 src/i18n/locales/tr-TR/moduleConfig.json delete mode 100644 src/i18n/locales/tr-TR/nodes.json delete mode 100644 src/i18n/locales/tr-TR/ui.json delete mode 100644 src/i18n/locales/uk-UA/channels.json delete mode 100644 src/i18n/locales/uk-UA/commandPalette.json delete mode 100644 src/i18n/locales/uk-UA/common.json delete mode 100644 src/i18n/locales/uk-UA/dashboard.json delete mode 100644 src/i18n/locales/uk-UA/deviceConfig.json delete mode 100644 src/i18n/locales/uk-UA/dialog.json delete mode 100644 src/i18n/locales/uk-UA/messages.json delete mode 100644 src/i18n/locales/uk-UA/moduleConfig.json delete mode 100644 src/i18n/locales/uk-UA/nodes.json delete mode 100644 src/i18n/locales/uk-UA/ui.json delete mode 100644 src/i18n/locales/zh-CN/channels.json delete mode 100644 src/i18n/locales/zh-CN/commandPalette.json delete mode 100644 src/i18n/locales/zh-CN/common.json delete mode 100644 src/i18n/locales/zh-CN/dashboard.json delete mode 100644 src/i18n/locales/zh-CN/deviceConfig.json delete mode 100644 src/i18n/locales/zh-CN/dialog.json delete mode 100644 src/i18n/locales/zh-CN/messages.json delete mode 100644 src/i18n/locales/zh-CN/moduleConfig.json delete mode 100644 src/i18n/locales/zh-CN/nodes.json delete mode 100644 src/i18n/locales/zh-CN/ui.json delete mode 100644 src/i18n/locales/zh-TW/channels.json delete mode 100644 src/i18n/locales/zh-TW/commandPalette.json delete mode 100644 src/i18n/locales/zh-TW/common.json delete mode 100644 src/i18n/locales/zh-TW/dashboard.json delete mode 100644 src/i18n/locales/zh-TW/deviceConfig.json delete mode 100644 src/i18n/locales/zh-TW/dialog.json delete mode 100644 src/i18n/locales/zh-TW/messages.json delete mode 100644 src/i18n/locales/zh-TW/moduleConfig.json delete mode 100644 src/i18n/locales/zh-TW/nodes.json delete mode 100644 src/i18n/locales/zh-TW/ui.json diff --git a/crowdin.yml b/crowdin.yml index 14d994ec..2ac19722 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -7,4 +7,4 @@ preserve_hierarchy: true files: - source: "/src/i18n/locales/en/**/*.json" - translation: "/src/i18n/locales/%locale%/%original_file_name%" + translation: /src/i18n/locales/%two_letters_code%/**/%original_file_name% diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx index 03db9d9c..d33bc474 100644 --- a/src/components/LanguageSwitcher.tsx +++ b/src/components/LanguageSwitcher.tsx @@ -65,7 +65,7 @@ export default function LanguageSwitcher( "group-hover:text-gray-900 dark:group-hover:text-white", )} > - {currentLanguage.code.toUpperCase()} + {currentLanguage.name} @@ -73,7 +73,7 @@ export default function LanguageSwitcher( {supportedLanguages.map((language) => ( handleLanguageChange(language.code as LangCode)} + onClick={() => handleLanguageChange(language.code)} className="flex items-center justify-between cursor-pointer" >
diff --git a/src/core/hooks/useLang.ts b/src/core/hooks/useLang.ts index 62705bc3..156e697c 100644 --- a/src/core/hooks/useLang.ts +++ b/src/core/hooks/useLang.ts @@ -36,20 +36,22 @@ function useLang() { * Sets the i18n language. * * @param lng - The language tag to set + * @param persist - Whether to persist the language setting in local storage */ const set = useCallback( async (lng: LangCode, persist = true) => { if (i18n.language === lng) { return; } - console.info("set language:", lng); - if (persist) { - try { + + try { + console.info("setting language:", lng); + if (persist) { setLanguage({ language: lng }); - } catch (e) { - console.warn(e); } await i18n.changeLanguage(lng); + } catch (e) { + console.warn(e); } }, [i18n], diff --git a/src/i18n/config.ts b/src/i18n/config.ts index f203dab3..a028a25c 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -3,15 +3,29 @@ import { initReactI18next } from "react-i18next"; import Backend from "i18next-http-backend"; import LanguageDetector from "i18next-browser-languagedetector"; -export type Lang = { code: string; name: string; flag: string }; +export type Lang = { + code: Intl.Locale["language"]; + name: string; + flag: string; +}; + export type LangCode = Lang["code"]; +function getFlagEmoji(regionCode: string): string { + const A_LETTER_CODE = 0x1F1E6; + const a_char_code = "A".charCodeAt(0); + const codePoints = regionCode + .toUpperCase() + .split("") + .map((char) => A_LETTER_CODE + char.charCodeAt(0) - a_char_code); + return String.fromCodePoint(...codePoints); +} + export const supportedLanguages: Lang[] = [ - // { code: "de", name: "Deutsch", flag: "🇩🇪" }, - { code: "en", name: "English", flag: "🇺🇸" }, - // { code: "es", name: "Español", flag: "🇪🇸" }, - // { code: "fr", name: "Français", flag: "🇫🇷" }, - // { code: "zh", name: "中文", flag: "🇨🇳" }, + { code: "de", name: "German", flag: getFlagEmoji("de") }, + { code: "en", name: "English", flag: getFlagEmoji("us") }, + { code: "fi", name: "Finnish", flag: getFlagEmoji("fi") }, + { code: "sv", name: "Swedish", flag: getFlagEmoji("se") }, ]; i18next @@ -28,15 +42,13 @@ i18next }, detection: { order: ["navigator", "localStorage"], + caches: ["localStorage"], }, fallbackLng: { - "en-US": ["en"], - "en-CA": ["en-US", "en"], "default": ["en"], }, fallbackNS: ["common", "ui", "dialog"], debug: import.meta.env.MODE === "development", - supportedLngs: supportedLanguages?.map((lang) => lang.code), ns: [ "channels", "commandPalette", diff --git a/src/i18n/locales/cs-CZ/channels.json b/src/i18n/locales/cs-CZ/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/cs-CZ/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/cs-CZ/commandPalette.json b/src/i18n/locales/cs-CZ/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/cs-CZ/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/cs-CZ/common.json b/src/i18n/locales/cs-CZ/common.json deleted file mode 100644 index dd918f3b..00000000 --- a/src/i18n/locales/cs-CZ/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Použít", - "backupKey": "Backup Key", - "cancel": "Zrušit", - "clearMessages": "Clear Messages", - "close": "Zavřít", - "confirm": "Confirm", - "delete": "Smazat", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Zpráva", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Odstranit", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Uložit", - "scanQr": "Naskenovat QR kód", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/cs-CZ/dashboard.json b/src/i18n/locales/cs-CZ/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/cs-CZ/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/cs-CZ/deviceConfig.json b/src/i18n/locales/cs-CZ/deviceConfig.json deleted file mode 100644 index 6e5cb4e0..00000000 --- a/src/i18n/locales/cs-CZ/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Zařízení", - "tabDisplay": "Obrazovka", - "tabLora": "LoRa", - "tabNetwork": "Síť", - "tabPosition": "Pozice", - "tabPower": "Napájení", - "tabSecurity": "Zabezpečení" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Dvojité klepnutí jako stisk tlačítka" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX časové pásmo" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Režim opětovného vysílání" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Nastavení Bluetooth", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Povoleno" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Režim párování" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Šířka pásma" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignorovat MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Předvolba modemu" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK do MQTT" - }, - "overrideDutyCycle": { - "description": "Přepsat střídu", - "label": "Přepsat střídu" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Povoleno" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway/Brána" - }, - "ip": { - "description": "IP Address", - "label": "IP adresa" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Podsíť" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Povoleno" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Konfigurace" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Časová značka", - "unset": "Zrušit nastavení", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Povolit úsporný režim" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Nastavení napájení" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Soukromý klíč" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Veřejný klíč" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/cs-CZ/dialog.json b/src/i18n/locales/cs-CZ/dialog.json deleted file mode 100644 index cf2c0735..00000000 --- a/src/i18n/locales/cs-CZ/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Sériová komunikace", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Zpráva", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Napětí", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Jste si jistý?" - } -} diff --git a/src/i18n/locales/cs-CZ/messages.json b/src/i18n/locales/cs-CZ/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/cs-CZ/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/cs-CZ/moduleConfig.json b/src/i18n/locales/cs-CZ/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/cs-CZ/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/cs-CZ/nodes.json b/src/i18n/locales/cs-CZ/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/cs-CZ/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/cs-CZ/ui.json b/src/i18n/locales/cs-CZ/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/cs-CZ/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/de-DE/channels.json b/src/i18n/locales/de-DE/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/de-DE/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/de-DE/commandPalette.json b/src/i18n/locales/de-DE/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/de-DE/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/de-DE/common.json b/src/i18n/locales/de-DE/common.json deleted file mode 100644 index 6ee355ad..00000000 --- a/src/i18n/locales/de-DE/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Anwenden", - "backupKey": "Schlüssel sichern", - "cancel": "Abbrechen", - "clearMessages": "Nachrichten löschen", - "close": "Schließen", - "confirm": "Bestätigen", - "delete": "Löschen", - "dismiss": "Tastatur ausblenden", - "download": "Herunterladen", - "export": "Exportieren", - "generate": "Erzeugen", - "regenerate": "Neu erzeugen", - "import": "Importieren", - "message": "Nachricht", - "now": "Jetzt", - "ok": "Ok", - "print": "Drucken", - "rebootOtaNow": "Neustart in den OTA Modus", - "remove": "Entfernen", - "requestNewKeys": "Neue Schlüssel anfordern", - "requestPosition": "Standort anfordern", - "reset": "Zurücksetzen", - "save": "Speichern", - "scanQr": "QR Code scannen", - "traceRoute": "Route verfolgen" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web-Applikation" - }, - "loading": "Wird geladen...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Sprung", - "plural": "Sprünge" - }, - "hopsAway": { - "one": "{{count}} Sprung entfernt", - "plural": "{{count}} Sprünge entfernt", - "unknown": "Sprungweite unbekannt" - }, - "megahertz": "MHz", - "raw": "Einheitslos", - "meter": { - "one": "Meter", - "plural": "Meter", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/de-DE/dashboard.json b/src/i18n/locales/de-DE/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/de-DE/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/de-DE/deviceConfig.json b/src/i18n/locales/de-DE/deviceConfig.json deleted file mode 100644 index 9bd24e95..00000000 --- a/src/i18n/locales/de-DE/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Einstellungen", - "tabBluetooth": "Bluetooth", - "tabDevice": "Gerät", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Netzwerk", - "tabPosition": "Standort", - "tabPower": "Leistung", - "tabSecurity": "Sicherheit" - }, - "sidebar": { - "label": "Module" - }, - "device": { - "title": "Geräteeinstellungen", - "description": "Einstellungen für dieses Gerät", - "buttonPin": { - "description": "GPIO für Taste überschreiben", - "label": "GPIO Taste" - }, - "buzzerPin": { - "description": "GPIO für Summer überschreiben", - "label": "GPIO Summer" - }, - "disableTripleClick": { - "description": "Dreifachklicken deaktivieren", - "label": "Dreifachklicken deaktivieren" - }, - "doubleTapAsButtonPress": { - "description": "Doppeltes Tippen als Taste verwenden", - "label": "Doppelklick als Tastendruck" - }, - "ledHeartbeatDisabled": { - "description": "Die Herzschlag LED deaktivieren", - "label": "Herzschlag LED deaktivieren" - }, - "nodeInfoBroadcastInterval": { - "description": "Häufigkeit der Übertragung von Knoteninformationen", - "label": "Knoteninfo Übertragungsintervall" - }, - "posixTimezone": { - "description": "Zeichenfolge der POSIX Zeitzone für dieses Gerät", - "label": "POSIX Zeitzone" - }, - "rebroadcastMode": { - "description": "Wie Weiterleitungen behandelt werden", - "label": "Weiterleitungsmodus" - }, - "role": { - "description": "In welche Rolle das Gerät im Netz arbeitet", - "label": "Rolle" - } - }, - "bluetooth": { - "title": "Bluetooth Einstellungen", - "description": "Einstellungen für das Bluetooth Modul", - "note": "Hinweis: Einige Geräte (ESP32) können nicht gleichzeitig Bluetooth und WLAN verwenden.", - "enabled": { - "description": "Bluetooth aktivieren oder deaktivieren", - "label": "Aktiviert" - }, - "pairingMode": { - "description": "PIN Nummer Auswahlverhalten", - "label": "Kopplungsmodus" - }, - "pin": { - "description": "PIN Nummer zum Verbinden verwenden", - "label": "PIN Nummer" - } - }, - "display": { - "description": "Einstellungen für die Geräteanzeige", - "title": "Anzeigeeinstellungen", - "headingBold": { - "description": "Überschrifttext fett darstellen", - "label": "Fette Überschrift" - }, - "carouselDelay": { - "description": "Bestimmt wie schnell die Fenster durch gewechselt werden", - "label": "Karussellverzögerung" - }, - "compassNorthTop": { - "description": "Norden im Kompass immer oben anzeigen", - "label": "Kompass Norden oben" - }, - "displayMode": { - "description": "Variante des Anzeigelayout", - "label": "Anzeigemodus" - }, - "displayUnits": { - "description": "Zeige metrische oder imperiale Einheiten", - "label": "Anzeigeeinheiten" - }, - "flipScreen": { - "description": "Anzeige um 180 Grad drehen", - "label": "Anzeige drehen" - }, - "gpsDisplayUnits": { - "description": "Anzeigeformat der Koordinaten", - "label": "GPS Anzeigeformat" - }, - "oledType": { - "description": "Art des OLED Anzeige, die an dem Gerät angeschlossen ist", - "label": "OLED Typ" - }, - "screenTimeout": { - "description": "Anzeige nach dieser Zeit automatisch ausschalten", - "label": "Anzeigeabschaltung" - }, - "twelveHourClock": { - "description": "12-Stunden Format benutzen", - "label": "12-Stunden Uhr" - }, - "wakeOnTapOrMotion": { - "description": "Gerät durch Tippen oder Bewegung aufwecken", - "label": "Aufwachen durch Tippen oder Bewegung" - } - }, - "lora": { - "title": "Netzeinstellungen", - "description": "Einstellungen für das LoRa Netz", - "bandwidth": { - "description": "Kanalbandbreite in MHz", - "label": "Bandbreite" - }, - "boostedRxGain": { - "description": "Erhöhte Empfangsverstärkung", - "label": "Erhöhte Empfangsverstärkung" - }, - "codingRate": { - "description": "Kodierrate", - "label": "Fehlerkorrektur" - }, - "frequencyOffset": { - "description": "Frequenzversatz zur Kalibrierung von Oszillatorfehlern", - "label": "Frequenzversatz" - }, - "frequencySlot": { - "description": "LoRa Frequenzschlitz", - "label": "Frequenzschlitz" - }, - "hopLimit": { - "description": "Maximale Sprungweite", - "label": "Sprungweite" - }, - "ignoreMqtt": { - "description": "MQTT Nachrichten nicht über das Netz weiterleiten", - "label": "MQTT ignorieren" - }, - "modemPreset": { - "description": "Modem Voreinstellung die verwendet wird", - "label": "Modem Voreinstellungen" - }, - "okToMqtt": { - "description": "Wenn auf aktiviert, zeigt diese Einstellung an, dass der Benutzer das Weiterleiten von Nachrichten über MQTT akzeptiert. Wenn deaktiviert, werden entfernte Knoten aufgefordert, Nachrichten nicht über MQTT weiterzuleiten", - "label": "OK für MQTT" - }, - "overrideDutyCycle": { - "description": "Duty-Cycle überschreiben", - "label": "Duty-Cycle überschreiben" - }, - "overrideFrequency": { - "description": "Sendefrequenz überschreiben (MHz)", - "label": "Sendefrequenz überschreiben" - }, - "region": { - "description": "Legt die Region für Ihren Knoten fest", - "label": "Region" - }, - "spreadingFactor": { - "description": "Anzahl der Symbole zur Kodierung der Nutzdaten", - "label": "Spreizfaktor" - }, - "transmitEnabled": { - "description": "Sender (TX) des LoRa Funkgerätes aktivieren/deaktivieren", - "label": "Senden aktiviert" - }, - "transmitPower": { - "description": "Maximale Sendeleistung", - "label": "Sendeleistung" - }, - "usePreset": { - "description": "Eine der vordefinierten Modem Voreinstellungen verwenden", - "label": "Voreinstellung verwenden" - }, - "meshSettings": { - "description": "Einstellungen für das LoRa Netz", - "label": "Netzeinstellungen" - }, - "waveformSettings": { - "description": "Einstellungen für die LoRa Wellenform", - "label": "Einstellungen der Wellenform" - }, - "radioSettings": { - "label": "Radio-Einstellungen", - "description": "Einstellungen für das LoRa Funkgerät" - } - }, - "network": { - "title": "WLAN Einstellungen", - "description": "WLAN Funkeinstellungen", - "note": "Hinweis: Einige Geräte (ESP32) können nicht gleichzeitig Bluetooth und WLAN verwenden.", - "addressMode": { - "description": "Auswahl der IP Adressenzuweisung", - "label": "IP Adressenmodus" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Aktivieren oder deaktivieren sie den Ethernet Anschluss", - "label": "Aktiviert" - }, - "gateway": { - "description": "Standard Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Netzwerkpasswort", - "label": "PSK" - }, - "ssid": { - "description": "Netzwerkname", - "label": "SSID" - }, - "subnet": { - "description": "Subnetzmaske", - "label": "Subnetz" - }, - "wifiEnabled": { - "description": "Aktivieren oder deaktivieren Sie die WLAN Übertragung", - "label": "Aktiviert" - }, - "meshViaUdp": { - "label": "Netz über UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Einstellung des Ethernet Ports", - "label": "Ethernet Einstellung" - }, - "ipConfigSettings": { - "description": "Einstellung der IP Adresse", - "label": "IP Adresseinstellungen" - }, - "ntpConfigSettings": { - "description": "NTP Server Einstellungen", - "label": "NTP Einstellungen" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog Einstellung", - "label": "Rsyslog Einstellung" - }, - "udpConfigSettings": { - "description": "UDP über Netz Einstellung", - "label": "UDP Konfiguration" - } - }, - "position": { - "title": "Standorteinstellung", - "description": "Einstellungen für das Standortmodul", - "broadcastInterval": { - "description": "Wie oft Ihr Standort über das Netz gesendet wird", - "label": "Übertragungsintervall" - }, - "enablePin": { - "description": "Überschreiben des GPIO der das GPS-Modul aktiviert", - "label": "GPIO GPS aktivieren" - }, - "fixedPosition": { - "description": "GPS Standort nicht senden, sondern manuell angegeben", - "label": "Fester Standort" - }, - "gpsMode": { - "description": "Einstellung, ob GPS des Geräts aktiviert, deaktiviert oder nicht vorhanden ist", - "label": "GPS Modus" - }, - "gpsUpdateInterval": { - "description": "Wie oft ein GPS Standort ermittelt werden soll", - "label": "GPS Aktualisierungsintervall" - }, - "positionFlags": { - "description": "Optionalen, die bei der Zusammenstellung von Standortnachrichten enthalten sein sollen. Je mehr Optionen ausgewählt werden, desto größer wird die Nachricht und die längere Übertragungszeit erhöht das Risiko für einen Nachrichtenverlust.", - "label": "Standort Optionen" - }, - "receivePin": { - "description": "GPIO Pin für serielles Empfangen (RX) des GPS-Moduls überschreiben", - "label": "GPIO Empfangen" - }, - "smartPositionEnabled": { - "description": "Standort nur verschicken, wenn eine sinnvolle Standortänderung stattgefunden hat", - "label": "Intelligenten Standort aktivieren" - }, - "smartPositionMinDistance": { - "description": "Mindestabstand (in Meter), die vor dem Senden einer Standortaktualisierung zurückgelegt werden muss", - "label": "Minimale Entfernung für intelligenten Standort" - }, - "smartPositionMinInterval": { - "description": "Minimales Intervall (in Sekunden), das vor dem Senden einer Standortaktualisierung vergangen sein muss", - "label": "Minimales Intervall für intelligenten Standort" - }, - "transmitPin": { - "description": "GPIO Pin für serielles Senden (TX) des GPS-Moduls überschreiben", - "label": "GPIO Senden" - }, - "intervalsSettings": { - "description": "Wie oft Standortaktualisierungen gesendet werden", - "label": "Intervalle" - }, - "flags": { - "placeholder": "Standort Optionen auswählen", - "altitude": "Höhe", - "altitudeGeoidalSeparation": "Geoidale Höhentrennung", - "altitudeMsl": "Höhe in Bezug auf Meeresspiegel", - "dop": "Dilution of Präzision (DOP) PDOP standardmäßig verwenden", - "hdopVdop": "Wenn DOP gesetzt ist, wird HDOP / VDOP anstelle von PDOP verwendet", - "numSatellites": "Anzahl Satelliten", - "sequenceNumber": "Sequenznummer", - "timestamp": "Zeitstempel", - "unset": "Nicht konfiguriert", - "vehicleHeading": "Fahrzeugsteuerkurs", - "vehicleSpeed": "Fahrzeuggeschwindigkeit" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Zur Optimierung der Genauigkeit bei der Akkuspannunsmessung", - "label": "ADC Multiplikationsfaktor" - }, - "ina219Address": { - "description": "Adresse des INA219 Stromsensors", - "label": "INA219 Adresse" - }, - "lightSleepDuration": { - "description": "Wie lange das Gerät im leichten Schlafmodus ist", - "label": "Dauer leichter Schlafmodus" - }, - "minimumWakeTime": { - "description": "Minimale Zeitspanne für die das Gerät aktiv bleibt, nachdem es eine Nachricht empfangen hat", - "label": "Minimale Aufwachzeit" - }, - "noConnectionBluetoothDisabled": { - "description": "Wenn das Gerät keine Bluetooth Verbindung erhält, wird der BLE Funk nach dieser Zeit deaktiviert", - "label": "Keine Verbindung, Bluetooth deaktiviert" - }, - "powerSavingEnabled": { - "description": "Auswählen, wenn aus einer Stromquelle mit niedriger Kapazität (z.B Solar) betrieben wird, um den Stromverbrauch so weit wie möglich zu minimieren.", - "label": "Energiesparmodus aktivieren" - }, - "shutdownOnBatteryDelay": { - "description": "Verzögerung bis zum Abschalten der Knoten sich im Akkubetrieb befindet. 0 für unbegrenzt", - "label": "Verzögerung Akkuabschaltung" - }, - "superDeepSleepDuration": { - "description": "Wie lange das Gerät im supertiefen Schlafmodus ist", - "label": "Dauer Supertiefschlaf" - }, - "powerConfigSettings": { - "description": "Einstellungen für das Energiemodul", - "label": "Power Konfiguration" - }, - "sleepSettings": { - "description": "Einstellungen Ruhezustand für das Energiemodul", - "label": "Einstellung Ruhezustand" - } - }, - "security": { - "description": "Sicherheitseinstellungen", - "title": "Sicherheitseinstellungen", - "button_backupKey": "Schlüssel sichern", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Veraltete Administrierung erlauben" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Debug-Protokoll API aktivieren" - }, - "managed": { - "description": "Wenn aktiviert, können die Geräteeinstellungen nur von einem entfernten Administratorknoten über administrative Nachrichten geändert werden. Aktivieren Sie diese Option nur, wenn mindestens ein geeigneter Administratorknoten eingerichtet, und desen öffentlicher Schlüssel wird in einem der obigen Felder gespeichert wurde.", - "label": "Verwaltet" - }, - "privateKey": { - "description": "Wird verwendet, um einen gemeinsamen Schlüssel mit einem entfernten Gerät zu erstellen", - "label": "Privater Schlüssel" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Öffentlicher Schlüssel" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Erster Admin-Schlüssel" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Zweiter Admin-Schlüssel" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serielle Ausgabe aktiviert" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Dritter Admin-Schlüssel" - }, - "adminSettings": { - "description": "Administrator Einstellungen", - "label": "Administrator Einstellungen" - }, - "loggingSettings": { - "description": "Einstellungen für die Protokollierung", - "label": "Protokolleinstellungen" - } - } -} diff --git a/src/i18n/locales/de-DE/dialog.json b/src/i18n/locales/de-DE/dialog.json deleted file mode 100644 index 85b03e0e..00000000 --- a/src/i18n/locales/de-DE/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "Diese Aktion wird den Nachrichtenverlauf löschen. Dies kann nicht rückgängig gemacht werden. Sind Sie sicher, dass Sie fortfahren möchten?", - "title": "Alle Nachrichten löschen" - }, - "deviceName": { - "description": "Das Gerät wird neu gestartet, sobald die Einstellung gespeichert ist.", - "longName": "Langer Name", - "shortName": "Kurzname", - "title": "Gerätename ändern" - }, - "import": { - "description": "Die aktuelle LoRa Einstellung wird überschrieben.", - "error": { - "invalidUrl": "Ungültige Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Kanalsammlung / QR-Code URL", - "channels": "Channels:", - "usePreset": "Voreinstellung verwenden?", - "title": "Kanalsammlung importieren" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Standort: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Vorab verteilten Schlüssel (PSK) neu erstellen?", - "description": "Sind Sie sicher, dass Sie den vorab verteilten Schlüssel neu erstellen möchten?", - "regenerate": "Neu erstellen" - }, - "newDeviceDialog": { - "title": "Neues Gerät verbinden", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Seriell", - "useHttps": "HTTPS verwenden", - "connecting": "Connecting...", - "connect": "Verbindung herstellen", - "connectionFailedAlert": { - "title": "Verbindung fehlgeschlagen", - "descriptionPrefix": "Verbindung zum Gerät fehlgeschlagen. ", - "httpsHint": "Wenn Sie HTTPS verwenden, müssen Sie möglicherweise zuerst ein selbstsigniertes Zertifikat akzeptieren. ", - "openLinkPrefix": "Öffnen Sie ", - "openLinkSuffix": "in einem neuen Tab", - "acceptTlsWarningSuffix": ", akzeptieren Sie alle TLS-Warnungen, wenn Sie dazu aufgefordert werden, dann versuchen Sie es erneut", - "learnMoreLink": "Mehr erfahren" - }, - "httpConnection": { - "label": "IP Adresse/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "Noch keine Geräte gekoppelt.", - "newDeviceButton": "Neues Gerät", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "Noch keine Geräte gekoppelt.", - "newDeviceButton": "Neues Gerät" - }, - "validation": { - "requiresFeatures": "Dieser Verbindungstyp erfordert <0>. Bitte verwenden Sie einen unterstützten Browser, wie Chrome oder Edge.", - "requiresSecureContext": "Diese Anwendung erfordert einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost.", - "additionallyRequiresSecureContext": "Zusätzlich erfordert es einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost." - } - }, - "nodeDetails": { - "message": "Nachricht", - "requestPosition": "Standort anfordern", - "traceRoute": "Route verfolgen", - "airTxUtilization": "Auslastung Sendezeit", - "allRawMetrics": "Alle Rohdaten", - "batteryLevel": "Akkustand", - "channelUtilization": "Kanalauslastung", - "details": "Details:", - "deviceMetrics": "Gerätekennzahlen:", - "hardware": "Hardware: ", - "lastHeard": "Zuletzt gehört: ", - "nodeHexPrefix": "Knoten ID: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Spannung", - "title": "Knotendetails für {{identifier}}", - "ignoreNode": "Knoten ignorieren", - "removeNode": "Knoten entfernen", - "unignoreNode": "Knoten akzeptieren" - }, - "pkiBackup": { - "description": "Wir empfehlen die regelmäßige Sicherung Ihrer Schlüsseldaten. Möchten Sie jetzt sicheren?", - "loseKeysWarning": "Wenn Sie Ihre Schlüssel verlieren, müssen Sie Ihr Gerät zurücksetzen.", - "secureBackup": "Es ist wichtig, dass Sie Ihre öffentlichen und privaten Schlüssel sichern und diese sicher speichern!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Schlüssel sichern" - }, - "pkiRegenerate": { - "description": "Sind Sie sicher, dass Sie Schlüsselpaar neu erstellen möchten?", - "title": "Schlüsselpaar neu erstellen" - }, - "qr": { - "addChannels": "Kanäle hinzufügen", - "replaceChannels": "Kanäle ersetzen", - "description": "Die aktuelle LoRa Einstellung wird ebenfalls geteilt.", - "sharableUrl": "Teilbare URL", - "title": "QR Code Erzeugen" - }, - "rebootOta": { - "title": "Neustart planen", - "description": "Startet den verbundenen Knoten nach einer Verzögerung in den OTA (Over-the-Air) Modus.", - "enterDelay": "Verzögerung eingeben (Sek.)", - "scheduled": "Neustart wurde geplant" - }, - "reboot": { - "title": "Neustart planen", - "description": "Startet den verbundenen Knoten nach x Minuten neu." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "Dies entfernt den Knoten vom Gerät und fordert neue Schlüssel an.", - "keyMismatchReasonSuffix": ". Dies liegt daran, dass der aktuelle öffentliche Schlüssel des entfernten Knotens nicht mit dem zuvor gespeicherten Schlüssel für diesen Knoten übereinstimmt.", - "unableToSendDmPrefix": "Ihr Knoten kann keine Direktnachricht an folgenden Knoten senden: " - }, - "acceptNewKeys": "Neue Schlüssel akzeptieren", - "title": "Schlüsselfehler - {{identifier}}" - }, - "removeNode": { - "description": "Sind Sie sicher, dass Sie diesen Knoten entfernen möchten?", - "title": "Knoten entfernen?" - }, - "shutdown": { - "title": "Herunterfahren planen", - "description": "Schaltet den verbundenen Knoten nach x Minuten aus." - }, - "traceRoute": { - "routeToDestination": "Route zum Ziel:", - "routeBack": "Route zurück:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Ja, ich weiß, was ich tue!", - "conjunction": " und der Blog-Beitrag über ", - "postamble": " und verstehen die Auswirkungen einer Veränderung der Rolle.", - "preamble": "Ich habe die", - "choosingRightDeviceRole": "Wahl der richtigen Geräterolle", - "deviceRoleDocumentation": "Dokumentation der Geräterolle", - "title": "Bist Du sicher?" - } -} diff --git a/src/i18n/locales/de-DE/messages.json b/src/i18n/locales/de-DE/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/de-DE/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/de-DE/moduleConfig.json b/src/i18n/locales/de-DE/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/de-DE/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/de-DE/nodes.json b/src/i18n/locales/de-DE/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/de-DE/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/de-DE/ui.json b/src/i18n/locales/de-DE/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/de-DE/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/es-ES/channels.json b/src/i18n/locales/es-ES/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/es-ES/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/es-ES/commandPalette.json b/src/i18n/locales/es-ES/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/es-ES/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/es-ES/common.json b/src/i18n/locales/es-ES/common.json deleted file mode 100644 index e5da6d9f..00000000 --- a/src/i18n/locales/es-ES/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Aplique", - "backupKey": "Backup Key", - "cancel": "Cancelar", - "clearMessages": "Clear Messages", - "close": "Cerrar", - "confirm": "Confirm", - "delete": "Eliminar", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Mensaje", - "now": "Now", - "ok": "Vale", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Quitar", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reiniciar", - "save": "Guardar", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/es-ES/dashboard.json b/src/i18n/locales/es-ES/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/es-ES/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/es-ES/deviceConfig.json b/src/i18n/locales/es-ES/deviceConfig.json deleted file mode 100644 index dfa21d26..00000000 --- a/src/i18n/locales/es-ES/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Dispositivo", - "tabDisplay": "Pantalla", - "tabLora": "LoRa", - "tabNetwork": "Red", - "tabPosition": "Posición", - "tabPower": "Energía", - "tabSecurity": "Seguridad" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Modo de emparejamiento" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Región" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "Configuración UDP" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Sin configurar", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Clave privada" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Clave Pública" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/es-ES/dialog.json b/src/i18n/locales/es-ES/dialog.json deleted file mode 100644 index 97f12d8f..00000000 --- a/src/i18n/locales/es-ES/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Mensaje", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Tensión", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "¿Estás seguro?" - } -} diff --git a/src/i18n/locales/es-ES/messages.json b/src/i18n/locales/es-ES/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/es-ES/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/es-ES/moduleConfig.json b/src/i18n/locales/es-ES/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/es-ES/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/es-ES/nodes.json b/src/i18n/locales/es-ES/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/es-ES/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/es-ES/ui.json b/src/i18n/locales/es-ES/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/es-ES/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/fi-FI/channels.json b/src/i18n/locales/fi-FI/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/fi-FI/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/fi-FI/commandPalette.json b/src/i18n/locales/fi-FI/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/fi-FI/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/fi-FI/common.json b/src/i18n/locales/fi-FI/common.json deleted file mode 100644 index ed81cf16..00000000 --- a/src/i18n/locales/fi-FI/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Hyväksy", - "backupKey": "Varmuuskopioi avain", - "cancel": "Peruuta", - "clearMessages": "Tyhjennä viestit", - "close": "Sulje", - "confirm": "Vahvista", - "delete": "Poista", - "dismiss": "Hylkää", - "download": "Lataa", - "export": "Vie", - "generate": "Luo", - "regenerate": "Luo uudelleen", - "import": "Tuo", - "message": "Viesti", - "now": "Nyt", - "ok": "OK", - "print": "Tulosta", - "rebootOtaNow": "Käynnistä uudelleen OTA-tilaan nyt", - "remove": "Poista", - "requestNewKeys": "Pyydä uudet avaimet", - "requestPosition": "Pyydä sijaintia", - "reset": "Palauta", - "save": "Tallenna", - "scanQr": "Skannaa QR-koodi", - "traceRoute": "Reitinselvitys" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Ladataan...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hyppy", - "plural": "Hyppyä" - }, - "hopsAway": { - "one": "{{count}} hypyn päässä", - "plural": "{{count}} hypyn päässä", - "unknown": "Hyppyjen määrä tuntematon" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/fi-FI/dashboard.json b/src/i18n/locales/fi-FI/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/fi-FI/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/fi-FI/deviceConfig.json b/src/i18n/locales/fi-FI/deviceConfig.json deleted file mode 100644 index a42db3e8..00000000 --- a/src/i18n/locales/fi-FI/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Asetukset", - "tabBluetooth": "Bluetooth", - "tabDevice": "Laite", - "tabDisplay": "Näyttö", - "tabLora": "LoRa", - "tabNetwork": "Verkko", - "tabPosition": "Sijainti", - "tabPower": "Virta", - "tabSecurity": "Turvallisuus" - }, - "sidebar": { - "label": "Moduulit" - }, - "device": { - "title": "Laitteen asetukset", - "description": "Laitteen asetukset", - "buttonPin": { - "description": "Painikkeen pinnin ohitus", - "label": "Painikkeen pinni" - }, - "buzzerPin": { - "description": "Summerin pinnin ohitus", - "label": "Summerin pinni" - }, - "disableTripleClick": { - "description": "Poista kolmoisklikkaus käytöstä", - "label": "Poista kolmoisklikkaus käytöstä" - }, - "doubleTapAsButtonPress": { - "description": "Käsittele kaksoisnapautus painikkeen painalluksena", - "label": "Kaksoisnapautus painikkeen painalluksena" - }, - "ledHeartbeatDisabled": { - "description": "Poista ledin vilkkuminen käytöstä", - "label": "Ledin vilkkuminen poistettu käytöstä" - }, - "nodeInfoBroadcastInterval": { - "description": "Kuinka usein laitteen tiedot lähetetään verkkoon", - "label": "Laitteen tietojen lähetyksen aikaväli" - }, - "posixTimezone": { - "description": "POSIX-aikavyöhykkeen merkkijono laitetta varten", - "label": "POSIX-aikavyöhyke" - }, - "rebroadcastMode": { - "description": "Kuinka uudelleenlähetyksiä käsitellään", - "label": "Uudelleenlähetyksen tila" - }, - "role": { - "description": "Mikä rooli laitteella on mesh-verkossa", - "label": "Rooli" - } - }, - "bluetooth": { - "title": "Bluetooth asetukset", - "description": "Bluetooth moduulin asetukset", - "note": "Huomautus: Jotkin laitteet (ESP32) eivät voi käyttää bluetoothia sekä WiFiä samanaikaisesti.", - "enabled": { - "description": "Ota Bluetooth käyttöön tai poista käytöstä", - "label": "Käytössä" - }, - "pairingMode": { - "description": "PIN-koodin valinnan käyttäytyminen.", - "label": "Paritustila" - }, - "pin": { - "description": "Bluetooth PIN-koodi, jota käytetään pariliitettäessä", - "label": "PIN" - } - }, - "display": { - "description": "Laitteen näytön asetukset", - "title": "Näyttöasetukset", - "headingBold": { - "description": "Lihavoi otsikkoteksti", - "label": "Lihavoitu otsikko" - }, - "carouselDelay": { - "description": "Kuinka nopeasti ikkunat kulkevat", - "label": "Karusellin Viive" - }, - "compassNorthTop": { - "description": "Kiinnitä pohjoinen kompassin yläreunaan", - "label": "Kompassin pohjoinen ylhäällä" - }, - "displayMode": { - "description": "Näytön asettelun vaihtoehdot", - "label": "Näyttötila" - }, - "displayUnits": { - "description": "Näytä metriset tai imperiaaliset yksiköt", - "label": "Näyttöyksiköt" - }, - "flipScreen": { - "description": "Käännä näyttöä 180 astetta", - "label": "Käännä näyttö" - }, - "gpsDisplayUnits": { - "description": "Koordinaattien näyttömuoto", - "label": "GPS näyttöyksiköt" - }, - "oledType": { - "description": "Laitteeseen liitetyn OLED-näytön tyyppi", - "label": "OLED-tyyppi" - }, - "screenTimeout": { - "description": "Sammuta näyttö tämän ajan jälkeen", - "label": "Näytön aikakatkaisu" - }, - "twelveHourClock": { - "description": "Käytä 12 tunnin kelloa", - "label": "12 tunnin kello" - }, - "wakeOnTapOrMotion": { - "description": "Herätä laite napauttamalla tai liikkeestä", - "label": "Herätä napauttamalla tai liikkeellä" - } - }, - "lora": { - "title": "Mesh-verkon asetukset", - "description": "LoRa-verkon asetukset", - "bandwidth": { - "description": "Kanavan kaistanleveys MHz", - "label": "Kaistanleveys" - }, - "boostedRxGain": { - "description": "RX tehostettu vahvistus", - "label": "RX tehostettu vahvistus" - }, - "codingRate": { - "description": "Koodausnopeuden nimittäjä", - "label": "Koodausnopeus" - }, - "frequencyOffset": { - "description": "Taajuuskorjaus kalibrointivirheiden korjaamiseksi", - "label": "Taajuuspoikkeama" - }, - "frequencySlot": { - "description": "LoRa-taajuuden kanavanumero", - "label": "Taajuuspaikka" - }, - "hopLimit": { - "description": "Maksimimäärä hyppyjä", - "label": "Hyppyraja" - }, - "ignoreMqtt": { - "description": "Älä välitä MQTT-viestejä mesh-verkon yli", - "label": "Ohita MQTT" - }, - "modemPreset": { - "description": "Käytössä olevan modeemin esiasetus", - "label": "Modeemin esiasetus" - }, - "okToMqtt": { - "description": "Kun asetetaan arvoksi true, tämä asetus tarkoittaa, että käyttäjä hyväksyy paketin lähettämisen MQTT:lle. Jos asetetaan arvoksi false, etälaitteita pyydetään olemaan välittämättä paketteja MQTT:lle", - "label": "MQTT päällä" - }, - "overrideDutyCycle": { - "description": "Ohita käyttöaste (Duty Cycle)", - "label": "Ohita käyttöaste (Duty Cycle)" - }, - "overrideFrequency": { - "description": "Käytä mukautettua taajuutta", - "label": "Mukautettu taajuus" - }, - "region": { - "description": "Asettaa alueen laitteelle", - "label": "Alue" - }, - "spreadingFactor": { - "description": "Ilmaisee symbolia kohden lähetettävien taajuuksien määrän", - "label": "Levennyskerroin" - }, - "transmitEnabled": { - "description": "LoRa-radion lähetyksen (TX) käyttöönotto tai poiskytkentä", - "label": "Lähetys käytössä" - }, - "transmitPower": { - "description": "Suurin lähetysteho", - "label": "Lähetysteho" - }, - "usePreset": { - "description": "Käytä ennalta määriteltyä modeemin esiasetusta", - "label": "Käytä esiasetusta" - }, - "meshSettings": { - "description": "LoRa-verkon asetukset", - "label": "Mesh-verkon asetukset" - }, - "waveformSettings": { - "description": "LoRa-aaltomuodon asetukset", - "label": "Signaalimuodon asetukset" - }, - "radioSettings": { - "label": "Radioasetukset", - "description": "LoRa-laitteen asetukset" - } - }, - "network": { - "title": "WiFi-asetukset", - "description": "WiFi-radion asetukset", - "note": "Huomautus: Jotkin laitteet (ESP32) eivät voi käyttää sekä Bluetoothia että WiFiä samanaikaisesti.", - "addressMode": { - "description": "Osoitteen määrityksen valinta", - "label": "Osoitetila" - }, - "dns": { - "description": "DNS-palvelin", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Ota käyttöön tai poista käytöstä ethernet-portti", - "label": "Käytössä" - }, - "gateway": { - "description": "Oletusyhdyskäytävä", - "label": "Yhdyskäytävä" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Verkon salasana", - "label": "PSK" - }, - "ssid": { - "description": "Verkon nimi", - "label": "SSID" - }, - "subnet": { - "description": "Aliverkon peite", - "label": "Aliverkko" - }, - "wifiEnabled": { - "description": "Ota WiFi käyttöön tai poista se käytöstä", - "label": "Käytössä" - }, - "meshViaUdp": { - "label": "Mesh UDP:n kautta" - }, - "ntpServer": { - "label": "NTP-palvelin" - }, - "rsyslogServer": { - "label": "Rsyslog-palvelin" - }, - "ethernetConfigSettings": { - "description": "Ethernet-portin asetukset", - "label": "Ethernet-asetukset" - }, - "ipConfigSettings": { - "description": "IP-osoitteen asetukset", - "label": "IP-osoitteen asetukset" - }, - "ntpConfigSettings": { - "description": "NTP-asetukset", - "label": "NTP-asetukset" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog määritykset", - "label": "Rsyslog määritykset" - }, - "udpConfigSettings": { - "description": "UDP-yhdeyden asetukset", - "label": "UDP-asetukset" - } - }, - "position": { - "title": "Sijainnin asetukset", - "description": "Sijaintimoduulin asetukset", - "broadcastInterval": { - "description": "Kuinka usein sijainti lähetetään mesh-verkon yli", - "label": "Lähetyksen aikaväli" - }, - "enablePin": { - "description": "GPS-moduulin käyttöönottopinnin korvaus", - "label": "Ota pinni käytöön" - }, - "fixedPosition": { - "description": "Älä raportoi GPS-sijaintia, vaan käytä manuaalisesti määritettyä sijaintia", - "label": "Kiinteä sijainti" - }, - "gpsMode": { - "description": "Määritä, onko laitteen GPS käytössä, pois päältä vai puuttuuko se kokonaan", - "label": "GSP-tila" - }, - "gpsUpdateInterval": { - "description": "Kuinka usein GPS-paikannus suoritetaan", - "label": "GPS-päivitysväli" - }, - "positionFlags": { - "description": "Valinnaiset kentät, jotka voidaan sisällyttää sijaintiviesteihin. Mitä enemmän kenttiä valitaan, sitä suurempi viesti on, mikä johtaa pidempään lähetysaikaan ja suurempaan pakettihäviöriskiin.", - "label": "Sijaintimerkinnät" - }, - "receivePin": { - "description": "GPS-moduulin käyttöönottopinnin korvaus", - "label": "Vastaanoton pinni" - }, - "smartPositionEnabled": { - "description": "Lähetä sijainti vain, kun sijainnissa on tapahtunut merkittävä muutos", - "label": "Ota älykäs sijainti käyttöön" - }, - "smartPositionMinDistance": { - "description": "Vähimmäisetäisyys (metreinä), joka on kuljettava ennen sijaintipäivityksen lähettämistä", - "label": "Älykkään sijainnin minimietäisyys" - }, - "smartPositionMinInterval": { - "description": "Lyhin aikaväli (sekunteina), joka on kuluttava ennen sijaintipäivityksen lähettämistä", - "label": "Älykkään sijainnin vähimmäisetäisyys" - }, - "transmitPin": { - "description": "GPS-moduulin käyttöönottopinnin korvaus", - "label": "Lähetyksen pinni" - }, - "intervalsSettings": { - "description": "Kuinka usein sijaintipäivitykset lähetetään", - "label": "Aikaväli" - }, - "flags": { - "placeholder": "Valitse sijaintiasetukset...", - "altitude": "Korkeus", - "altitudeGeoidalSeparation": "Korkeuden geoidinen erotus", - "altitudeMsl": "Korkeus on mitattu merenpinnan tasosta", - "dop": "Tarkkuuden heikkenemä (DOP), oletuksena käytetään PDOP-arvoa", - "hdopVdop": "Jos DOP on asetettu, käytä HDOP- ja VDOP-arvoja PDOP:n sijaan", - "numSatellites": "Satelliittien määrä", - "sequenceNumber": "Sekvenssinumero", - "timestamp": "Aikaleima", - "unset": "Ei yhdistetty", - "vehicleHeading": "Ajoneuvon suunta", - "vehicleSpeed": "Ajoneuvon nopeus" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Käytetään akun jännitteen lukeman säätämiseen", - "label": "Korvaava AD-muuntimen kerroin" - }, - "ina219Address": { - "description": "Akkunäytön INA219 osoite", - "label": "INA219 Osoite" - }, - "lightSleepDuration": { - "description": "Kuinka kauan laite on kevyessä lepotilassa", - "label": "Kevyen lepotilan kesto" - }, - "minimumWakeTime": { - "description": "Vähimmäisaika, jonka laite pysyy hereillä paketin vastaanoton jälkeen", - "label": "Minimi heräämisaika" - }, - "noConnectionBluetoothDisabled": { - "description": "Jos laite ei saa Bluetooth-yhteyttä, BLE-radio poistetaan käytöstä tämän ajan kuluttua", - "label": "Ei yhteyttä. Bluetooth on pois käytöstä" - }, - "powerSavingEnabled": { - "description": "Valitse, jos laite saa virtaa matalavirtalähteestä (esim. aurinkopaneeli), jolloin virrankulutusta minimoidaan mahdollisimman paljon.", - "label": "Ota virransäästötila käyttöön" - }, - "shutdownOnBatteryDelay": { - "description": "Sammuta laite automaattisesti tämän ajan kuluttua akkukäytöllä, 0 tarkoittaa toistaiseksi päällä", - "label": "Viive laitteen sammuttamisessa akkukäytöllä" - }, - "superDeepSleepDuration": { - "description": "Kuinka pitkään laite on supersyvässä lepotilassa", - "label": "Supersyvän lepotilan kesto" - }, - "powerConfigSettings": { - "description": "Virtamoduulin asetukset", - "label": "Virran asetukset" - }, - "sleepSettings": { - "description": "Virtamoduulin lepotila-asetukset", - "label": "Lepotilan asetukset" - } - }, - "security": { - "description": "Turvallisuuskokoonpanon asetukset", - "title": "Turvallisuusasetukset", - "button_backupKey": "Varmuuskopioi avain", - "adminChannelEnabled": { - "description": "Salli saapuva laitteen ohjaus suojaamattoman vanhan admin-kanavan kautta", - "label": "Salli vanha admin ylläpitäjä" - }, - "enableDebugLogApi": { - "description": "Lähetä reaaliaikainen debug-loki sarjaportin kautta, katso ja vie laitteen lokitiedostot, joista sijaintitiedot on poistettu, Bluetoothin kautta", - "label": "Ota käyttöön virheenkorjauslokin API-rajapinta" - }, - "managed": { - "description": "Jos tämä on käytössä, laitteen asetuksia voi muuttaa vain etäadmin-laitteen hallintaviestien kautta. Älä ota tätä käyttöön, ellei vähintään yhtä sopivaa etäadmin-laitetta ole määritetty ja julkinen avain ei ole tallennettu johonkin yllä olevista kentistä.", - "label": "Hallinnoitu" - }, - "privateKey": { - "description": "Käytetään jaetun avaimen luomiseen etälaitteen kanssa", - "label": "Yksityinen avain" - }, - "publicKey": { - "description": "Lähetetään muille mesh-verkon laitteille, jotta ne voivat laskea jaetun salaisen avaimen", - "label": "Julkinen avain" - }, - "primaryAdminKey": { - "description": "Ensisijainen julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", - "label": "Ensisijainen järjestelmänvalvojan avain" - }, - "secondaryAdminKey": { - "description": "Toissijainen julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", - "label": "Toissijainen järjestelmänvalvojan avain" - }, - "serialOutputEnabled": { - "description": "Sarjakonsoli Stream API:n yli", - "label": "Sarjaulostulo Käytössä" - }, - "tertiaryAdminKey": { - "description": "Kolmas julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", - "label": "Kolmas järjestelmänvalvojan hallinta-avain" - }, - "adminSettings": { - "description": "Järjestelmänvalvojan asetukset", - "label": "Ylläpitäjän asetukset" - }, - "loggingSettings": { - "description": "Kirjautumisen asetukset", - "label": "Kirjautumisen asetukset" - } - } -} diff --git a/src/i18n/locales/fi-FI/dialog.json b/src/i18n/locales/fi-FI/dialog.json deleted file mode 100644 index 777330d4..00000000 --- a/src/i18n/locales/fi-FI/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "Tämä toiminto poistaa kaiken viestihistorian. Toimintoa ei voi perua. Haluatko varmasti jatkaa?", - "title": "Tyhjennä kaikki viestit" - }, - "deviceName": { - "description": "Laite käynnistyy uudelleen, kun asetus on tallennettu.", - "longName": "Pitkä nimi", - "shortName": "Lyhytnimi", - "title": "Vaihda laitteen nimi" - }, - "import": { - "description": "Nykyinen LoRa-asetus ylikirjoitetaan.", - "error": { - "invalidUrl": "Virheellinen Meshtastic verkko-osoite" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Kanavan asetus / QR-koodin URL-osoite", - "channels": "Channels:", - "usePreset": "Käytä esiasetusta?", - "title": "Tuo kanava-asetukset" - }, - "locationResponse": { - "altitude": "Korkeus: ", - "coordinates": "Koordinaatit: ", - "title": "Sijainti: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Luodaanko ennalta jaettu avain uudelleen?", - "description": "Haluatko varmasti luoda ennalta jaetun avaimen uudelleen?", - "regenerate": "Luo uudelleen" - }, - "newDeviceDialog": { - "title": "Yhdistä uuteen laitteeseen", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Sarjaliitäntä", - "useHttps": "Käytä HTTPS", - "connecting": "Connecting...", - "connect": "Yhdistä", - "connectionFailedAlert": { - "title": "Yhteys epäonnistui", - "descriptionPrefix": "Laitteeseen ei saatu yhteyttä. ", - "httpsHint": "Jos käytät HTTPS:ää, sinun on ehkä ensin hyväksyttävä itse allekirjoitettu varmenne. ", - "openLinkPrefix": "Avaa ", - "openLinkSuffix": " uuteen välilehteen", - "acceptTlsWarningSuffix": ", hyväksy mahdolliset TLS-varoitukset, jos niitä ilmenee ja yritä sitten uudelleen.", - "learnMoreLink": "Lue lisää" - }, - "httpConnection": { - "label": "IP-osoite / isäntänimi", - "placeholder": "000.000.000 / meshtastinen.paikallinen" - }, - "serialConnection": { - "noDevicesPaired": "Yhtään laitetta ei ole vielä yhdistetty.", - "newDeviceButton": "Uusi laite", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "Yhtään laitetta ei ole vielä yhdistetty.", - "newDeviceButton": "Uusi laite" - }, - "validation": { - "requiresFeatures": "Tämä yhteystyyppi vaatii <0>. Käytä tuettua selainta, kuten Chromea tai Edgeä.", - "requiresSecureContext": "Tämä sovellus vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia.", - "additionallyRequiresSecureContext": "Lisäksi se vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia." - } - }, - "nodeDetails": { - "message": "Viesti", - "requestPosition": "Pyydä sijaintia", - "traceRoute": "Reitinselvitys", - "airTxUtilization": "Ilmatien TX käyttöaste", - "allRawMetrics": "Kaikki raakatiedot:", - "batteryLevel": "Akun varaus", - "channelUtilization": "Kanavan käyttöaste", - "details": "Details:", - "deviceMetrics": "Laitteen mittausloki:", - "hardware": "Hardware: ", - "lastHeard": "Viimeksi kuultu: ", - "nodeHexPrefix": "Laitteen Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Jännite", - "title": "Tiedot laitteelle {{identifier}}", - "ignoreNode": "Älä huomioi laitetta", - "removeNode": "Poista laite", - "unignoreNode": "Poista laitteen ohitus käytöstä" - }, - "pkiBackup": { - "description": "Suosittelemme avaintietojen säännöllistä varmuuskopiointia. Haluatko varmuuskopioida nyt?", - "loseKeysWarning": "Jos menetät avaimesi, sinun täytyy palauttaa laite tehdasasetuksiin.", - "secureBackup": "On tärkeää varmuuskopioida julkiset ja yksityiset avaimet ja säilyttää niiden varmuuskopioita turvallisesti!", - "footer": "=== AVAIMIEN LOPPU ===", - "header": "=== MESHTASTIC AVAIMET {{longName}} ({{shortName}}) LAITTEELLE ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_avaimet_{{longName}}_{{shortName}}.txt", - "title": "Varmuuskopioi avaimet" - }, - "pkiRegenerate": { - "description": "Haluatko varmasti luoda avainparin uudelleen?", - "title": "Luo avainpari uudelleen" - }, - "qr": { - "addChannels": "Lisää kanavia", - "replaceChannels": "Korvaa kanavia", - "description": "Nykyinen LoRa-kokoonpano tullaan myös jakamaan.", - "sharableUrl": "Jaettava URL", - "title": "Generoi QR-koodi" - }, - "rebootOta": { - "title": "Ajasta uudelleenkäynnistys", - "description": "Käynnistä yhdistetty laite uudelleen viiveen jälkeen OTA-tilaan (langaton päivitys).", - "enterDelay": "Anna viive (sekuntia)", - "scheduled": "Uudelleenkäynnistys on ajastettu" - }, - "reboot": { - "title": "Ajasta uudelleenkäynnistys", - "description": "Käynnistä yhdistetty laite x minuutin jälkeen." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "Tämä poistaa laitteen laitteesta ja pyytää uusia avaimia.", - "keyMismatchReasonSuffix": ". Tämä johtuu siitä, että etälaitteen nykyinen julkinen avain ei vastaa aiemmin tallennettua avainta tälle laitteelle.", - "unableToSendDmPrefix": "Laitteesi ei pysty lähettämään suoraa viestiä laitteelle: " - }, - "acceptNewKeys": "Hyväksy uudet avaimet", - "title": "Avaimet eivät täsmää - {{identifier}}" - }, - "removeNode": { - "description": "Haluatko varmasti poistaa tämän laitteen?", - "title": "Poista laite?" - }, - "shutdown": { - "title": "Ajasta sammutus", - "description": "Sammuta yhdistetty laite x minuutin päästä." - }, - "traceRoute": { - "routeToDestination": "Reitin määränpää:", - "routeBack": "Reitti takaisin:" - }, - "tracerouteResponse": { - "title": "Reitinselvitys: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Kyllä, tiedän mitä teen", - "conjunction": " ja blogikirjoitukset ", - "postamble": " ja ymmärrän roolin muuttamisen vaikutukset.", - "preamble": "Olen lukenut ", - "choosingRightDeviceRole": "Valitse laitteelle oikea rooli", - "deviceRoleDocumentation": "Roolien dokumentaatio laitteelle", - "title": "Oletko varma?" - } -} diff --git a/src/i18n/locales/fi-FI/messages.json b/src/i18n/locales/fi-FI/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/fi-FI/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/fi-FI/moduleConfig.json b/src/i18n/locales/fi-FI/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/fi-FI/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/fi-FI/nodes.json b/src/i18n/locales/fi-FI/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/fi-FI/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/fi-FI/ui.json b/src/i18n/locales/fi-FI/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/fi-FI/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/fr-FR/channels.json b/src/i18n/locales/fr-FR/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/fr-FR/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/fr-FR/commandPalette.json b/src/i18n/locales/fr-FR/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/fr-FR/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/fr-FR/common.json b/src/i18n/locales/fr-FR/common.json deleted file mode 100644 index fad4c941..00000000 --- a/src/i18n/locales/fr-FR/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Appliquer", - "backupKey": "Backup Key", - "cancel": "Annuler", - "clearMessages": "Clear Messages", - "close": "Fermer", - "confirm": "Confirm", - "delete": "Effacer", - "dismiss": "Annuler", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "D'accord", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Supprimer", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Réinitialiser", - "save": "Sauvegarder", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/fr-FR/dashboard.json b/src/i18n/locales/fr-FR/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/fr-FR/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/fr-FR/deviceConfig.json b/src/i18n/locales/fr-FR/deviceConfig.json deleted file mode 100644 index d98bc2a7..00000000 --- a/src/i18n/locales/fr-FR/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Appareil", - "tabDisplay": "Écran", - "tabLora": "LoRa", - "tabNetwork": "Réseau", - "tabPosition": "Position", - "tabPower": "Alimentation", - "tabSecurity": "Sécurité" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "Zone horaire POSIX" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Rôle" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Activé" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Mode d'appariement" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bande Passante" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignorer MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK vers MQTT" - }, - "overrideDutyCycle": { - "description": "Ne pas prendre en compte la limite d'utilisation", - "label": "Ne pas prendre en compte la limite d'utilisation" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Région" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Activé" - }, - "gateway": { - "description": "Default Gateway", - "label": "Passerelle" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Sous-réseau" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Activé" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "Configuration UDP" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Horodatage", - "unset": "Désactivé", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Activer le mode économie d'énergie" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Configuration de l'alimentation" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Clé privée" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Clé publique" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/fr-FR/dialog.json b/src/i18n/locales/fr-FR/dialog.json deleted file mode 100644 index b7b9c962..00000000 --- a/src/i18n/locales/fr-FR/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Série", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Tension", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Générer un QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Êtes-vous sûr ?" - } -} diff --git a/src/i18n/locales/fr-FR/messages.json b/src/i18n/locales/fr-FR/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/fr-FR/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/fr-FR/moduleConfig.json b/src/i18n/locales/fr-FR/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/fr-FR/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/fr-FR/nodes.json b/src/i18n/locales/fr-FR/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/fr-FR/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/fr-FR/ui.json b/src/i18n/locales/fr-FR/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/fr-FR/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/it-IT/channels.json b/src/i18n/locales/it-IT/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/it-IT/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/it-IT/commandPalette.json b/src/i18n/locales/it-IT/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/it-IT/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/it-IT/common.json b/src/i18n/locales/it-IT/common.json deleted file mode 100644 index 665205de..00000000 --- a/src/i18n/locales/it-IT/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Applica", - "backupKey": "Backup Key", - "cancel": "Annulla", - "clearMessages": "Clear Messages", - "close": "Chiudi", - "confirm": "Confirm", - "delete": "Elimina", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Importa", - "message": "Messaggio", - "now": "Now", - "ok": "Ok", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Elimina", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Salva", - "scanQr": "Scansiona codice QR", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/it-IT/dashboard.json b/src/i18n/locales/it-IT/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/it-IT/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/it-IT/deviceConfig.json b/src/i18n/locales/it-IT/deviceConfig.json deleted file mode 100644 index 6ca4ef4d..00000000 --- a/src/i18n/locales/it-IT/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Dispositivo", - "tabDisplay": "Schermo", - "tabLora": "LoRa", - "tabNetwork": "Rete", - "tabPosition": "Posizione", - "tabPower": "Alimentazione", - "tabSecurity": "Sicurezza" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Ruolo" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Modalità abbinamento" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Larghezza di banda" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignora MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Configurazione Modem" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK per MQTT" - }, - "overrideDutyCycle": { - "description": "Ignora limite di Duty Cycle", - "label": "Ignora limite di Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Regione" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "Configurazione UDP" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Data e ora", - "unset": "Non impostato", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Abilita modalità risparmio energetico" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Configurazione Alimentazione" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Chiave Privata" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Chiave Pubblica" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/it-IT/dialog.json b/src/i18n/locales/it-IT/dialog.json deleted file mode 100644 index 6c0197a4..00000000 --- a/src/i18n/locales/it-IT/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Seriale", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Messaggio", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Tensione", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Sei sicuro?" - } -} diff --git a/src/i18n/locales/it-IT/messages.json b/src/i18n/locales/it-IT/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/it-IT/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/it-IT/moduleConfig.json b/src/i18n/locales/it-IT/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/it-IT/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/it-IT/nodes.json b/src/i18n/locales/it-IT/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/it-IT/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/it-IT/ui.json b/src/i18n/locales/it-IT/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/it-IT/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/ja-JP/channels.json b/src/i18n/locales/ja-JP/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/ja-JP/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/ja-JP/commandPalette.json b/src/i18n/locales/ja-JP/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/ja-JP/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/ja-JP/common.json b/src/i18n/locales/ja-JP/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/ja-JP/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/ja-JP/dashboard.json b/src/i18n/locales/ja-JP/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/ja-JP/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/ja-JP/deviceConfig.json b/src/i18n/locales/ja-JP/deviceConfig.json deleted file mode 100644 index 68bd011d..00000000 --- a/src/i18n/locales/ja-JP/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "接続するデバイスを選択", - "tabDisplay": "表示", - "tabLora": "LoRa", - "tabNetwork": "ネットワーク", - "tabPosition": "位置", - "tabPower": "電源", - "tabSecurity": "セキュリティ" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/ja-JP/dialog.json b/src/i18n/locales/ja-JP/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/ja-JP/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/ja-JP/messages.json b/src/i18n/locales/ja-JP/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/ja-JP/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/ja-JP/moduleConfig.json b/src/i18n/locales/ja-JP/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/ja-JP/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/ja-JP/nodes.json b/src/i18n/locales/ja-JP/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/ja-JP/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/ja-JP/ui.json b/src/i18n/locales/ja-JP/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/ja-JP/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/nl-NL/channels.json b/src/i18n/locales/nl-NL/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/nl-NL/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/nl-NL/commandPalette.json b/src/i18n/locales/nl-NL/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/nl-NL/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/nl-NL/common.json b/src/i18n/locales/nl-NL/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/nl-NL/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/nl-NL/dashboard.json b/src/i18n/locales/nl-NL/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/nl-NL/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/nl-NL/deviceConfig.json b/src/i18n/locales/nl-NL/deviceConfig.json deleted file mode 100644 index 9c72f6f1..00000000 --- a/src/i18n/locales/nl-NL/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Apparaat", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/nl-NL/dialog.json b/src/i18n/locales/nl-NL/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/nl-NL/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/nl-NL/messages.json b/src/i18n/locales/nl-NL/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/nl-NL/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/nl-NL/moduleConfig.json b/src/i18n/locales/nl-NL/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/nl-NL/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/nl-NL/nodes.json b/src/i18n/locales/nl-NL/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/nl-NL/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/nl-NL/ui.json b/src/i18n/locales/nl-NL/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/nl-NL/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/pt-PT/channels.json b/src/i18n/locales/pt-PT/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/pt-PT/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/pt-PT/commandPalette.json b/src/i18n/locales/pt-PT/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/pt-PT/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/pt-PT/common.json b/src/i18n/locales/pt-PT/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/pt-PT/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/pt-PT/dashboard.json b/src/i18n/locales/pt-PT/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/pt-PT/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/pt-PT/deviceConfig.json b/src/i18n/locales/pt-PT/deviceConfig.json deleted file mode 100644 index 31f72bf4..00000000 --- a/src/i18n/locales/pt-PT/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Dispositivo", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/pt-PT/dialog.json b/src/i18n/locales/pt-PT/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/pt-PT/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/pt-PT/messages.json b/src/i18n/locales/pt-PT/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/pt-PT/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/pt-PT/moduleConfig.json b/src/i18n/locales/pt-PT/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/pt-PT/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/pt-PT/nodes.json b/src/i18n/locales/pt-PT/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/pt-PT/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/pt-PT/ui.json b/src/i18n/locales/pt-PT/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/pt-PT/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/sv-SE/channels.json b/src/i18n/locales/sv-SE/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/sv-SE/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/sv-SE/commandPalette.json b/src/i18n/locales/sv-SE/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/sv-SE/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/sv-SE/common.json b/src/i18n/locales/sv-SE/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/sv-SE/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/sv-SE/dashboard.json b/src/i18n/locales/sv-SE/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/sv-SE/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/sv-SE/deviceConfig.json b/src/i18n/locales/sv-SE/deviceConfig.json deleted file mode 100644 index 0c25a4cd..00000000 --- a/src/i18n/locales/sv-SE/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Enhet", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "Moduler" - }, - "device": { - "title": "Enhetsinställningar", - "description": "Settings for the device", - "buttonPin": { - "description": "Stift för knapp", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Stift för summer", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Inaktivera trippeltryck", - "label": "Inaktivera trippeltryck" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Inaktivera blinkande LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "Hur ofta nod-info ska sändas", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "POSIX-tidszonsträng för enheten", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "Hur enheten hanterar återutsändning", - "label": "Återutsändningsläge" - }, - "role": { - "description": "Vilken roll enheten har på nätet", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth-inställningar", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Aktivera eller inaktivera Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Metod för parkoppling", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Variant på displaylayout", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Vänd skärmen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "Koordinatformat" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/sv-SE/dialog.json b/src/i18n/locales/sv-SE/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/sv-SE/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/sv-SE/messages.json b/src/i18n/locales/sv-SE/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/sv-SE/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/sv-SE/moduleConfig.json b/src/i18n/locales/sv-SE/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/sv-SE/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/sv-SE/nodes.json b/src/i18n/locales/sv-SE/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/sv-SE/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/sv-SE/ui.json b/src/i18n/locales/sv-SE/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/sv-SE/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/tr-TR/channels.json b/src/i18n/locales/tr-TR/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/tr-TR/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/tr-TR/commandPalette.json b/src/i18n/locales/tr-TR/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/tr-TR/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/tr-TR/common.json b/src/i18n/locales/tr-TR/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/tr-TR/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/tr-TR/dashboard.json b/src/i18n/locales/tr-TR/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/tr-TR/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/tr-TR/deviceConfig.json b/src/i18n/locales/tr-TR/deviceConfig.json deleted file mode 100644 index f18e84ea..00000000 --- a/src/i18n/locales/tr-TR/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Cihaz", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "Modüller" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/tr-TR/dialog.json b/src/i18n/locales/tr-TR/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/tr-TR/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/tr-TR/messages.json b/src/i18n/locales/tr-TR/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/tr-TR/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/tr-TR/moduleConfig.json b/src/i18n/locales/tr-TR/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/tr-TR/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/tr-TR/nodes.json b/src/i18n/locales/tr-TR/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/tr-TR/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/tr-TR/ui.json b/src/i18n/locales/tr-TR/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/tr-TR/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/uk-UA/channels.json b/src/i18n/locales/uk-UA/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/uk-UA/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/uk-UA/commandPalette.json b/src/i18n/locales/uk-UA/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/uk-UA/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/uk-UA/common.json b/src/i18n/locales/uk-UA/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/uk-UA/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/uk-UA/dashboard.json b/src/i18n/locales/uk-UA/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/uk-UA/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/uk-UA/deviceConfig.json b/src/i18n/locales/uk-UA/deviceConfig.json deleted file mode 100644 index 193c5494..00000000 --- a/src/i18n/locales/uk-UA/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "Device", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/uk-UA/dialog.json b/src/i18n/locales/uk-UA/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/uk-UA/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/uk-UA/messages.json b/src/i18n/locales/uk-UA/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/uk-UA/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/uk-UA/moduleConfig.json b/src/i18n/locales/uk-UA/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/uk-UA/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/uk-UA/nodes.json b/src/i18n/locales/uk-UA/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/uk-UA/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/uk-UA/ui.json b/src/i18n/locales/uk-UA/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/uk-UA/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/zh-CN/channels.json b/src/i18n/locales/zh-CN/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/zh-CN/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/zh-CN/commandPalette.json b/src/i18n/locales/zh-CN/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/zh-CN/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/zh-CN/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/zh-CN/dashboard.json b/src/i18n/locales/zh-CN/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/zh-CN/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/zh-CN/deviceConfig.json b/src/i18n/locales/zh-CN/deviceConfig.json deleted file mode 100644 index 2812b2c0..00000000 --- a/src/i18n/locales/zh-CN/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "设备", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "Modules" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "转播模式" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/zh-CN/dialog.json b/src/i18n/locales/zh-CN/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/zh-CN/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/zh-CN/messages.json b/src/i18n/locales/zh-CN/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/zh-CN/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/zh-CN/moduleConfig.json b/src/i18n/locales/zh-CN/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/zh-CN/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/zh-CN/nodes.json b/src/i18n/locales/zh-CN/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/zh-CN/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/zh-CN/ui.json b/src/i18n/locales/zh-CN/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/zh-CN/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/i18n/locales/zh-TW/channels.json b/src/i18n/locales/zh-TW/channels.json deleted file mode 100644 index 535b8e6b..00000000 --- a/src/i18n/locales/zh-TW/channels.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" - }, - "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." - }, - "settings": { - "label": "Channel Settings", - "description": "Crypto, MQTT & misc settings" - }, - "role": { - "label": "Role", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" - } - }, - "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" - }, - "name": { - "label": "Name", - "description": "A unique name for the channel <12 bytes, leave blank for default" - }, - "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" - }, - "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" - }, - "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", - "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } -} diff --git a/src/i18n/locales/zh-TW/commandPalette.json b/src/i18n/locales/zh-TW/commandPalette.json deleted file mode 100644 index 1eed8987..00000000 --- a/src/i18n/locales/zh-TW/commandPalette.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "emptyState": "No results found.", - "page": { - "title": "Command Menu" - }, - "pinGroup": { - "label": "Pin command group" - }, - "unpinGroup": { - "label": "Unpin command group" - }, - "goto": { - "label": "Goto", - "command": { - "messages": "Messages", - "map": "Map", - "config": "Config", - "channels": "Channels", - "nodes": "Nodes" - } - }, - "manage": { - "label": "Manage", - "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" - } - }, - "contextual": { - "label": "Contextual", - "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", - "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" - } - }, - "debug": { - "label": "Debug", - "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" - } - } -} diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json deleted file mode 100644 index 8c434125..00000000 --- a/src/i18n/locales/zh-TW/common.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "button": { - "apply": "Apply", - "backupKey": "Backup Key", - "cancel": "Cancel", - "clearMessages": "Clear Messages", - "close": "Close", - "confirm": "Confirm", - "delete": "Delete", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", - "import": "Import", - "message": "Message", - "now": "Now", - "ok": "OK", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", - "remove": "Remove", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", - "reset": "Reset", - "save": "Save", - "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" - }, - "app": { - "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" - }, - "loading": "Loading...", - "unit": { - "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", - "hop": { - "one": "Hop", - "plural": "Hops" - }, - "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" - }, - "megahertz": "MHz", - "raw": "raw", - "meter": { - "one": "Meter", - "plural": "Meters", - "suffix": "m" - }, - "minute": { - "one": "Minute", - "plural": "Minutes" - }, - "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" - }, - "second": { - "one": "Second", - "plural": "Seconds" - }, - "snr": "SNR", - "volt": { - "one": "Volt", - "plural": "Volts", - "suffix": "V" - }, - "record": { - "one": "Records", - "plural": "Records" - } - }, - "security": { - "256bit": "256 bit" - }, - "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", - "num": "??" - }, - "nodeUnknownPrefix": "!", - "unset": "UNSET", - "fallbackName": "Meshtastic {{last4}}", - "formValidation": { - "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." - }, - "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." - }, - "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." - }, - "invalidType": { - "number": "Invalid type, expected a number." - }, - "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." - }, - "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." - } - } -} diff --git a/src/i18n/locales/zh-TW/dashboard.json b/src/i18n/locales/zh-TW/dashboard.json deleted file mode 100644 index 3a3cd869..00000000 --- a/src/i18n/locales/zh-TW/dashboard.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", - "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" - } -} diff --git a/src/i18n/locales/zh-TW/deviceConfig.json b/src/i18n/locales/zh-TW/deviceConfig.json deleted file mode 100644 index f95b32fd..00000000 --- a/src/i18n/locales/zh-TW/deviceConfig.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "page": { - "title": "Configuration", - "tabBluetooth": "Bluetooth", - "tabDevice": "设备", - "tabDisplay": "Display", - "tabLora": "LoRa", - "tabNetwork": "Network", - "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" - }, - "sidebar": { - "label": "模組" - }, - "device": { - "title": "Device Settings", - "description": "Settings for the device", - "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" - }, - "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" - }, - "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" - }, - "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" - }, - "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" - }, - "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" - }, - "posixTimezone": { - "description": "The POSIX timezone string for the device", - "label": "POSIX Timezone" - }, - "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" - }, - "role": { - "description": "What role the device performs on the mesh", - "label": "Role" - } - }, - "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" - }, - "pairingMode": { - "description": "Pin selection behaviour.", - "label": "Pairing mode" - }, - "pin": { - "description": "Pin to use when pairing", - "label": "Pin" - } - }, - "display": { - "description": "Settings for the device display", - "title": "Display Settings", - "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" - }, - "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" - }, - "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" - }, - "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" - }, - "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" - }, - "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" - }, - "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" - }, - "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" - }, - "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" - }, - "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" - }, - "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" - } - }, - "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", - "bandwidth": { - "description": "Channel bandwidth in MHz", - "label": "Bandwidth" - }, - "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" - }, - "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" - }, - "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" - }, - "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" - }, - "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" - }, - "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" - }, - "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" - }, - "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", - "label": "OK to MQTT" - }, - "overrideDutyCycle": { - "description": "Override Duty Cycle", - "label": "Override Duty Cycle" - }, - "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" - }, - "region": { - "description": "Sets the region for your node", - "label": "Region" - }, - "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", - "label": "Spreading Factor" - }, - "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" - }, - "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" - }, - "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" - }, - "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" - }, - "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" - }, - "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" - } - }, - "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", - "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" - }, - "dns": { - "description": "DNS Server", - "label": "DNS" - }, - "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" - }, - "gateway": { - "description": "Default Gateway", - "label": "Gateway" - }, - "ip": { - "description": "IP Address", - "label": "IP" - }, - "psk": { - "description": "Network password", - "label": "PSK" - }, - "ssid": { - "description": "Network name", - "label": "SSID" - }, - "subnet": { - "description": "Subnet Mask", - "label": "Subnet" - }, - "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" - }, - "meshViaUdp": { - "label": "Mesh via UDP" - }, - "ntpServer": { - "label": "NTP Server" - }, - "rsyslogServer": { - "label": "Rsyslog Server" - }, - "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" - }, - "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" - }, - "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" - }, - "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" - }, - "udpConfigSettings": { - "description": "UDP over Mesh configuration", - "label": "UDP Config" - } - }, - "position": { - "title": "Position Settings", - "description": "Settings for the position module", - "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" - }, - "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" - }, - "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" - }, - "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" - }, - "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" - }, - "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" - }, - "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" - }, - "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" - }, - "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" - }, - "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" - }, - "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" - }, - "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" - }, - "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", - "timestamp": "Timestamp", - "unset": "Unset", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" - } - }, - "power": { - "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" - }, - "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" - }, - "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" - }, - "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" - }, - "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" - }, - "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", - "label": "Enable power saving mode" - }, - "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" - }, - "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" - }, - "powerConfigSettings": { - "description": "Settings for the power module", - "label": "Power Config" - }, - "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" - } - }, - "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", - "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" - }, - "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" - }, - "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" - }, - "privateKey": { - "description": "Used to create a shared key with a remote device", - "label": "Private Key" - }, - "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - "label": "Public Key" - }, - "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" - }, - "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" - }, - "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" - }, - "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" - }, - "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" - }, - "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" - } - } -} diff --git a/src/i18n/locales/zh-TW/dialog.json b/src/i18n/locales/zh-TW/dialog.json deleted file mode 100644 index 6bc70259..00000000 --- a/src/i18n/locales/zh-TW/dialog.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" - }, - "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" - }, - "import": { - "description": "The current LoRa configuration will be overridden.", - "error": { - "invalidUrl": "Invalid Meshtastic URL" - }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" - }, - "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" - }, - "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" - }, - "newDeviceDialog": { - "title": "Connect New Device", - "https": "https", - "http": "http", - "tabHttp": "HTTP", - "tabBluetooth": "Bluetooth", - "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", - "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" - }, - "httpConnection": { - "label": "IP Address/Hostname", - "placeholder": "000.000.000.000 / meshtastic.local" - }, - "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", - "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" - }, - "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" - }, - "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." - } - }, - "nodeDetails": { - "message": "Message", - "requestPosition": "Request Position", - "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", - "voltage": "Voltage", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" - }, - "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", - "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" - }, - "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" - }, - "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" - }, - "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" - }, - "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." - }, - "refreshKeys": { - "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " - }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" - }, - "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" - }, - "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." - }, - "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" - }, - "tracerouteResponse": { - "title": "Traceroute: {{identifier}}" - }, - "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" - } -} diff --git a/src/i18n/locales/zh-TW/messages.json b/src/i18n/locales/zh-TW/messages.json deleted file mode 100644 index 101d3a0c..00000000 --- a/src/i18n/locales/zh-TW/messages.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "page": { - "title": "Messages: {{chatName}}" - }, - "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." - }, - "selectChatPrompt": { - "text": "Select a channel or node to start messaging." - }, - "sendMessage": { - "placeholder": "Type your message here...", - "sendButton": "Send" - }, - "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" - }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } - } - } -} diff --git a/src/i18n/locales/zh-TW/moduleConfig.json b/src/i18n/locales/zh-TW/moduleConfig.json deleted file mode 100644 index caacbe17..00000000 --- a/src/i18n/locales/zh-TW/moduleConfig.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "page": { - "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", - "tabCannedMessage": "Canned", - "tabDetectionSensor": "Detection Sensor", - "tabExternalNotification": "Ext Notif", - "tabMqtt": "MQTT", - "tabNeighborInfo": "Neighbor Info", - "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", - "tabSerial": "Serial", - "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" - }, - "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", - "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" - }, - "current": { - "label": "Current", - "description": "Sets the current for the LED output. Default is 10" - }, - "red": { - "label": "Red", - "description": "Sets the red LED level. Values are 0-255" - }, - "green": { - "label": "Green", - "description": "Sets the green LED level. Values are 0-255" - }, - "blue": { - "label": "Blue", - "description": "Sets the blue LED level. Values are 0-255" - } - }, - "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", - "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" - }, - "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" - }, - "bitrate": { - "label": "Bitrate", - "description": "Bitrate to use for audio encoding" - }, - "i2sWs": { - "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" - }, - "i2sSd": { - "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" - }, - "i2sDin": { - "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" - }, - "i2sSck": { - "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" - } - }, - "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", - "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" - }, - "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" - }, - "inputbrokerPinA": { - "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" - }, - "inputbrokerPinB": { - "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" - }, - "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" - }, - "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." - }, - "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" - }, - "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" - }, - "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" - }, - "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" - } - }, - "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" - }, - "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" - }, - "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" - }, - "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" - }, - "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" - }, - "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" - }, - "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" - }, - "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" - } - }, - "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", - "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" - }, - "outputMs": { - "label": "Output MS", - "description": "Output MS" - }, - "output": { - "label": "Output", - "description": "Output" - }, - "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" - }, - "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" - }, - "active": { - "label": "Active", - "description": "Active" - }, - "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" - }, - "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" - }, - "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" - }, - "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" - }, - "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" - }, - "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" - }, - "usePwm": { - "label": "Use PWM", - "description": "Use PWM" - }, - "nagTimeout": { - "label": "Nag Timeout", - "description": "Nag Timeout" - }, - "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" - } - }, - "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" - }, - "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" - }, - "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" - }, - "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" - }, - "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." - }, - "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" - }, - "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" - }, - "root": { - "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" - }, - "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." - }, - "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." - }, - "mapReportSettings": { - "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" - }, - "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", - "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" - } - } - } - }, - "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", - "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" - }, - "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" - } - }, - "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" - }, - "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" - }, - "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." - }, - "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." - } - }, - "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" - }, - "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" - }, - "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" - } - }, - "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" - }, - "echo": { - "label": "Echo", - "description": "Any packets you send will be echoed back to your device" - }, - "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." - }, - "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." - }, - "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" - }, - "timeout": { - "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" - }, - "mode": { - "label": "Mode", - "description": "Select Mode" - }, - "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." - } - }, - "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", - "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" - }, - "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" - }, - "records": { - "label": "Number of records", - "description": "Number of records to store" - }, - "historyReturnMax": { - "label": "History return max", - "description": "Max number of records to return" - }, - "historyReturnWindow": { - "label": "History return window", - "description": "Max number of records to return" - } - }, - "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", - "deviceUpdateInterval": { - "label": "Device Metrics", - "description": "Device metrics update interval (seconds)" - }, - "environmentUpdateInterval": { - "label": "Environment metrics update interval (seconds)", - "description": "" - }, - "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" - }, - "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" - }, - "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" - }, - "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" - }, - "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" - }, - "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" - }, - "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" - }, - "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" - } - } -} diff --git a/src/i18n/locales/zh-TW/nodes.json b/src/i18n/locales/zh-TW/nodes.json deleted file mode 100644 index 5202f039..00000000 --- a/src/i18n/locales/zh-TW/nodes.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "nodeDetail": { - "publicKeyEnabled": { - "label": "Public Key Enabled" - }, - "noPublicKey": { - "label": "No Public Key" - }, - "directMessage": { - "label": "Direct Message {{shortName}}" - }, - "favorite": { - "label": "Favorite" - }, - "notFavorite": { - "label": "Not a Favorite" - }, - "status": { - "heard": "Heard", - "mqtt": "MQTT" - }, - "elevation": { - "label": "Elevation" - }, - "channelUtil": { - "label": "Channel Util" - }, - "airtimeUtil": { - "label": "Airtime Util" - } - }, - "nodesTable": { - "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" - }, - "connectionStatus": { - "direct": "Direct", - "away": "away", - "unknown": "-", - "viaMqtt": ", via MQTT" - }, - "lastHeardStatus": { - "never": "Never" - } - } -} diff --git a/src/i18n/locales/zh-TW/ui.json b/src/i18n/locales/zh-TW/ui.json deleted file mode 100644 index 28342071..00000000 --- a/src/i18n/locales/zh-TW/ui.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "navigation": { - "title": "Navigation", - "messages": "Messages", - "map": "Map", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" - }, - "app": { - "title": "Meshtastic", - "logo": "Meshtastic Logo" - }, - "sidebar": { - "collapseToggle": { - "button": { - "open": "Open sidebar", - "close": "Close sidebar" - } - }, - "deviceInfo": { - "volts": "{{voltage}} volts", - "firmware": { - "title": "Firmware", - "version": "v{{version}}", - "buildDate": "Build date: {{date}}" - }, - "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" - }, - "editDeviceName": "Edit device name" - } - }, - "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", - "title": "Battery" - }, - "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." - }, - "toast": { - "positionRequestSent": { - "title": "Position request sent." - }, - "requestingPosition": { - "title": "Requesting position, please wait..." - }, - "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." - }, - "tracerouteSent": { - "title": "Traceroute sent." - }, - "savedChannel": { - "title": "Saved Channel: {{channelName}}" - }, - "messages": { - "pkiEncryption": { - "title": "Chat is using PKI encryption." - }, - "pskEncryption": { - "title": "Chat is using PSK encryption." - } - }, - "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." - }, - "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." - }, - "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." - } - }, - "notifications": { - "copied": { - "label": "Copied!" - }, - "copyToClipboard": { - "label": "Copy to clipboard" - }, - "hidePassword": { - "label": "Hide password" - }, - "showPassword": { - "label": "Show password" - }, - "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" - } - }, - "general": { - "label": "General" - }, - "hardware": { - "label": "Hardware" - }, - "metrics": { - "label": "Metrics" - }, - "role": { - "label": "Role" - }, - "filter": { - "label": "Filter" - }, - "clearInput": { - "label": "Clear input" - }, - "resetFilters": { - "label": "Reset Filters" - }, - "nodeName": { - "label": "Node name/number", - "placeholder": "Meshtastic 1234" - }, - "airtimeUtilization": { - "label": "Airtime Utilization (%)" - }, - "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" - }, - "batteryVoltage": { - "label": "Battery voltage (V)", - "title": "Voltage" - }, - "channelUtilization": { - "label": "Channel Utilization (%)" - }, - "hops": { - "direct": "Direct", - "label": "Number of hops", - "text": "Number of hops: {{value}}" - }, - "lastHeard": { - "label": "Last heard", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" - }, - "snr": { - "label": "SNR (db)" - }, - "favorites": { - "label": "Favorites" - }, - "hide": { - "label": "Hide" - }, - "showOnly": { - "label": "Show Only" - }, - "viaMqtt": { - "label": "Connected via MQTT" - }, - "language": { - "label": "Language", - "changeLanguage": "Change Language" - }, - "theme": { - "dark": "Dark", - "light": "Light", - "system": "Automatic", - "changeTheme": "Change Color Scheme" - }, - "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", - "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", - "stackTraceLabel": "Stack trace:", - "fallbackError": "{{error}}" - }, - "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", - "commitSha": "Commit SHA: {{sha}}" - } -} diff --git a/src/tests/setup.ts b/src/tests/setup.ts index 4211fb77..d9c3279e 100644 --- a/src/tests/setup.ts +++ b/src/tests/setup.ts @@ -64,14 +64,11 @@ i18n .use(initReactI18next) .init({ lng: "en", - fallbackLng: "en", ns: appNamespaces, defaultNS: appDefaultNS, fallbackNS: appFallbackNS, - supportedLngs: ["en"], - resources: { en: { channels: channelsEN, From 474e610c3ddfb02af1e91e166a43e072b2ea9321 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 16 Jun 2025 15:55:29 -0400 Subject: [PATCH 10/37] fix: revert crowdin config (#659) --- crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crowdin.yml b/crowdin.yml index 2ac19722..14d994ec 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -7,4 +7,4 @@ preserve_hierarchy: true files: - source: "/src/i18n/locales/en/**/*.json" - translation: /src/i18n/locales/%two_letters_code%/**/%original_file_name% + translation: "/src/i18n/locales/%locale%/%original_file_name%" From c36ff6077805696295687bca81333cf2990c2621 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 15:59:08 -0400 Subject: [PATCH 11/37] chore(i18n): New Crowdin Translations by GitHub Action (#660) Co-authored-by: Crowdin Bot --- src/i18n/locales/bg-BG/channels.json | 69 ++++ src/i18n/locales/bg-BG/commandPalette.json | 50 +++ src/i18n/locales/bg-BG/common.json | 119 ++++++ src/i18n/locales/bg-BG/dashboard.json | 12 + src/i18n/locales/bg-BG/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/bg-BG/dialog.json | 159 ++++++++ src/i18n/locales/bg-BG/messages.json | 40 ++ src/i18n/locales/bg-BG/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/bg-BG/nodes.json | 51 +++ src/i18n/locales/bg-BG/ui.json | 201 +++++++++ src/i18n/locales/cs-CZ/channels.json | 69 ++++ src/i18n/locales/cs-CZ/commandPalette.json | 50 +++ src/i18n/locales/cs-CZ/common.json | 119 ++++++ src/i18n/locales/cs-CZ/dashboard.json | 12 + src/i18n/locales/cs-CZ/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/cs-CZ/dialog.json | 159 ++++++++ src/i18n/locales/cs-CZ/messages.json | 40 ++ src/i18n/locales/cs-CZ/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/cs-CZ/nodes.json | 51 +++ src/i18n/locales/cs-CZ/ui.json | 201 +++++++++ src/i18n/locales/de-DE/channels.json | 69 ++++ src/i18n/locales/de-DE/commandPalette.json | 50 +++ src/i18n/locales/de-DE/common.json | 119 ++++++ src/i18n/locales/de-DE/dashboard.json | 12 + src/i18n/locales/de-DE/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/de-DE/dialog.json | 159 ++++++++ src/i18n/locales/de-DE/messages.json | 40 ++ src/i18n/locales/de-DE/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/de-DE/nodes.json | 51 +++ src/i18n/locales/de-DE/ui.json | 201 +++++++++ src/i18n/locales/es-ES/channels.json | 69 ++++ src/i18n/locales/es-ES/commandPalette.json | 50 +++ src/i18n/locales/es-ES/common.json | 119 ++++++ src/i18n/locales/es-ES/dashboard.json | 12 + src/i18n/locales/es-ES/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/es-ES/dialog.json | 159 ++++++++ src/i18n/locales/es-ES/messages.json | 40 ++ src/i18n/locales/es-ES/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/es-ES/nodes.json | 51 +++ src/i18n/locales/es-ES/ui.json | 201 +++++++++ src/i18n/locales/fi-FI/channels.json | 69 ++++ src/i18n/locales/fi-FI/commandPalette.json | 50 +++ src/i18n/locales/fi-FI/common.json | 119 ++++++ src/i18n/locales/fi-FI/dashboard.json | 12 + src/i18n/locales/fi-FI/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/fi-FI/dialog.json | 159 ++++++++ src/i18n/locales/fi-FI/messages.json | 40 ++ src/i18n/locales/fi-FI/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/fi-FI/nodes.json | 51 +++ src/i18n/locales/fi-FI/ui.json | 201 +++++++++ src/i18n/locales/fr-FR/channels.json | 69 ++++ src/i18n/locales/fr-FR/commandPalette.json | 50 +++ src/i18n/locales/fr-FR/common.json | 119 ++++++ src/i18n/locales/fr-FR/dashboard.json | 12 + src/i18n/locales/fr-FR/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/fr-FR/dialog.json | 159 ++++++++ src/i18n/locales/fr-FR/messages.json | 40 ++ src/i18n/locales/fr-FR/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/fr-FR/nodes.json | 51 +++ src/i18n/locales/fr-FR/ui.json | 201 +++++++++ src/i18n/locales/it-IT/channels.json | 69 ++++ src/i18n/locales/it-IT/commandPalette.json | 50 +++ src/i18n/locales/it-IT/common.json | 119 ++++++ src/i18n/locales/it-IT/dashboard.json | 12 + src/i18n/locales/it-IT/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/it-IT/dialog.json | 159 ++++++++ src/i18n/locales/it-IT/messages.json | 40 ++ src/i18n/locales/it-IT/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/it-IT/nodes.json | 51 +++ src/i18n/locales/it-IT/ui.json | 201 +++++++++ src/i18n/locales/ja-JP/channels.json | 69 ++++ src/i18n/locales/ja-JP/commandPalette.json | 50 +++ src/i18n/locales/ja-JP/common.json | 119 ++++++ src/i18n/locales/ja-JP/dashboard.json | 12 + src/i18n/locales/ja-JP/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/ja-JP/dialog.json | 159 ++++++++ src/i18n/locales/ja-JP/messages.json | 40 ++ src/i18n/locales/ja-JP/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/ja-JP/nodes.json | 51 +++ src/i18n/locales/ja-JP/ui.json | 201 +++++++++ src/i18n/locales/nl-NL/channels.json | 69 ++++ src/i18n/locales/nl-NL/commandPalette.json | 50 +++ src/i18n/locales/nl-NL/common.json | 119 ++++++ src/i18n/locales/nl-NL/dashboard.json | 12 + src/i18n/locales/nl-NL/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/nl-NL/dialog.json | 159 ++++++++ src/i18n/locales/nl-NL/messages.json | 40 ++ src/i18n/locales/nl-NL/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/nl-NL/nodes.json | 51 +++ src/i18n/locales/nl-NL/ui.json | 201 +++++++++ src/i18n/locales/pt-PT/channels.json | 69 ++++ src/i18n/locales/pt-PT/commandPalette.json | 50 +++ src/i18n/locales/pt-PT/common.json | 119 ++++++ src/i18n/locales/pt-PT/dashboard.json | 12 + src/i18n/locales/pt-PT/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/pt-PT/dialog.json | 159 ++++++++ src/i18n/locales/pt-PT/messages.json | 40 ++ src/i18n/locales/pt-PT/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/pt-PT/nodes.json | 51 +++ src/i18n/locales/pt-PT/ui.json | 201 +++++++++ src/i18n/locales/sv-SE/channels.json | 69 ++++ src/i18n/locales/sv-SE/commandPalette.json | 50 +++ src/i18n/locales/sv-SE/common.json | 119 ++++++ src/i18n/locales/sv-SE/dashboard.json | 12 + src/i18n/locales/sv-SE/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/sv-SE/dialog.json | 159 ++++++++ src/i18n/locales/sv-SE/messages.json | 40 ++ src/i18n/locales/sv-SE/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/sv-SE/nodes.json | 51 +++ src/i18n/locales/sv-SE/ui.json | 201 +++++++++ src/i18n/locales/tr-TR/channels.json | 69 ++++ src/i18n/locales/tr-TR/commandPalette.json | 50 +++ src/i18n/locales/tr-TR/common.json | 119 ++++++ src/i18n/locales/tr-TR/dashboard.json | 12 + src/i18n/locales/tr-TR/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/tr-TR/dialog.json | 159 ++++++++ src/i18n/locales/tr-TR/messages.json | 40 ++ src/i18n/locales/tr-TR/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/tr-TR/nodes.json | 51 +++ src/i18n/locales/tr-TR/ui.json | 201 +++++++++ src/i18n/locales/uk-UA/channels.json | 69 ++++ src/i18n/locales/uk-UA/commandPalette.json | 50 +++ src/i18n/locales/uk-UA/common.json | 119 ++++++ src/i18n/locales/uk-UA/dashboard.json | 12 + src/i18n/locales/uk-UA/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/uk-UA/dialog.json | 159 ++++++++ src/i18n/locales/uk-UA/messages.json | 40 ++ src/i18n/locales/uk-UA/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/uk-UA/nodes.json | 51 +++ src/i18n/locales/uk-UA/ui.json | 201 +++++++++ src/i18n/locales/zh-CN/channels.json | 69 ++++ src/i18n/locales/zh-CN/commandPalette.json | 50 +++ src/i18n/locales/zh-CN/common.json | 119 ++++++ src/i18n/locales/zh-CN/dashboard.json | 12 + src/i18n/locales/zh-CN/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/zh-CN/dialog.json | 159 ++++++++ src/i18n/locales/zh-CN/messages.json | 40 ++ src/i18n/locales/zh-CN/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/zh-CN/nodes.json | 51 +++ src/i18n/locales/zh-CN/ui.json | 201 +++++++++ 140 files changed, 22078 insertions(+) create mode 100644 src/i18n/locales/bg-BG/channels.json create mode 100644 src/i18n/locales/bg-BG/commandPalette.json create mode 100644 src/i18n/locales/bg-BG/common.json create mode 100644 src/i18n/locales/bg-BG/dashboard.json create mode 100644 src/i18n/locales/bg-BG/deviceConfig.json create mode 100644 src/i18n/locales/bg-BG/dialog.json create mode 100644 src/i18n/locales/bg-BG/messages.json create mode 100644 src/i18n/locales/bg-BG/moduleConfig.json create mode 100644 src/i18n/locales/bg-BG/nodes.json create mode 100644 src/i18n/locales/bg-BG/ui.json create mode 100644 src/i18n/locales/cs-CZ/channels.json create mode 100644 src/i18n/locales/cs-CZ/commandPalette.json create mode 100644 src/i18n/locales/cs-CZ/common.json create mode 100644 src/i18n/locales/cs-CZ/dashboard.json create mode 100644 src/i18n/locales/cs-CZ/deviceConfig.json create mode 100644 src/i18n/locales/cs-CZ/dialog.json create mode 100644 src/i18n/locales/cs-CZ/messages.json create mode 100644 src/i18n/locales/cs-CZ/moduleConfig.json create mode 100644 src/i18n/locales/cs-CZ/nodes.json create mode 100644 src/i18n/locales/cs-CZ/ui.json create mode 100644 src/i18n/locales/de-DE/channels.json create mode 100644 src/i18n/locales/de-DE/commandPalette.json create mode 100644 src/i18n/locales/de-DE/common.json create mode 100644 src/i18n/locales/de-DE/dashboard.json create mode 100644 src/i18n/locales/de-DE/deviceConfig.json create mode 100644 src/i18n/locales/de-DE/dialog.json create mode 100644 src/i18n/locales/de-DE/messages.json create mode 100644 src/i18n/locales/de-DE/moduleConfig.json create mode 100644 src/i18n/locales/de-DE/nodes.json create mode 100644 src/i18n/locales/de-DE/ui.json create mode 100644 src/i18n/locales/es-ES/channels.json create mode 100644 src/i18n/locales/es-ES/commandPalette.json create mode 100644 src/i18n/locales/es-ES/common.json create mode 100644 src/i18n/locales/es-ES/dashboard.json create mode 100644 src/i18n/locales/es-ES/deviceConfig.json create mode 100644 src/i18n/locales/es-ES/dialog.json create mode 100644 src/i18n/locales/es-ES/messages.json create mode 100644 src/i18n/locales/es-ES/moduleConfig.json create mode 100644 src/i18n/locales/es-ES/nodes.json create mode 100644 src/i18n/locales/es-ES/ui.json create mode 100644 src/i18n/locales/fi-FI/channels.json create mode 100644 src/i18n/locales/fi-FI/commandPalette.json create mode 100644 src/i18n/locales/fi-FI/common.json create mode 100644 src/i18n/locales/fi-FI/dashboard.json create mode 100644 src/i18n/locales/fi-FI/deviceConfig.json create mode 100644 src/i18n/locales/fi-FI/dialog.json create mode 100644 src/i18n/locales/fi-FI/messages.json create mode 100644 src/i18n/locales/fi-FI/moduleConfig.json create mode 100644 src/i18n/locales/fi-FI/nodes.json create mode 100644 src/i18n/locales/fi-FI/ui.json create mode 100644 src/i18n/locales/fr-FR/channels.json create mode 100644 src/i18n/locales/fr-FR/commandPalette.json create mode 100644 src/i18n/locales/fr-FR/common.json create mode 100644 src/i18n/locales/fr-FR/dashboard.json create mode 100644 src/i18n/locales/fr-FR/deviceConfig.json create mode 100644 src/i18n/locales/fr-FR/dialog.json create mode 100644 src/i18n/locales/fr-FR/messages.json create mode 100644 src/i18n/locales/fr-FR/moduleConfig.json create mode 100644 src/i18n/locales/fr-FR/nodes.json create mode 100644 src/i18n/locales/fr-FR/ui.json create mode 100644 src/i18n/locales/it-IT/channels.json create mode 100644 src/i18n/locales/it-IT/commandPalette.json create mode 100644 src/i18n/locales/it-IT/common.json create mode 100644 src/i18n/locales/it-IT/dashboard.json create mode 100644 src/i18n/locales/it-IT/deviceConfig.json create mode 100644 src/i18n/locales/it-IT/dialog.json create mode 100644 src/i18n/locales/it-IT/messages.json create mode 100644 src/i18n/locales/it-IT/moduleConfig.json create mode 100644 src/i18n/locales/it-IT/nodes.json create mode 100644 src/i18n/locales/it-IT/ui.json create mode 100644 src/i18n/locales/ja-JP/channels.json create mode 100644 src/i18n/locales/ja-JP/commandPalette.json create mode 100644 src/i18n/locales/ja-JP/common.json create mode 100644 src/i18n/locales/ja-JP/dashboard.json create mode 100644 src/i18n/locales/ja-JP/deviceConfig.json create mode 100644 src/i18n/locales/ja-JP/dialog.json create mode 100644 src/i18n/locales/ja-JP/messages.json create mode 100644 src/i18n/locales/ja-JP/moduleConfig.json create mode 100644 src/i18n/locales/ja-JP/nodes.json create mode 100644 src/i18n/locales/ja-JP/ui.json create mode 100644 src/i18n/locales/nl-NL/channels.json create mode 100644 src/i18n/locales/nl-NL/commandPalette.json create mode 100644 src/i18n/locales/nl-NL/common.json create mode 100644 src/i18n/locales/nl-NL/dashboard.json create mode 100644 src/i18n/locales/nl-NL/deviceConfig.json create mode 100644 src/i18n/locales/nl-NL/dialog.json create mode 100644 src/i18n/locales/nl-NL/messages.json create mode 100644 src/i18n/locales/nl-NL/moduleConfig.json create mode 100644 src/i18n/locales/nl-NL/nodes.json create mode 100644 src/i18n/locales/nl-NL/ui.json create mode 100644 src/i18n/locales/pt-PT/channels.json create mode 100644 src/i18n/locales/pt-PT/commandPalette.json create mode 100644 src/i18n/locales/pt-PT/common.json create mode 100644 src/i18n/locales/pt-PT/dashboard.json create mode 100644 src/i18n/locales/pt-PT/deviceConfig.json create mode 100644 src/i18n/locales/pt-PT/dialog.json create mode 100644 src/i18n/locales/pt-PT/messages.json create mode 100644 src/i18n/locales/pt-PT/moduleConfig.json create mode 100644 src/i18n/locales/pt-PT/nodes.json create mode 100644 src/i18n/locales/pt-PT/ui.json create mode 100644 src/i18n/locales/sv-SE/channels.json create mode 100644 src/i18n/locales/sv-SE/commandPalette.json create mode 100644 src/i18n/locales/sv-SE/common.json create mode 100644 src/i18n/locales/sv-SE/dashboard.json create mode 100644 src/i18n/locales/sv-SE/deviceConfig.json create mode 100644 src/i18n/locales/sv-SE/dialog.json create mode 100644 src/i18n/locales/sv-SE/messages.json create mode 100644 src/i18n/locales/sv-SE/moduleConfig.json create mode 100644 src/i18n/locales/sv-SE/nodes.json create mode 100644 src/i18n/locales/sv-SE/ui.json create mode 100644 src/i18n/locales/tr-TR/channels.json create mode 100644 src/i18n/locales/tr-TR/commandPalette.json create mode 100644 src/i18n/locales/tr-TR/common.json create mode 100644 src/i18n/locales/tr-TR/dashboard.json create mode 100644 src/i18n/locales/tr-TR/deviceConfig.json create mode 100644 src/i18n/locales/tr-TR/dialog.json create mode 100644 src/i18n/locales/tr-TR/messages.json create mode 100644 src/i18n/locales/tr-TR/moduleConfig.json create mode 100644 src/i18n/locales/tr-TR/nodes.json create mode 100644 src/i18n/locales/tr-TR/ui.json create mode 100644 src/i18n/locales/uk-UA/channels.json create mode 100644 src/i18n/locales/uk-UA/commandPalette.json create mode 100644 src/i18n/locales/uk-UA/common.json create mode 100644 src/i18n/locales/uk-UA/dashboard.json create mode 100644 src/i18n/locales/uk-UA/deviceConfig.json create mode 100644 src/i18n/locales/uk-UA/dialog.json create mode 100644 src/i18n/locales/uk-UA/messages.json create mode 100644 src/i18n/locales/uk-UA/moduleConfig.json create mode 100644 src/i18n/locales/uk-UA/nodes.json create mode 100644 src/i18n/locales/uk-UA/ui.json create mode 100644 src/i18n/locales/zh-CN/channels.json create mode 100644 src/i18n/locales/zh-CN/commandPalette.json create mode 100644 src/i18n/locales/zh-CN/common.json create mode 100644 src/i18n/locales/zh-CN/dashboard.json create mode 100644 src/i18n/locales/zh-CN/deviceConfig.json create mode 100644 src/i18n/locales/zh-CN/dialog.json create mode 100644 src/i18n/locales/zh-CN/messages.json create mode 100644 src/i18n/locales/zh-CN/moduleConfig.json create mode 100644 src/i18n/locales/zh-CN/nodes.json create mode 100644 src/i18n/locales/zh-CN/ui.json diff --git a/src/i18n/locales/bg-BG/channels.json b/src/i18n/locales/bg-BG/channels.json new file mode 100644 index 00000000..10379e7b --- /dev/null +++ b/src/i18n/locales/bg-BG/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Канали", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Настройки на канала", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Роля", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Име", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/bg-BG/commandPalette.json b/src/i18n/locales/bg-BG/commandPalette.json new file mode 100644 index 00000000..83140af2 --- /dev/null +++ b/src/i18n/locales/bg-BG/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Съобщения", + "map": "Карта", + "config": "Config", + "channels": "Канали", + "nodes": "Възли" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Импортиране", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/bg-BG/common.json b/src/i18n/locales/bg-BG/common.json new file mode 100644 index 00000000..3f874ddb --- /dev/null +++ b/src/i18n/locales/bg-BG/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Приложи", + "backupKey": "Backup Key", + "cancel": "Отказ", + "clearMessages": "Clear Messages", + "close": "Затвори", + "confirm": "Confirm", + "delete": "Изтриване", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Импортиране", + "message": "Съобщение", + "now": "Now", + "ok": "Добре", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Изтрий", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Нулиране", + "save": "Запис", + "scanQr": "Сканиране на QR кода", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/bg-BG/dashboard.json b/src/i18n/locales/bg-BG/dashboard.json new file mode 100644 index 00000000..e2b64fed --- /dev/null +++ b/src/i18n/locales/bg-BG/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Мрежа", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/bg-BG/deviceConfig.json b/src/i18n/locales/bg-BG/deviceConfig.json new file mode 100644 index 00000000..b44b77ee --- /dev/null +++ b/src/i18n/locales/bg-BG/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Устройство", + "tabDisplay": "Дисплей", + "tabLora": "LoRa", + "tabNetwork": "Мрежа", + "tabPosition": "Позиция", + "tabPower": "Захранване", + "tabSecurity": "Сигурност" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX часова зона" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Роля" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Режим на сдвояване" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Широчина на честотната лента" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Регион" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Шлюз" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Конфигурация на UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Времево клеймо", + "unset": "Отказ", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Активиране на енергоспестяващ режим" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Конфигурация на захранването" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Частен ключ" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Публичен ключ" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/bg-BG/dialog.json b/src/i18n/locales/bg-BG/dialog.json new file mode 100644 index 00000000..8d8e484a --- /dev/null +++ b/src/i18n/locales/bg-BG/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Свързване", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Съобщение", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Напрежение", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Сигурни ли сте?" + } +} diff --git a/src/i18n/locales/bg-BG/messages.json b/src/i18n/locales/bg-BG/messages.json new file mode 100644 index 00000000..56f346cd --- /dev/null +++ b/src/i18n/locales/bg-BG/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Изпрати" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/bg-BG/moduleConfig.json b/src/i18n/locales/bg-BG/moduleConfig.json new file mode 100644 index 00000000..32633d61 --- /dev/null +++ b/src/i18n/locales/bg-BG/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Телеметрия" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Червен", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Зелен", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Син", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Брой записи", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/bg-BG/nodes.json b/src/i18n/locales/bg-BG/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/bg-BG/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/bg-BG/ui.json b/src/i18n/locales/bg-BG/ui.json new file mode 100644 index 00000000..bab99b20 --- /dev/null +++ b/src/i18n/locales/bg-BG/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Съобщения", + "map": "Карта", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Канали", + "nodes": "Възли" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Фърмуер", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Батерия" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Скриване на паролата" + }, + "showPassword": { + "label": "Показване на паролата" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Хардуер" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Роля" + }, + "filter": { + "label": "Филтър" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Напрежение" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Последно чут", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Език", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Тъмна", + "light": "Светла", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/cs-CZ/channels.json b/src/i18n/locales/cs-CZ/channels.json new file mode 100644 index 00000000..33ae9f54 --- /dev/null +++ b/src/i18n/locales/cs-CZ/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanály", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primární", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Nastavení kanálu", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Jméno", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/cs-CZ/commandPalette.json b/src/i18n/locales/cs-CZ/commandPalette.json new file mode 100644 index 00000000..df166149 --- /dev/null +++ b/src/i18n/locales/cs-CZ/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Zprávy", + "map": "Mapa", + "config": "Config", + "channels": "Kanály", + "nodes": "Uzly" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/cs-CZ/common.json b/src/i18n/locales/cs-CZ/common.json new file mode 100644 index 00000000..dd918f3b --- /dev/null +++ b/src/i18n/locales/cs-CZ/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Použít", + "backupKey": "Backup Key", + "cancel": "Zrušit", + "clearMessages": "Clear Messages", + "close": "Zavřít", + "confirm": "Confirm", + "delete": "Smazat", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Zpráva", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Odstranit", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Uložit", + "scanQr": "Naskenovat QR kód", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/cs-CZ/dashboard.json b/src/i18n/locales/cs-CZ/dashboard.json new file mode 100644 index 00000000..f73dc07c --- /dev/null +++ b/src/i18n/locales/cs-CZ/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Sériová komunikace", + "connectionType_network": "Síť", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/cs-CZ/deviceConfig.json b/src/i18n/locales/cs-CZ/deviceConfig.json new file mode 100644 index 00000000..6e5cb4e0 --- /dev/null +++ b/src/i18n/locales/cs-CZ/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Zařízení", + "tabDisplay": "Obrazovka", + "tabLora": "LoRa", + "tabNetwork": "Síť", + "tabPosition": "Pozice", + "tabPower": "Napájení", + "tabSecurity": "Zabezpečení" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Dvojité klepnutí jako stisk tlačítka" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX časové pásmo" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Režim opětovného vysílání" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Nastavení Bluetooth", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Povoleno" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Režim párování" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Šířka pásma" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignorovat MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Předvolba modemu" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK do MQTT" + }, + "overrideDutyCycle": { + "description": "Přepsat střídu", + "label": "Přepsat střídu" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Povoleno" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway/Brána" + }, + "ip": { + "description": "IP Address", + "label": "IP adresa" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Podsíť" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Povoleno" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Konfigurace" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Časová značka", + "unset": "Zrušit nastavení", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Povolit úsporný režim" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Nastavení napájení" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Soukromý klíč" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Veřejný klíč" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/cs-CZ/dialog.json b/src/i18n/locales/cs-CZ/dialog.json new file mode 100644 index 00000000..cf2c0735 --- /dev/null +++ b/src/i18n/locales/cs-CZ/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Sériová komunikace", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Zpráva", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Napětí", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Jste si jistý?" + } +} diff --git a/src/i18n/locales/cs-CZ/messages.json b/src/i18n/locales/cs-CZ/messages.json new file mode 100644 index 00000000..12f340e9 --- /dev/null +++ b/src/i18n/locales/cs-CZ/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Odeslat" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/cs-CZ/moduleConfig.json b/src/i18n/locales/cs-CZ/moduleConfig.json new file mode 100644 index 00000000..69d76cfe --- /dev/null +++ b/src/i18n/locales/cs-CZ/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambientní osvětlení", + "tabAudio": "Zvuk", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detekční senzor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Informace o sousedech", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Zkouška dosahu", + "tabSerial": "Sériová komunikace", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetrie" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Proud", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Červená", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Zelená", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Modrá", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Povoleno", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Povoleno", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS povoleno", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Kořenové téma", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Povoleno", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Vypršel čas spojení", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Počet záznamů", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Interval aktualizace měření spotřeby (v sekundách)" + }, + "environmentUpdateInterval": { + "label": "Interval aktualizace měření životního prostředí (v sekundách)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/cs-CZ/nodes.json b/src/i18n/locales/cs-CZ/nodes.json new file mode 100644 index 00000000..4f0694de --- /dev/null +++ b/src/i18n/locales/cs-CZ/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Oblíbené" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Přímý", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/cs-CZ/ui.json b/src/i18n/locales/cs-CZ/ui.json new file mode 100644 index 00000000..f173ed53 --- /dev/null +++ b/src/i18n/locales/cs-CZ/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Zprávy", + "map": "Mapa", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Kanály", + "nodes": "Uzly" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Baterie" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Skrýt heslo" + }, + "showPassword": { + "label": "Zobrazit heslo" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metriky" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filtr" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Napětí" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Přímý", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Naposledy slyšen", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Jazyk", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Tmavý", + "light": "Světlý", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/de-DE/channels.json b/src/i18n/locales/de-DE/channels.json new file mode 100644 index 00000000..7048124e --- /dev/null +++ b/src/i18n/locales/de-DE/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanäle", + "channelName": "Kanal {{channelName}}", + "broadcastLabel": "Primär", + "channelIndex": "Kanal {{index}}" + }, + "validation": { + "pskInvalid": "Bitte geben Sie einen gültigen {{bits}} Bit PSK Schlüssel ein." + }, + "settings": { + "label": "Kanaleinstellungen", + "description": "Verschlüsselung, MQTT & sonstige Einstellungen" + }, + "role": { + "label": "Rolle", + "description": "Gerätetelemetrie wird über den PRIMÄR Kanal gesendet. Nur ein PRIMÄR Kanal ist erlaubt.", + "options": { + "primary": "PRIMÄR", + "disabled": "DEAKTIVIERT", + "secondary": "SEKUNDÄR" + } + }, + "psk": { + "label": "Vorher verteilter Schlüssel", + "description": "Unterstützte PSK-Längen: 256-Bit, 128-Bit, 8-Bit, leer (0-Bit)", + "generate": "Erzeugen" + }, + "name": { + "label": "Name", + "description": "Ein eindeutiger Name für den Kanal <12 Bytes. Leer lassen für Standard." + }, + "uplinkEnabled": { + "label": "Uplink aktiviert", + "description": "Nachrichten vom lokalen Netz über MQTT versenden" + }, + "downlinkEnabled": { + "label": "Downlink aktiviert", + "description": "Nachrichten von MQTT im lokalen Netz versenden" + }, + "positionPrecision": { + "label": "Standort", + "description": "Die Genauigkeit des Standorts, die in diesem Kanal geteilt werden soll. Kann deaktiviert werden.", + "options": { + "none": "Standort nicht freigeben", + "precise": "Genauer Standort", + "metric_km23": "Innerhalb von 23 Kilometern", + "metric_km12": "Innerhalb von 12 Kilometern", + "metric_km5_8": "Innerhalb von 5,8 Kilometern", + "metric_km2_9": "Innerhalb von 2,9 Kilometern", + "metric_km1_5": "Innerhalb von 1,5 Kilometern", + "metric_m700": "Innerhalb von 700 Metern", + "metric_m350": "Innerhalb von 350 Metern", + "metric_m200": "Innerhalb von 200 Metern", + "metric_m90": "Innerhalb von 90 Metern", + "metric_m50": "Innerhalb von 50 Metern", + "imperial_mi15": "Innerhalb von 15 Meilen", + "imperial_mi7_3": "Innerhalb von 7,3 Meilen", + "imperial_mi3_6": "Innerhalb von 3,6 Meilen", + "imperial_mi1_8": "Innerhalb von 1,8 Meilen", + "imperial_mi0_9": "Innerhalb von 0,9 Meilen", + "imperial_mi0_5": "Innerhalb von 0,5 Meilen", + "imperial_mi0_2": "Innerhalb von 0,2 Meilen", + "imperial_ft600": "Innerhalb von 600 Fuß", + "imperial_ft300": "Innerhalb von 300 Fuß", + "imperial_ft150": "Innerhalb von 150 Fuß" + } + } +} diff --git a/src/i18n/locales/de-DE/commandPalette.json b/src/i18n/locales/de-DE/commandPalette.json new file mode 100644 index 00000000..63114907 --- /dev/null +++ b/src/i18n/locales/de-DE/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "Keine Ergebnisse gefunden.", + "page": { + "title": "Befehlsmenü" + }, + "pinGroup": { + "label": "Befehlsgruppe anheften" + }, + "unpinGroup": { + "label": "Befehlsgruppe lösen" + }, + "goto": { + "label": "Gehe zu", + "command": { + "messages": "Nachrichten", + "map": "Karte", + "config": "Einstellungen", + "channels": "Kanäle", + "nodes": "Knoten" + } + }, + "manage": { + "label": "Verwalten", + "command": { + "switchNode": "Knoten wechseln", + "connectNewNode": "Neuen Knoten verbinden" + } + }, + "contextual": { + "label": "Kontextabhängig", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Importieren", + "scheduleShutdown": "Herunterfahren planen", + "scheduleReboot": "Neustarten planen", + "rebootToOtaMode": "Neustart in den OTA Modus", + "resetNodeDb": "Knotendatenbank zurücksetzen", + "factoryResetDevice": "Gerät auf Werkseinstellungen zurücksetzen", + "factoryResetConfig": "Auf Werkseinstellungen zurücksetzen" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Neu einrichten", + "clearAllStoredMessages": "Alle gespeicherten Nachrichten löschen" + } + } +} diff --git a/src/i18n/locales/de-DE/common.json b/src/i18n/locales/de-DE/common.json new file mode 100644 index 00000000..3a8af3a5 --- /dev/null +++ b/src/i18n/locales/de-DE/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Anwenden", + "backupKey": "Schlüssel sichern", + "cancel": "Abbrechen", + "clearMessages": "Nachrichten löschen", + "close": "Schließen", + "confirm": "Bestätigen", + "delete": "Löschen", + "dismiss": "Tastatur ausblenden", + "download": "Herunterladen", + "export": "Exportieren", + "generate": "Erzeugen", + "regenerate": "Neu erzeugen", + "import": "Importieren", + "message": "Nachricht", + "now": "Jetzt", + "ok": "Ok", + "print": "Drucken", + "rebootOtaNow": "Neustart in den OTA Modus", + "remove": "Entfernen", + "requestNewKeys": "Neue Schlüssel anfordern", + "requestPosition": "Standort anfordern", + "reset": "Zurücksetzen", + "save": "Speichern", + "scanQr": "QR Code scannen", + "traceRoute": "Route verfolgen" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web-Applikation" + }, + "loading": "Wird geladen...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Sprung", + "plural": "Sprünge" + }, + "hopsAway": { + "one": "{{count}} Sprung entfernt", + "plural": "{{count}} Sprünge entfernt", + "unknown": "Sprungweite unbekannt" + }, + "megahertz": "MHz", + "raw": "Einheitslos", + "meter": { + "one": "Meter", + "plural": "Meter", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minuten" + }, + "millisecond": { + "one": "Millisekunde", + "plural": "Millisekunden", + "suffix": "ms" + }, + "second": { + "one": "Sekunde", + "plural": "Sekunden" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volt", + "suffix": "V" + }, + "record": { + "one": "Datensatz", + "plural": "Datensätze" + } + }, + "security": { + "256bit": "256 Bit" + }, + "unknown": { + "longName": "Unbekannt", + "shortName": "UNB", + "notAvailable": "Keine Angaben", + "num": "???" + }, + "nodeUnknownPrefix": "!", + "unset": "NICHT GESETZT", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Zu lang, erwarte maximal {{maximum}} Zeichen.", + "number": "Zu groß, erwartete eine Zahl kleiner oder gleich {{maximum}}.", + "bytes": "Zu groß, erwarte maximal {{params.maximum}} Bytes." + }, + "tooSmall": { + "string": "Zu kurz, erwartete mindestens {{minimum}} Zeichen.", + "number": "Zu klein, erwartete eine Zahl größer oder gleich {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Ungültiges Format, erwartete eine IPv4 Adresse.", + "key": "Ungültiges Format, erwartet einen Base64-kodierten vor verteilten Schlüssel (PSK)." + }, + "invalidType": { + "number": "Ungültiger Typ, erwartete eine Zahl." + }, + "pskLength": { + "0bit": "Der Schlüssel muss leer sein.", + "8bit": "Der administrative Schlüssel muss ein vor verteilter 8 Bit Schlüssel (PSK) sein.", + "128bit": "Der administrative Schlüssel muss ein vor verteilter 128 Bit Schlüssel (PSK) sein.", + "256bit": "Der administrative Schlüssel muss ein vor verteilter 256 Bit Schlüssel (PSK) sein." + }, + "required": { + "generic": "Dies ist ein Pflichtfeld.", + "managed": "Mindestens ein administrativer Schlüssel wird benötigt, um diesen Knoten zu verwalten", + "key": "Schlüssel erforderlich." + } + } +} diff --git a/src/i18n/locales/de-DE/dashboard.json b/src/i18n/locales/de-DE/dashboard.json new file mode 100644 index 00000000..5ec2de3d --- /dev/null +++ b/src/i18n/locales/de-DE/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Verbundene Geräte", + "description": "Verwalten Sie Ihre verbundenen Meshtastic Geräte.", + "connectionType_ble": "BLE", + "connectionType_serial": "Seriell", + "connectionType_network": "Netzwerk", + "noDevicesTitle": "Keine Geräte verbunden", + "noDevicesDescription": "Verbinden Sie ein neues Gerät, um zu beginnen.", + "button_newConnection": "Neue Verbindung" + } +} diff --git a/src/i18n/locales/de-DE/deviceConfig.json b/src/i18n/locales/de-DE/deviceConfig.json new file mode 100644 index 00000000..12a24450 --- /dev/null +++ b/src/i18n/locales/de-DE/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Einstellungen", + "tabBluetooth": "Bluetooth", + "tabDevice": "Gerät", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Netzwerk", + "tabPosition": "Standort", + "tabPower": "Leistung", + "tabSecurity": "Sicherheit" + }, + "sidebar": { + "label": "Module" + }, + "device": { + "title": "Geräteeinstellungen", + "description": "Einstellungen für dieses Gerät", + "buttonPin": { + "description": "GPIO für Taste überschreiben", + "label": "GPIO Taste" + }, + "buzzerPin": { + "description": "GPIO für Summer überschreiben", + "label": "GPIO Summer" + }, + "disableTripleClick": { + "description": "Dreifachklicken deaktivieren", + "label": "Dreifachklicken deaktivieren" + }, + "doubleTapAsButtonPress": { + "description": "Doppeltes Tippen als Taste verwenden", + "label": "Doppelklick als Tastendruck" + }, + "ledHeartbeatDisabled": { + "description": "Die Herzschlag LED deaktivieren", + "label": "Herzschlag LED deaktivieren" + }, + "nodeInfoBroadcastInterval": { + "description": "Häufigkeit der Übertragung von Knoteninformationen", + "label": "Knoteninfo Übertragungsintervall" + }, + "posixTimezone": { + "description": "Zeichenfolge der POSIX Zeitzone für dieses Gerät", + "label": "POSIX Zeitzone" + }, + "rebroadcastMode": { + "description": "Wie Weiterleitungen behandelt werden", + "label": "Weiterleitungsmodus" + }, + "role": { + "description": "In welche Rolle das Gerät im Netz arbeitet", + "label": "Rolle" + } + }, + "bluetooth": { + "title": "Bluetooth Einstellungen", + "description": "Einstellungen für das Bluetooth Modul", + "note": "Hinweis: Einige Geräte (ESP32) können nicht gleichzeitig Bluetooth und WLAN verwenden.", + "enabled": { + "description": "Bluetooth aktivieren oder deaktivieren", + "label": "Aktiviert" + }, + "pairingMode": { + "description": "PIN Nummer Auswahlverhalten", + "label": "Kopplungsmodus" + }, + "pin": { + "description": "PIN Nummer zum Verbinden verwenden", + "label": "PIN Nummer" + } + }, + "display": { + "description": "Einstellungen für die Geräteanzeige", + "title": "Anzeigeeinstellungen", + "headingBold": { + "description": "Überschrifttext fett darstellen", + "label": "Fette Überschrift" + }, + "carouselDelay": { + "description": "Bestimmt wie schnell die Fenster durch gewechselt werden", + "label": "Karussellverzögerung" + }, + "compassNorthTop": { + "description": "Norden im Kompass immer oben anzeigen", + "label": "Kompass Norden oben" + }, + "displayMode": { + "description": "Variante des Anzeigelayout", + "label": "Anzeigemodus" + }, + "displayUnits": { + "description": "Zeige metrische oder imperiale Einheiten", + "label": "Anzeigeeinheiten" + }, + "flipScreen": { + "description": "Anzeige um 180 Grad drehen", + "label": "Anzeige drehen" + }, + "gpsDisplayUnits": { + "description": "Anzeigeformat der Koordinaten", + "label": "GPS Anzeigeformat" + }, + "oledType": { + "description": "Art des OLED Anzeige, die an dem Gerät angeschlossen ist", + "label": "OLED Typ" + }, + "screenTimeout": { + "description": "Anzeige nach dieser Zeit automatisch ausschalten", + "label": "Anzeigeabschaltung" + }, + "twelveHourClock": { + "description": "12-Stunden Format benutzen", + "label": "12-Stunden Uhr" + }, + "wakeOnTapOrMotion": { + "description": "Gerät durch Tippen oder Bewegung aufwecken", + "label": "Aufwachen durch Tippen oder Bewegung" + } + }, + "lora": { + "title": "Netzeinstellungen", + "description": "Einstellungen für das LoRa Netz", + "bandwidth": { + "description": "Kanalbandbreite in MHz", + "label": "Bandbreite" + }, + "boostedRxGain": { + "description": "Erhöhte Empfangsverstärkung", + "label": "Erhöhte Empfangsverstärkung" + }, + "codingRate": { + "description": "Kodierrate", + "label": "Fehlerkorrektur" + }, + "frequencyOffset": { + "description": "Frequenzversatz zur Kalibrierung von Oszillatorfehlern", + "label": "Frequenzversatz" + }, + "frequencySlot": { + "description": "LoRa Frequenzschlitz", + "label": "Frequenzschlitz" + }, + "hopLimit": { + "description": "Maximale Sprungweite", + "label": "Sprungweite" + }, + "ignoreMqtt": { + "description": "MQTT Nachrichten nicht über das Netz weiterleiten", + "label": "MQTT ignorieren" + }, + "modemPreset": { + "description": "Modem Voreinstellung die verwendet wird", + "label": "Modem Voreinstellungen" + }, + "okToMqtt": { + "description": "Wenn auf aktiviert, zeigt diese Einstellung an, dass der Benutzer das Weiterleiten von Nachrichten über MQTT akzeptiert. Wenn deaktiviert, werden entfernte Knoten aufgefordert, Nachrichten nicht über MQTT weiterzuleiten", + "label": "OK für MQTT" + }, + "overrideDutyCycle": { + "description": "Duty-Cycle überschreiben", + "label": "Duty-Cycle überschreiben" + }, + "overrideFrequency": { + "description": "Sendefrequenz überschreiben (MHz)", + "label": "Sendefrequenz überschreiben" + }, + "region": { + "description": "Legt die Region für Ihren Knoten fest", + "label": "Region" + }, + "spreadingFactor": { + "description": "Anzahl der Symbole zur Kodierung der Nutzdaten", + "label": "Spreizfaktor" + }, + "transmitEnabled": { + "description": "Sender (TX) des LoRa Funkgerätes aktivieren/deaktivieren", + "label": "Senden aktiviert" + }, + "transmitPower": { + "description": "Maximale Sendeleistung", + "label": "Sendeleistung" + }, + "usePreset": { + "description": "Eine der vordefinierten Modem Voreinstellungen verwenden", + "label": "Voreinstellung verwenden" + }, + "meshSettings": { + "description": "Einstellungen für das LoRa Netz", + "label": "Netzeinstellungen" + }, + "waveformSettings": { + "description": "Einstellungen für die LoRa Wellenform", + "label": "Einstellungen der Wellenform" + }, + "radioSettings": { + "label": "Radio-Einstellungen", + "description": "Einstellungen für das LoRa Funkgerät" + } + }, + "network": { + "title": "WLAN Einstellungen", + "description": "WLAN Funkeinstellungen", + "note": "Hinweis: Einige Geräte (ESP32) können nicht gleichzeitig Bluetooth und WLAN verwenden.", + "addressMode": { + "description": "Auswahl der IP Adressenzuweisung", + "label": "IP Adressenmodus" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Aktivieren oder deaktivieren sie den Ethernet Anschluss", + "label": "Aktiviert" + }, + "gateway": { + "description": "Standard Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Adresse", + "label": "IP" + }, + "psk": { + "description": "Netzwerkpasswort", + "label": "PSK" + }, + "ssid": { + "description": "Netzwerkname", + "label": "SSID" + }, + "subnet": { + "description": "Subnetzmaske", + "label": "Subnetz" + }, + "wifiEnabled": { + "description": "Aktivieren oder deaktivieren Sie die WLAN Übertragung", + "label": "Aktiviert" + }, + "meshViaUdp": { + "label": "Netz über UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Einstellung des Ethernet Ports", + "label": "Ethernet Einstellung" + }, + "ipConfigSettings": { + "description": "Einstellung der IP Adresse", + "label": "IP Adresseinstellungen" + }, + "ntpConfigSettings": { + "description": "NTP Server Einstellungen", + "label": "NTP Einstellungen" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog Einstellung", + "label": "Rsyslog Einstellung" + }, + "udpConfigSettings": { + "description": "UDP über Netz Einstellung", + "label": "UDP Konfiguration" + } + }, + "position": { + "title": "Standorteinstellung", + "description": "Einstellungen für das Standortmodul", + "broadcastInterval": { + "description": "Wie oft Ihr Standort über das Netz gesendet wird", + "label": "Übertragungsintervall" + }, + "enablePin": { + "description": "Überschreiben des GPIO der das GPS-Modul aktiviert", + "label": "GPIO GPS aktivieren" + }, + "fixedPosition": { + "description": "GPS Standort nicht senden, sondern manuell angegeben", + "label": "Fester Standort" + }, + "gpsMode": { + "description": "Einstellung, ob GPS des Geräts aktiviert, deaktiviert oder nicht vorhanden ist", + "label": "GPS Modus" + }, + "gpsUpdateInterval": { + "description": "Wie oft ein GPS Standort ermittelt werden soll", + "label": "GPS Aktualisierungsintervall" + }, + "positionFlags": { + "description": "Optionalen, die bei der Zusammenstellung von Standortnachrichten enthalten sein sollen. Je mehr Optionen ausgewählt werden, desto größer wird die Nachricht und die längere Übertragungszeit erhöht das Risiko für einen Nachrichtenverlust.", + "label": "Standort Optionen" + }, + "receivePin": { + "description": "GPIO Pin für serielles Empfangen (RX) des GPS-Moduls überschreiben", + "label": "GPIO Empfangen" + }, + "smartPositionEnabled": { + "description": "Standort nur verschicken, wenn eine sinnvolle Standortänderung stattgefunden hat", + "label": "Intelligenten Standort aktivieren" + }, + "smartPositionMinDistance": { + "description": "Mindestabstand (in Meter), die vor dem Senden einer Standortaktualisierung zurückgelegt werden muss", + "label": "Minimale Entfernung für intelligenten Standort" + }, + "smartPositionMinInterval": { + "description": "Minimales Intervall (in Sekunden), das vor dem Senden einer Standortaktualisierung vergangen sein muss", + "label": "Minimales Intervall für intelligenten Standort" + }, + "transmitPin": { + "description": "GPIO Pin für serielles Senden (TX) des GPS-Moduls überschreiben", + "label": "GPIO Senden" + }, + "intervalsSettings": { + "description": "Wie oft Standortaktualisierungen gesendet werden", + "label": "Intervalle" + }, + "flags": { + "placeholder": "Standort Optionen auswählen", + "altitude": "Höhe", + "altitudeGeoidalSeparation": "Geoidale Höhentrennung", + "altitudeMsl": "Höhe in Bezug auf Meeresspiegel", + "dop": "Dilution of Präzision (DOP) PDOP standardmäßig verwenden", + "hdopVdop": "Wenn DOP gesetzt ist, wird HDOP / VDOP anstelle von PDOP verwendet", + "numSatellites": "Anzahl Satelliten", + "sequenceNumber": "Sequenznummer", + "timestamp": "Zeitstempel", + "unset": "Nicht konfiguriert", + "vehicleHeading": "Fahrzeugsteuerkurs", + "vehicleSpeed": "Fahrzeuggeschwindigkeit" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Zur Optimierung der Genauigkeit bei der Akkuspannunsmessung", + "label": "ADC Multiplikationsfaktor" + }, + "ina219Address": { + "description": "Adresse des INA219 Stromsensors", + "label": "INA219 Adresse" + }, + "lightSleepDuration": { + "description": "Wie lange das Gerät im leichten Schlafmodus ist", + "label": "Dauer leichter Schlafmodus" + }, + "minimumWakeTime": { + "description": "Minimale Zeitspanne für die das Gerät aktiv bleibt, nachdem es eine Nachricht empfangen hat", + "label": "Minimale Aufwachzeit" + }, + "noConnectionBluetoothDisabled": { + "description": "Wenn das Gerät keine Bluetooth Verbindung erhält, wird der BLE Funk nach dieser Zeit deaktiviert", + "label": "Keine Verbindung, Bluetooth deaktiviert" + }, + "powerSavingEnabled": { + "description": "Auswählen, wenn aus einer Stromquelle mit niedriger Kapazität (z.B Solar) betrieben wird, um den Stromverbrauch so weit wie möglich zu minimieren.", + "label": "Energiesparmodus aktivieren" + }, + "shutdownOnBatteryDelay": { + "description": "Verzögerung bis zum Abschalten der Knoten sich im Akkubetrieb befindet. 0 für unbegrenzt", + "label": "Verzögerung Akkuabschaltung" + }, + "superDeepSleepDuration": { + "description": "Wie lange das Gerät im supertiefen Schlafmodus ist", + "label": "Dauer Supertiefschlaf" + }, + "powerConfigSettings": { + "description": "Einstellungen für das Energiemodul", + "label": "Power Konfiguration" + }, + "sleepSettings": { + "description": "Einstellungen Ruhezustand für das Energiemodul", + "label": "Einstellung Ruhezustand" + } + }, + "security": { + "description": "Sicherheitseinstellungen", + "title": "Sicherheitseinstellungen", + "button_backupKey": "Schlüssel sichern", + "adminChannelEnabled": { + "description": "Erlaubt die Gerätesteuerung über den unsicheren, veralteten administrativen Kanal", + "label": "Veraltete Administrierung erlauben" + }, + "enableDebugLogApi": { + "description": "Ausgabe von Fehlerprotokollen in Echtzeit über die serielle Schnittstelle, Anzeige und Export von Standort reduzierten Geräteprotokollen über Bluetooth", + "label": "Debug-Protokoll API aktivieren" + }, + "managed": { + "description": "Wenn aktiviert, können die Geräteeinstellungen nur von einem entfernten Administratorknoten über administrative Nachrichten geändert werden. Aktivieren Sie diese Option nur, wenn mindestens ein geeigneter Administratorknoten eingerichtet, und desen öffentlicher Schlüssel wird in einem der obigen Felder gespeichert wurde.", + "label": "Verwaltet" + }, + "privateKey": { + "description": "Wird verwendet, um einen gemeinsamen Schlüssel mit einem entfernten Gerät zu erstellen", + "label": "Privater Schlüssel" + }, + "publicKey": { + "description": "Wird an andere Knoten im Netz gesendet, damit diese einen gemeinsamen geheimen Schlüssel berechnen können", + "label": "Öffentlicher Schlüssel" + }, + "primaryAdminKey": { + "description": "Erster öffentlicher Schlüssel, der berechtigt ist, administrative Nachrichten an diesen Knoten zu senden", + "label": "Erster Admin-Schlüssel" + }, + "secondaryAdminKey": { + "description": "Zweiter öffentlicher Schlüssel, der berechtigt ist, administrative Nachrichten an diesen Knoten zu senden", + "label": "Zweiter Admin-Schlüssel" + }, + "serialOutputEnabled": { + "description": "Serielle Konsole über die Stream-API", + "label": "Serielle Ausgabe aktiviert" + }, + "tertiaryAdminKey": { + "description": "Dritter öffentlicher Schlüssel, der berechtigt ist, administrative Nachrichten an diesen Knoten zu senden", + "label": "Dritter Admin-Schlüssel" + }, + "adminSettings": { + "description": "Administrator Einstellungen", + "label": "Administrator Einstellungen" + }, + "loggingSettings": { + "description": "Einstellungen für die Protokollierung", + "label": "Protokolleinstellungen" + } + } +} diff --git a/src/i18n/locales/de-DE/dialog.json b/src/i18n/locales/de-DE/dialog.json new file mode 100644 index 00000000..b385e70b --- /dev/null +++ b/src/i18n/locales/de-DE/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "Diese Aktion wird den Nachrichtenverlauf löschen. Dies kann nicht rückgängig gemacht werden. Sind Sie sicher, dass Sie fortfahren möchten?", + "title": "Alle Nachrichten löschen" + }, + "deviceName": { + "description": "Das Gerät wird neu gestartet, sobald die Einstellung gespeichert ist.", + "longName": "Langer Name", + "shortName": "Kurzname", + "title": "Gerätename ändern" + }, + "import": { + "description": "Die aktuelle LoRa Einstellung wird überschrieben.", + "error": { + "invalidUrl": "Ungültige Meshtastic URL" + }, + "channelPrefix": "Kanal: ", + "channelSetUrl": "Kanalsammlung / QR-Code URL", + "channels": "Kanäle:", + "usePreset": "Voreinstellung verwenden?", + "title": "Kanalsammlung importieren" + }, + "locationResponse": { + "altitude": "Höhe: ", + "coordinates": "Koordinaten: ", + "title": "Standort: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Vorab verteilten Schlüssel (PSK) neu erstellen?", + "description": "Sind Sie sicher, dass Sie den vorab verteilten Schlüssel neu erstellen möchten?", + "regenerate": "Neu erstellen" + }, + "newDeviceDialog": { + "title": "Neues Gerät verbinden", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seriell", + "useHttps": "HTTPS verwenden", + "connecting": "Wird verbunden...", + "connect": "Verbindung herstellen", + "connectionFailedAlert": { + "title": "Verbindung fehlgeschlagen", + "descriptionPrefix": "Verbindung zum Gerät fehlgeschlagen. ", + "httpsHint": "Wenn Sie HTTPS verwenden, müssen Sie möglicherweise zuerst ein selbstsigniertes Zertifikat akzeptieren. ", + "openLinkPrefix": "Öffnen Sie ", + "openLinkSuffix": "in einem neuen Tab", + "acceptTlsWarningSuffix": ", akzeptieren Sie alle TLS-Warnungen, wenn Sie dazu aufgefordert werden, dann versuchen Sie es erneut", + "learnMoreLink": "Mehr erfahren" + }, + "httpConnection": { + "label": "IP Adresse/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "Noch keine Geräte gekoppelt.", + "newDeviceButton": "Neues Gerät", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "Noch keine Geräte gekoppelt.", + "newDeviceButton": "Neues Gerät" + }, + "validation": { + "requiresFeatures": "Dieser Verbindungstyp erfordert <0>. Bitte verwenden Sie einen unterstützten Browser, wie Chrome oder Edge.", + "requiresSecureContext": "Diese Anwendung erfordert einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost.", + "additionallyRequiresSecureContext": "Zusätzlich erfordert es einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost." + } + }, + "nodeDetails": { + "message": "Nachricht", + "requestPosition": "Standort anfordern", + "traceRoute": "Route verfolgen", + "airTxUtilization": "Auslastung Sendezeit", + "allRawMetrics": "Alle Rohdaten", + "batteryLevel": "Akkustand", + "channelUtilization": "Kanalauslastung", + "details": "Details:", + "deviceMetrics": "Gerätekennzahlen:", + "hardware": "Hardware: ", + "lastHeard": "Zuletzt gehört: ", + "nodeHexPrefix": "Knoten ID: !", + "nodeNumber": "Knotennummer: ", + "position": "Standort:", + "role": "Rolle: ", + "uptime": "Laufzeit: ", + "voltage": "Spannung", + "title": "Knotendetails für {{identifier}}", + "ignoreNode": "Knoten ignorieren", + "removeNode": "Knoten entfernen", + "unignoreNode": "Knoten akzeptieren" + }, + "pkiBackup": { + "description": "Wir empfehlen die regelmäßige Sicherung Ihrer Schlüsseldaten. Möchten Sie jetzt sicheren?", + "loseKeysWarning": "Wenn Sie Ihre Schlüssel verlieren, müssen Sie Ihr Gerät zurücksetzen.", + "secureBackup": "Es ist wichtig, dass Sie Ihre öffentlichen und privaten Schlüssel sichern und diese sicher speichern!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Privater Schlüssel:", + "publicKey": "Öffentlicher Schlüssel:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Schlüssel sichern" + }, + "pkiRegenerate": { + "description": "Sind Sie sicher, dass Sie Schlüsselpaar neu erstellen möchten?", + "title": "Schlüsselpaar neu erstellen" + }, + "qr": { + "addChannels": "Kanäle hinzufügen", + "replaceChannels": "Kanäle ersetzen", + "description": "Die aktuelle LoRa Einstellung wird ebenfalls geteilt.", + "sharableUrl": "Teilbare URL", + "title": "QR Code Erzeugen" + }, + "rebootOta": { + "title": "Neustart planen", + "description": "Startet den verbundenen Knoten nach einer Verzögerung in den OTA (Over-the-Air) Modus.", + "enterDelay": "Verzögerung eingeben (Sek.)", + "scheduled": "Neustart wurde geplant" + }, + "reboot": { + "title": "Neustart planen", + "description": "Startet den verbundenen Knoten nach x Minuten neu." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "Dies entfernt den Knoten vom Gerät und fordert neue Schlüssel an.", + "keyMismatchReasonSuffix": ". Dies liegt daran, dass der aktuelle öffentliche Schlüssel des entfernten Knotens nicht mit dem zuvor gespeicherten Schlüssel für diesen Knoten übereinstimmt.", + "unableToSendDmPrefix": "Ihr Knoten kann keine Direktnachricht an folgenden Knoten senden: " + }, + "acceptNewKeys": "Neue Schlüssel akzeptieren", + "title": "Schlüsselfehler - {{identifier}}" + }, + "removeNode": { + "description": "Sind Sie sicher, dass Sie diesen Knoten entfernen möchten?", + "title": "Knoten entfernen?" + }, + "shutdown": { + "title": "Herunterfahren planen", + "description": "Schaltet den verbundenen Knoten nach x Minuten aus." + }, + "traceRoute": { + "routeToDestination": "Route zum Ziel:", + "routeBack": "Route zurück:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Ja, ich weiß, was ich tue!", + "conjunction": " und der Blog-Beitrag über ", + "postamble": " und verstehen die Auswirkungen einer Veränderung der Rolle.", + "preamble": "Ich habe die", + "choosingRightDeviceRole": "Wahl der richtigen Geräterolle", + "deviceRoleDocumentation": "Dokumentation der Geräterolle", + "title": "Bist Du sicher?" + } +} diff --git a/src/i18n/locales/de-DE/messages.json b/src/i18n/locales/de-DE/messages.json new file mode 100644 index 00000000..401e425b --- /dev/null +++ b/src/i18n/locales/de-DE/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Nachrichten: {{chatName}}" + }, + "emptyState": { + "title": "Einen Chat auswählen", + "text": "Noch keine Nachrichten." + }, + "selectChatPrompt": { + "text": "Wählen Sie einen Kanal oder Knoten, um Nachrichten zu schreiben." + }, + "sendMessage": { + "placeholder": "Geben Sie Ihre Nachricht hier ein...", + "sendButton": "Senden" + }, + "actionsMenu": { + "addReactionLabel": "Reaktion hinzufügen", + "replyLabel": "Antworten" + }, + "item": { + "status": { + "delivered": { + "label": "Nachricht zugestellt", + "displayText": "Nachricht zugestellt" + }, + "failed": { + "label": "Nachrichtenübermittlung fehlgeschlagen", + "displayText": "Zustellung fehlgeschlagen" + }, + "unknown": { + "label": "Nachrichtenstatus unbekannt", + "displayText": "Unbekannter Status" + }, + "waiting": { + "ariaLabel": "Nachricht wird gesendet", + "displayText": "Warte auf Zustellung" + } + } + } +} diff --git a/src/i18n/locales/de-DE/moduleConfig.json b/src/i18n/locales/de-DE/moduleConfig.json new file mode 100644 index 00000000..6a6e759a --- /dev/null +++ b/src/i18n/locales/de-DE/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Umgebungslicht", + "tabAudio": "Audio", + "tabCannedMessage": "Vordefinierte Nachrichten", + "tabDetectionSensor": "Erkennungssensor", + "tabExternalNotification": "Externe Benachrichtigung", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Nachbarinformation", + "tabPaxcounter": "Pax Zähler", + "tabRangeTest": "Reichweitentest", + "tabSerial": "Seriell", + "tabStoreAndForward": "Speichern&Weiterleiten", + "tabTelemetry": "Telemetrie" + }, + "ambientLighting": { + "title": "Einstellung Umgebungsbeleuchtung", + "description": "Einstellungen für das Modul Umgebungsbeleuchtung", + "ledState": { + "label": "LED Status", + "description": "Setzt die LED auf ein oder aus" + }, + "current": { + "label": "Stromstärke", + "description": "Legt den Strom für den LED Ausgang fest. Standard ist 10" + }, + "red": { + "label": "Rot", + "description": "Legt den roten LED Wert fest. Bereich 0-255" + }, + "green": { + "label": "Grün", + "description": "Legt den grünen LED Wert fest. Bereich 0-255" + }, + "blue": { + "label": "Blau", + "description": "Legt den blauen LED Wert fest. Bereich 0-255" + } + }, + "audio": { + "title": "Audioeinstellungen", + "description": "Einstellungen für das Audiomodul", + "codec2Enabled": { + "label": "Codec 2 aktiviert", + "description": "Codec 2 Audiokodierung aktivieren" + }, + "pttPin": { + "label": "GPIO PTT", + "description": "Für PTT verwendeter GPIO Pin" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate zur Audiokodierung" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO Pin für i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO Pin für i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO Pin für i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO Pin für i2S SCK" + } + }, + "cannedMessage": { + "title": "Einstellungen für vordefinierte Nachrichten", + "description": "Einstellungen für das Modul vordefinierte Nachrichten", + "moduleEnabled": { + "label": "Modul aktiviert", + "description": "Vordefinierte Nachrichten aktivieren" + }, + "rotary1Enabled": { + "label": "Drehgeber #1 aktiviert", + "description": "Drehgeber aktivieren" + }, + "inputbrokerPinA": { + "label": "Drehgeber Pin A", + "description": "GPIO Pin Wert (1-39) für Drehgeber Pin A" + }, + "inputbrokerPinB": { + "label": "Drehgeber Pin B", + "description": "GPIO Pin Wert (1-39) für Drehgeber Pin B" + }, + "inputbrokerPinPress": { + "label": "Drehgeber Pin Taste", + "description": "GPIO Pin Wert (1-39) für Drehgeber Pin Taste" + }, + "inputbrokerEventCw": { + "label": "Ereignis im Uhrzeigersinn", + "description": "Eingabeereignis auswählen." + }, + "inputbrokerEventCcw": { + "label": "Ereignis gegen Uhrzeigersinn", + "description": "Eingabeereignis auswählen." + }, + "inputbrokerEventPress": { + "label": "Ereignis Tastendruck", + "description": "Eingabeereignis auswählen." + }, + "updown1Enabled": { + "label": "Geber Hoch/Runter aktiviert", + "description": "Aktiviere Geber Hoch/Runter" + }, + "allowInputSource": { + "label": "Eingabequelle zulassen", + "description": "Wählen Sie aus: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Sende Glocke", + "description": "Sendet ein Klingelzeichen (Glocke) mit jeder Nachricht" + } + }, + "detectionSensor": { + "title": "Sensoreinstellungen für Erkennung", + "description": "Einstellungen für das Erkennungssensormodul", + "enabled": { + "label": "Aktiviert", + "description": "Erkennungssensormodul aktivieren oder deaktivieren" + }, + "minimumBroadcastSecs": { + "label": "Minimale Übertragungszeit alle Sekunden", + "description": "Das Intervall in Sekunden, wie oft eine Nachricht an das Netz gesendet wird, wenn eine Statusänderung erkannt wurde" + }, + "stateBroadcastSecs": { + "label": "Statusübertragung alle Sekunden", + "description": "Das Intervall in Sekunden, wie oft eine Nachricht mit dem aktuellen Status an das Netz gesendet wird, unabhängig von Änderungen" + }, + "sendBell": { + "label": "Sende Glocke", + "description": "ASCII-Glocke mit Warnmeldung senden" + }, + "name": { + "label": "Anzeigename", + "description": "Formatierte Nachricht die an das Netz gesendet wird, maximal 20 Zeichen" + }, + "monitorPin": { + "label": "GPIO Pin überwachen", + "description": "Der GPIO Pin zur Überwachung von Statusänderungen" + }, + "detectionTriggerType": { + "label": "Auslösetyp der Erkennung", + "description": "Die Art des zu verwendenden Auslöseereignisses" + }, + "usePullup": { + "label": "Pullup verwenden", + "description": "Gibt an, ob der INPUT_PULLUP Modus für GPIO Pin verwendet wird oder nicht" + } + }, + "externalNotification": { + "title": "Einstellungen für externe Benachrichtigungen", + "description": "Einstellung für das Modul externe Benachrichtigung", + "enabled": { + "label": "Modul aktiviert", + "description": "Externe Benachrichtigung aktivieren" + }, + "outputMs": { + "label": "Ausgabe MS", + "description": "Ausgabe MS" + }, + "output": { + "label": "Ausgabe", + "description": "Ausgabe" + }, + "outputVibra": { + "label": "Ausgabe Vibration", + "description": "Ausgabe Vibration" + }, + "outputBuzzer": { + "label": "Ausgabe Summer", + "description": "Ausgabe Summer" + }, + "active": { + "label": "Aktiv", + "description": "Aktiv" + }, + "alertMessage": { + "label": "Warnmeldung", + "description": "Warnmeldung" + }, + "alertMessageVibra": { + "label": "Vibration bei Warnmeldung", + "description": "Vibration bei Warnmeldung" + }, + "alertMessageBuzzer": { + "label": "Summer bei Warnmeldung", + "description": "Summer bei Warnmeldung" + }, + "alertBell": { + "label": "Warnglocke", + "description": "Soll beim Empfang eines eingehenden Klingelzeichens (Glocke) eine Warnung ausgelöst werden?" + }, + "alertBellVibra": { + "label": "Vibration bei Klingelzeichen", + "description": "Vibration bei Klingelzeichen" + }, + "alertBellBuzzer": { + "label": "Summer bei Klingelzeichen", + "description": "Summer bei Klingelzeichen" + }, + "usePwm": { + "label": "PWM verwenden", + "description": "PWM verwenden" + }, + "nagTimeout": { + "label": "Nervige Verzögerung", + "description": "Nervige Verzögerung" + }, + "useI2sAsBuzzer": { + "label": "I2S GPIO Pin als Summer verwenden", + "description": "I2S GPIO Pin als Summerausgang definieren" + } + }, + "mqtt": { + "title": "MQTT Einstellungen", + "description": "Einstellungen für das MQTT Modul", + "enabled": { + "label": "Aktiviert", + "description": "MQTT aktivieren oder deaktivieren" + }, + "address": { + "label": "MQTT Server Adresse", + "description": "MQTT Serveradresse für Standard/benutzerdefinierte Server" + }, + "username": { + "label": "MQTT Benutzername", + "description": "MQTT Benutzername für Standard/benutzerdefinierte Server" + }, + "password": { + "label": "MQTT Passwort", + "description": "MQTT Passwort für Standard/benutzerdefinierte Server" + }, + "encryptionEnabled": { + "label": "Verschlüsselung aktiviert", + "description": "MQTT-Verschlüsselung aktivieren oder deaktivieren. Hinweis: Alle Nachrichten werden unverschlüsselt an den MQTT-Broker gesendet, wenn diese Option nicht aktiviert ist. Unabhängig von der eingestellten Kanalverschlüsselung. Einschließlich der Standortdaten." + }, + "jsonEnabled": { + "label": "JSON aktiviert", + "description": "Gibt an, ob JSON Nachrichten über MQTT gesendet oder empfangen werden sollen" + }, + "tlsEnabled": { + "label": "TLS aktiviert", + "description": "TLS aktivieren oder deaktivieren" + }, + "root": { + "label": "Hauptthema", + "description": "MQTT Hauptthema für Standard/Benutzerdefinierte Server" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy aktiviert", + "description": "Verwendet die Netzwerkverbindung zum Austausch von MQTT Nachrichten mit dem Client." + }, + "mapReportingEnabled": { + "label": "Kartenberichte aktiviert", + "description": "Ihr Knoten sendet in regelmäßigen Abständen eine unverschlüsselte Nachricht mit Kartenbericht an den konfigurierten MQTT-Server. Einschließlich ID, langen und kurzen Namen, ungefährer Standort, Hardwaremodell, Geräterolle, Firmware-Version, LoRa Region, Modem-Voreinstellung und Name des Primärkanal." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Veröffentlichungsintervall Kartenbericht (s)", + "description": "Intervall in Sekunden, um Kartenberichte zu veröffentlichen" + }, + "positionPrecision": { + "label": "Ungefährer Standort", + "description": "Der geteilte Standort mit einer Genauigkeit innerhalb dieser Entfernung", + "options": { + "metric_km23": "Innerhalb von 23 km", + "metric_km12": "Innerhalb von 12 km", + "metric_km5_8": "Innerhalb von 5,8 km", + "metric_km2_9": "Innerhalb von 2,9 km", + "metric_km1_5": "Innerhalb von 1,5 km", + "metric_m700": "Innerhalb von 700 m", + "metric_m350": "Innerhalb von 350 m", + "metric_m200": "Innerhalb von 200 m", + "metric_m90": "Innerhalb von 90 m", + "metric_m50": "Innerhalb von 50 m", + "imperial_mi15": "Innerhalb von 15 Meilen", + "imperial_mi7_3": "Innerhalb von 7,3 Meilen", + "imperial_mi3_6": "Innerhalb von 3,6 Meilen", + "imperial_mi1_8": "Innerhalb von 1,8 Meilen", + "imperial_mi0_9": "Innerhalb von 0,9 Meilen", + "imperial_mi0_5": "Innerhalb von 0,5 Meilen", + "imperial_mi0_2": "Innerhalb von 0,2 Meilen", + "imperial_ft600": "Innerhalb von 600 Fuß", + "imperial_ft300": "Innerhalb von 300 Fuß", + "imperial_ft150": "Innerhalb von 150 Fuß" + } + } + } + }, + "neighborInfo": { + "title": "Einstellung Nachbarinformation", + "description": "Einstellungen für das Modul Nachbarinformation", + "enabled": { + "label": "Aktiviert", + "description": "Nachbarinformation Modul aktivieren oder deaktivieren" + }, + "updateInterval": { + "label": "Aktualisierungsintervall", + "description": "Intervall in Sekunden, wie oft die Nachbarinformation an das Netz gesendet wird" + } + }, + "paxcounter": { + "title": "Einstellung für Pax Zähler", + "description": "Einstellungen für das Modul Pax Zähler", + "enabled": { + "label": "Modul aktiviert", + "description": "Aktiviere Pax Zähler" + }, + "paxcounterUpdateInterval": { + "label": "Aktualisierungsintervall (Sekunden)", + "description": "Wie lange soll zwischen dem Senden von Pax Zählernachrichten gewartet werden" + }, + "wifiThreshold": { + "label": "WLAN RSSI Grenzwert", + "description": "Bei welchem WLAN RSSI Grenzwert sollte der Zähler erhöht werden. Standardwert -80" + }, + "bleThreshold": { + "label": "BLE RSSI Grenzwert", + "description": "Bei welchem BLE RSSI Grenzwert sollte der Zähler erhöht werden. Standardwert -80" + } + }, + "rangeTest": { + "title": "Einstellung Reichweitentest", + "description": "Einstellungen für das Modul Reichweitentest", + "enabled": { + "label": "Modul aktiviert", + "description": "Reichweitentest aktivieren" + }, + "sender": { + "label": "Nachrichtenintervall", + "description": "Wie lange soll zwischen dem Senden von Testnachrichten gewartet werden" + }, + "save": { + "label": "CSV im internen Speicher abspeichern", + "description": "Nur für ESP32" + } + }, + "serial": { + "title": "Serielle Einstellungen", + "description": "Einstellungen für das serielle Modul", + "enabled": { + "label": "Modul aktiviert", + "description": "Serielle Ausgabe aktivieren" + }, + "echo": { + "label": "Echo", + "description": "Wenn aktiviert, werden alle Nachrichten, die Sie senden, an Ihr Gerät zurückgesendet" + }, + "rxd": { + "label": "GPIO Empfangen", + "description": "Setzen Sie den GPIO Pin, den Sie eingerichtet haben, als RXD Pin." + }, + "txd": { + "label": "GPIO Senden", + "description": "Setzen Sie den GPIO Pin, den Sie eingerichtet haben, als TXD Pin." + }, + "baud": { + "label": "Baudrate", + "description": "Serielle Baudrate" + }, + "timeout": { + "label": "Zeitlimit erreicht", + "description": "Wartezeit in Sekunden bis eine Nachricht als gesendet angenommen wird" + }, + "mode": { + "label": "Betriebsmodus", + "description": "Modus auswählen" + }, + "overrideConsoleSerialPort": { + "label": "Seriellen Port der Konsole überschreiben", + "description": "Wenn Sie einen seriellen Port an die Konsole angeschlossen haben, wird diese überschrieben." + } + }, + "storeForward": { + "title": "Speichern & Weiterleiten Einstellungen", + "description": "Einstellungen für das Modul Speichern & Weiterleiten", + "enabled": { + "label": "Modul aktiviert", + "description": "Speichern & Weiterleiten aktivieren" + }, + "heartbeat": { + "label": "Herzschlag aktiviert", + "description": "Herzschlag für Speichern & Weiterleiten aktivieren" + }, + "records": { + "label": "Anzahl Einträge", + "description": "Anzahl der zu speichernden Datensätze" + }, + "historyReturnMax": { + "label": "Verlauf Rückgabewert maximal", + "description": "Maximale Anzahl an zurückzugebenden Datensätzen" + }, + "historyReturnWindow": { + "label": "Zeitraum Rückgabewert", + "description": "Maximale Anzahl an zurückzugebenden Datensätzen" + } + }, + "telemetry": { + "title": "Telemetrieeinstellungen", + "description": "Einstellungen für das Telemetriemodul", + "deviceUpdateInterval": { + "label": "Gerätekennzahlen", + "description": "Aktualisierungsintervall für Gerätekennzahlen (Sekunden)" + }, + "environmentUpdateInterval": { + "label": "Aktualisierungsintervall für Umweltdaten (Sekunden)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Modul aktiviert", + "description": "Aktiviert die Telemetrie für Umweltdaten" + }, + "environmentScreenEnabled": { + "label": "OLED Anzeige aktivieren", + "description": "Zeige das Telemetriemodul auf der OLED Anzeige" + }, + "environmentDisplayFahrenheit": { + "label": "Temperatur in Fahrenheit", + "description": "Temperatur in Fahrenheit anzeigen" + }, + "airQualityEnabled": { + "label": "Luftqualität aktiviert", + "description": "Telemetrie für Luftqualität aktivieren" + }, + "airQualityInterval": { + "label": "Aktualisierungsintervall Luftqualität", + "description": "Wie oft werden Luftqualitätsdaten über das Netz gesendet" + }, + "powerMeasurementEnabled": { + "label": "Energiemessung aktiviert", + "description": "Aktiviere die Telemetrie für die Energiemessung" + }, + "powerUpdateInterval": { + "label": "Aktualisierungsintervall Energie", + "description": "Wie oft werden Energiedaten an das Netz gesendet" + }, + "powerScreenEnabled": { + "label": "Energieanzeige aktiviert", + "description": "Aktiviere die Anzeige für Energietelemetrie" + } + } +} diff --git a/src/i18n/locales/de-DE/nodes.json b/src/i18n/locales/de-DE/nodes.json new file mode 100644 index 00000000..af9df668 --- /dev/null +++ b/src/i18n/locales/de-DE/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Öffentlicher Schlüssel aktiviert" + }, + "noPublicKey": { + "label": "Kein öffentlicher Schlüssel" + }, + "directMessage": { + "label": "Direktnachricht {{shortName}}" + }, + "favorite": { + "label": "Favorit" + }, + "notFavorite": { + "label": "Kein Favorit" + }, + "status": { + "heard": "Gehört", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Höhe" + }, + "channelUtil": { + "label": "Kanal-Auslastung" + }, + "airtimeUtil": { + "label": "Sendezeit-Auslastung" + } + }, + "nodesTable": { + "headings": { + "longName": "Langer Name", + "connection": "Verbindung", + "lastHeard": "Zuletzt gehört", + "encryption": "Verschlüsselung", + "model": "Modell", + "macAddress": "MAC Adresse" + }, + "connectionStatus": { + "direct": "Direkt", + "away": "abwesend", + "unknown": "-", + "viaMqtt": ", über MQTT" + }, + "lastHeardStatus": { + "never": "Nie" + } + } +} diff --git a/src/i18n/locales/de-DE/ui.json b/src/i18n/locales/de-DE/ui.json new file mode 100644 index 00000000..23e4f9d0 --- /dev/null +++ b/src/i18n/locales/de-DE/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Nachrichten", + "map": "Karte", + "config": "Einstellungen", + "radioConfig": "Funkgerätekonfiguration", + "moduleConfig": "Moduleinstellungen", + "channels": "Kanäle", + "nodes": "Knoten" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Seitenleiste öffnen", + "close": "Seitenleiste schließen" + } + }, + "deviceInfo": { + "volts": "{{voltage}} Volt", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Erstelldatum: {{date}}" + }, + "deviceName": { + "title": "Gerätename", + "changeName": "Gerätename ändern", + "placeholder": "Gerätename eingeben" + }, + "editDeviceName": "Gerätename bearbeiten" + } + }, + "batteryStatus": { + "charging": "{{level}}% Ladung", + "pluggedIn": "Wird geladen", + "title": "Batterie" + }, + "search": { + "nodes": "Knoten suchen...", + "channels": "Kanäle suchen...", + "commandPalette": "Befehle suchen..." + }, + "toast": { + "positionRequestSent": { + "title": "Standortanfrage gesendet." + }, + "requestingPosition": { + "title": "Standort wird angefordert, bitte warten..." + }, + "sendingTraceroute": { + "title": "Sende Traceroute, bitte warten..." + }, + "tracerouteSent": { + "title": "Traceroute gesendet." + }, + "savedChannel": { + "title": "Gespeicherter Kanal: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Der Chat verwendet PKI-Verschlüsselung." + }, + "pskEncryption": { + "title": "Chat verwendet PSK-Verschlüsselung." + } + }, + "configSaveError": { + "title": "Fehler beim Speichern von Einstellung", + "description": "Beim Speichern der Einstellungen ist ein Fehler aufgetreten." + }, + "validationError": { + "title": "Einstellungsfehler vorhanden", + "description": "Bitte korrigieren Sie die Einstellungsfehler vor dem Speichern." + }, + "saveSuccess": { + "title": "Einstellungen speichern", + "description": "Die Einstellungsänderung {{case}} wurde gespeichert." + } + }, + "notifications": { + "copied": { + "label": "Kopiert!" + }, + "copyToClipboard": { + "label": "In die Zwischenablage kopieren" + }, + "hidePassword": { + "label": "Passwort verbergen" + }, + "showPassword": { + "label": "Passwort anzeigen" + }, + "deliveryStatus": { + "delivered": "Zugestellt", + "failed": "Zustellung fehlgeschlagen", + "waiting": "Warte...", + "unknown": "Unbekannt" + } + }, + "general": { + "label": "Allgemein" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Messgrößen" + }, + "role": { + "label": "Rolle" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Eingabe löschen" + }, + "resetFilters": { + "label": "Filter zurücksetzen" + }, + "nodeName": { + "label": "Knotenname/-nummer", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Sendezeit-Auslastung (%)" + }, + "batteryLevel": { + "label": "Akkustand (%)", + "labelText": "Akkustand (%): {{value}}" + }, + "batteryVoltage": { + "label": "Batteriespannung (V)", + "title": "Spannung" + }, + "channelUtilization": { + "label": "Kanalauslastung (%)" + }, + "hops": { + "direct": "Direkt", + "label": "Anzahl Hops", + "text": "Sprungweite: {{value}}" + }, + "lastHeard": { + "label": "Zuletzt gehört", + "labelText": "Zuletzt gehört: {{value}}", + "nowLabel": "Jetzt" + }, + "snr": { + "label": "SNR (dB)" + }, + "favorites": { + "label": "Favoriten" + }, + "hide": { + "label": "Ausblenden" + }, + "showOnly": { + "label": "Zeige nur" + }, + "viaMqtt": { + "label": "Über MQTT verbunden" + }, + "language": { + "label": "Sprache", + "changeLanguage": "Sprache ändern" + }, + "theme": { + "dark": "Dunkel", + "light": "Hell", + "system": "Automatisch", + "changeTheme": "Farbschema ändern" + }, + "errorPage": { + "title": "Das ist ein wenig peinlich...", + "description1": "Es tut uns wirklich leid, aber im Webclient ist ein Fehler aufgetreten, der es zum Absturz gebracht hat.
Das soll nicht passieren, und wir arbeiten hart daran, es zu beheben.", + "description2": "Der beste Weg, um zu verhindern, dass sich dies Ihnen oder irgendjemand anderem wiederholt, besteht darin, uns über dieses Problem zu berichten.", + "reportInstructions": "Bitte fügen Sie folgende Informationen in Ihren Bericht ein:", + "reportSteps": { + "step1": "Was haben Sie getan, als der Fehler aufgetreten ist", + "step2": "Was haben Sie erwartet", + "step3": "Was tatsächlich passiert ist", + "step4": "Sonstige relevante Informationen" + }, + "reportLink": "Sie können das Problem auf unserem <0>GitHub melden", + "dashboardLink": "Zurück zum <0>Dashboard", + "detailsSummary": "Fehlerdetails", + "errorMessageLabel": "Fehlermeldungen:", + "stackTraceLabel": "Stapelabzug:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic®️ ist eine eingetragene Marke der Meshtastic LLC. | <1>Rechtliche Informationen", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/es-ES/channels.json b/src/i18n/locales/es-ES/channels.json new file mode 100644 index 00000000..12e43673 --- /dev/null +++ b/src/i18n/locales/es-ES/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Canales", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Ajustes del canal", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Nombre", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/es-ES/commandPalette.json b/src/i18n/locales/es-ES/commandPalette.json new file mode 100644 index 00000000..12235d7a --- /dev/null +++ b/src/i18n/locales/es-ES/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Mensajes", + "map": "Mapa", + "config": "Config", + "channels": "Canales", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/es-ES/common.json b/src/i18n/locales/es-ES/common.json new file mode 100644 index 00000000..e5da6d9f --- /dev/null +++ b/src/i18n/locales/es-ES/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Aplique", + "backupKey": "Backup Key", + "cancel": "Cancelar", + "clearMessages": "Clear Messages", + "close": "Cerrar", + "confirm": "Confirm", + "delete": "Eliminar", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Mensaje", + "now": "Now", + "ok": "Vale", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Quitar", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reiniciar", + "save": "Guardar", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/es-ES/dashboard.json b/src/i18n/locales/es-ES/dashboard.json new file mode 100644 index 00000000..9c70e841 --- /dev/null +++ b/src/i18n/locales/es-ES/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Red", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/es-ES/deviceConfig.json b/src/i18n/locales/es-ES/deviceConfig.json new file mode 100644 index 00000000..dfa21d26 --- /dev/null +++ b/src/i18n/locales/es-ES/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Dispositivo", + "tabDisplay": "Pantalla", + "tabLora": "LoRa", + "tabNetwork": "Red", + "tabPosition": "Posición", + "tabPower": "Energía", + "tabSecurity": "Seguridad" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Modo de emparejamiento" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Región" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configuración UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Sin configurar", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Clave privada" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Clave Pública" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/es-ES/dialog.json b/src/i18n/locales/es-ES/dialog.json new file mode 100644 index 00000000..97f12d8f --- /dev/null +++ b/src/i18n/locales/es-ES/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Mensaje", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Tensión", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "¿Estás seguro?" + } +} diff --git a/src/i18n/locales/es-ES/messages.json b/src/i18n/locales/es-ES/messages.json new file mode 100644 index 00000000..09c10917 --- /dev/null +++ b/src/i18n/locales/es-ES/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Enviar" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/es-ES/moduleConfig.json b/src/i18n/locales/es-ES/moduleConfig.json new file mode 100644 index 00000000..2c192219 --- /dev/null +++ b/src/i18n/locales/es-ES/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Intensidad", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Tiempo agotado", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/es-ES/nodes.json b/src/i18n/locales/es-ES/nodes.json new file mode 100644 index 00000000..366eee1d --- /dev/null +++ b/src/i18n/locales/es-ES/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorito" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Directo", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/es-ES/ui.json b/src/i18n/locales/es-ES/ui.json new file mode 100644 index 00000000..efa3a1f6 --- /dev/null +++ b/src/i18n/locales/es-ES/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Mensajes", + "map": "Mapa", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Canales", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Batería" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Mostrar contraseña" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Filtro" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Tensión" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Directo", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Última escucha", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Idioma", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Oscuro", + "light": "Claro", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/fi-FI/channels.json b/src/i18n/locales/fi-FI/channels.json new file mode 100644 index 00000000..f6d20a3e --- /dev/null +++ b/src/i18n/locales/fi-FI/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanavat", + "channelName": "Kanava: {{channelName}}", + "broadcastLabel": "Ensisijainen", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Syötä kelvollinen {{bits}} bittinen PSK." + }, + "settings": { + "label": "Kanava-asetukset", + "description": "Crypto, MQTT ja muut asetukset" + }, + "role": { + "label": "Rooli", + "description": "Laitteen telemetriatiedot lähetetään ENSISIJAISEN kanavan kautta. Vain yksi ENSISIJAINEN kanava sallitaan", + "options": { + "primary": "ENSISIJAISEN", + "disabled": "POIS KÄYTÖSTÄ", + "secondary": "TOISIJAINEN" + } + }, + "psk": { + "label": "Esijaettu avain", + "description": "Tuetut PSK-pituudet: 256-bit, 128-bit, 8-bit, tyhjät (0-bit)", + "generate": "Luo" + }, + "name": { + "label": "Nimi", + "description": "Kanavan yksilöllinen nimi (alle 12 merkkiä), jätä tyhjäksi käyttääksesi oletusta" + }, + "uplinkEnabled": { + "label": "Lähetys käytössä", + "description": "Lähetä viestejä paikallisesta verkosta MQTT-verkkoon" + }, + "downlinkEnabled": { + "label": "Vastaanotto käytössä", + "description": "Lähetä viestejä MQTT:stä paikalliseen verkkoon" + }, + "positionPrecision": { + "label": "Sijainti", + "description": "Kanavalle jaettavan sijainnin tarkkuus. Voi poistaa käytöstä.", + "options": { + "none": "Älä jaa sijaintia", + "precise": "Tarkka Sijainti", + "metric_km23": "23 kilometrin säteellä", + "metric_km12": "12 kilometrin säteellä", + "metric_km5_8": "5,8 kilometrin säteellä", + "metric_km2_9": "2,9 kilometrin säteellä", + "metric_km1_5": "1,5 kilometrin säteellä", + "metric_m700": "700 metrin säteellä", + "metric_m350": "350 metrin säteellä", + "metric_m200": "200 metrin säteellä", + "metric_m90": "90 metrin säteellä", + "metric_m50": "50 metrin säteellä", + "imperial_mi15": "15 mailin säteellä", + "imperial_mi7_3": "7,3 mailin säteellä", + "imperial_mi3_6": "3,6 mailin säteellä", + "imperial_mi1_8": "1,8 mailin säteellä", + "imperial_mi0_9": "0,9 mailin säteellä", + "imperial_mi0_5": "0,5 mailin säteellä", + "imperial_mi0_2": "0,2 mailin säteellä", + "imperial_ft600": "600 jalan säteellä", + "imperial_ft300": "300 jalan säteellä", + "imperial_ft150": "150 jalan säteellä" + } + } +} diff --git a/src/i18n/locales/fi-FI/commandPalette.json b/src/i18n/locales/fi-FI/commandPalette.json new file mode 100644 index 00000000..221821eb --- /dev/null +++ b/src/i18n/locales/fi-FI/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "Tuloksia ei löytynyt.", + "page": { + "title": "Komentovalikko" + }, + "pinGroup": { + "label": "Kiinnitä komentoryhmä" + }, + "unpinGroup": { + "label": "Irroita komentoryhmä" + }, + "goto": { + "label": "Siirry", + "command": { + "messages": "Viestit", + "map": "Kartta", + "config": "Asetukset", + "channels": "Kanavat", + "nodes": "Laitteet" + } + }, + "manage": { + "label": "Hallinnoi", + "command": { + "switchNode": "Vaihda laitetta", + "connectNewNode": "Yhdistä uusi laite" + } + }, + "contextual": { + "label": "Kontekstin mukainen", + "command": { + "qrCode": "QR-koodi", + "qrGenerator": "QR-koodigeneraattori", + "qrImport": "Tuo", + "scheduleShutdown": "Ajasta sammutus", + "scheduleReboot": "Ajasta uudelleenkäynnistys", + "rebootToOtaMode": "Uudelleenkäynnistä OTA-tilaan", + "resetNodeDb": "Nollaa laitteen DB-tietokanta", + "factoryResetDevice": "Palauta tehdasasetukset", + "factoryResetConfig": "Tehdasasetusten palautusasetukset" + } + }, + "debug": { + "label": "Vianetsintä", + "command": { + "reconfigure": "Määritä uudelleen", + "clearAllStoredMessages": "Tyhjennä kaikki tallennetut viesti" + } + } +} diff --git a/src/i18n/locales/fi-FI/common.json b/src/i18n/locales/fi-FI/common.json new file mode 100644 index 00000000..beb5a9d4 --- /dev/null +++ b/src/i18n/locales/fi-FI/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Hyväksy", + "backupKey": "Varmuuskopioi avain", + "cancel": "Peruuta", + "clearMessages": "Tyhjennä viestit", + "close": "Sulje", + "confirm": "Vahvista", + "delete": "Poista", + "dismiss": "Hylkää", + "download": "Lataa", + "export": "Vie", + "generate": "Luo", + "regenerate": "Luo uudelleen", + "import": "Tuo", + "message": "Viesti", + "now": "Nyt", + "ok": "OK", + "print": "Tulosta", + "rebootOtaNow": "Käynnistä uudelleen OTA-tilaan nyt", + "remove": "Poista", + "requestNewKeys": "Pyydä uudet avaimet", + "requestPosition": "Pyydä sijaintia", + "reset": "Palauta", + "save": "Tallenna", + "scanQr": "Skannaa QR-koodi", + "traceRoute": "Reitinselvitys" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Ladataan...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hyppy", + "plural": "Hyppyä" + }, + "hopsAway": { + "one": "{{count}} hypyn päässä", + "plural": "{{count}} hypyn päässä", + "unknown": "Hyppyjen määrä tuntematon" + }, + "megahertz": "MHz", + "raw": "raakatieto", + "meter": { + "one": "Metri", + "plural": "Metriä", + "suffix": "m" + }, + "minute": { + "one": "Minuutti", + "plural": "Minuuttia" + }, + "millisecond": { + "one": "Millisekunti", + "plural": "Millisekuntia", + "suffix": "ms" + }, + "second": { + "one": "Sekunti", + "plural": "Sekuntia" + }, + "snr": "SNR", + "volt": { + "one": "Voltti", + "plural": "Voltit", + "suffix": "V" + }, + "record": { + "one": "Tiedot", + "plural": "Tiedot" + } + }, + "security": { + "256bit": "256 bittiä" + }, + "unknown": { + "longName": "Tuntematon", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "EI ASETETTU", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Teksti on liian pitkä – sallittu enimmäispituus on {{maximum}} merkkiä.", + "number": "Arvo on liian suuri – sallittu enimmäisarvo on {{maximum}}.", + "bytes": "Liian suuri koko – sallittu enimmäismäärä on {{params.maximum}} tavua." + }, + "tooSmall": { + "string": "Teksti on liian lyhyt – vähimmäispituus on {{minimum}} merkkiä.", + "number": "Arvo on liian pieni – pienin sallittu arvo on {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Virheellinen muoto – odotettu muoto on IPv4-osoite.", + "key": "Virheellinen muoto – odotettu muoto on Base64-koodattu jaettu avain (PSK)." + }, + "invalidType": { + "number": "Virheellinen tyyppi – arvon tulee olla numero." + }, + "pskLength": { + "0bit": "Avainkentän on oltava tyhjä.", + "8bit": "Avaimen on oltava 8-bittinen jaettu avain (PSK).", + "128bit": "Avaimen on oltava 128-bittinen jaettu avain (PSK).", + "256bit": "Avaimen on oltava 256-bittinen jaettu avain (PSK)." + }, + "required": { + "generic": "Tämä kenttä on pakollinen.", + "managed": "Vähintään yksi hallinta-avain vaaditaan, jos laitetta hallitaan.", + "key": "Avain on pakollinen." + } + } +} diff --git a/src/i18n/locales/fi-FI/dashboard.json b/src/i18n/locales/fi-FI/dashboard.json new file mode 100644 index 00000000..43ce8a7f --- /dev/null +++ b/src/i18n/locales/fi-FI/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Yhdistetyt laitteet", + "description": "Hallitse yhdistettyjä Meshtastic laitteitasi.", + "connectionType_ble": "BLE", + "connectionType_serial": "Sarjaliitäntä", + "connectionType_network": "Verkko", + "noDevicesTitle": "Ei laitteita yhdistettynä", + "noDevicesDescription": "Yhdistä uusi laite aloittaaksesi.", + "button_newConnection": "Uusi yhteys" + } +} diff --git a/src/i18n/locales/fi-FI/deviceConfig.json b/src/i18n/locales/fi-FI/deviceConfig.json new file mode 100644 index 00000000..8b0d01b8 --- /dev/null +++ b/src/i18n/locales/fi-FI/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Asetukset", + "tabBluetooth": "Bluetooth", + "tabDevice": "Laite", + "tabDisplay": "Näyttö", + "tabLora": "LoRa", + "tabNetwork": "Verkko", + "tabPosition": "Sijainti", + "tabPower": "Virta", + "tabSecurity": "Turvallisuus" + }, + "sidebar": { + "label": "Moduulit" + }, + "device": { + "title": "Laitteen asetukset", + "description": "Laitteen asetukset", + "buttonPin": { + "description": "Painikkeen pinnin ohitus", + "label": "Painikkeen pinni" + }, + "buzzerPin": { + "description": "Summerin pinnin ohitus", + "label": "Summerin pinni" + }, + "disableTripleClick": { + "description": "Poista kolmoisklikkaus käytöstä", + "label": "Poista kolmoisklikkaus käytöstä" + }, + "doubleTapAsButtonPress": { + "description": "Käsittele kaksoisnapautus painikkeen painalluksena", + "label": "Kaksoisnapautus painikkeen painalluksena" + }, + "ledHeartbeatDisabled": { + "description": "Poista ledin vilkkuminen käytöstä", + "label": "Ledin vilkkuminen poistettu käytöstä" + }, + "nodeInfoBroadcastInterval": { + "description": "Kuinka usein laitteen tiedot lähetetään verkkoon", + "label": "Laitteen tietojen lähetyksen aikaväli" + }, + "posixTimezone": { + "description": "POSIX-aikavyöhykkeen merkkijono laitetta varten", + "label": "POSIX-aikavyöhyke" + }, + "rebroadcastMode": { + "description": "Kuinka uudelleenlähetyksiä käsitellään", + "label": "Uudelleenlähetyksen tila" + }, + "role": { + "description": "Mikä rooli laitteella on mesh-verkossa", + "label": "Rooli" + } + }, + "bluetooth": { + "title": "Bluetooth asetukset", + "description": "Bluetooth moduulin asetukset", + "note": "Huomautus: Jotkin laitteet (ESP32) eivät voi käyttää bluetoothia sekä WiFiä samanaikaisesti.", + "enabled": { + "description": "Ota Bluetooth käyttöön tai poista käytöstä", + "label": "Käytössä" + }, + "pairingMode": { + "description": "PIN-koodin valinnan käyttäytyminen.", + "label": "Paritustila" + }, + "pin": { + "description": "Bluetooth PIN-koodi, jota käytetään pariliitettäessä", + "label": "PIN" + } + }, + "display": { + "description": "Laitteen näytön asetukset", + "title": "Näyttöasetukset", + "headingBold": { + "description": "Lihavoi otsikkoteksti", + "label": "Lihavoitu otsikko" + }, + "carouselDelay": { + "description": "Kuinka nopeasti ikkunat kulkevat", + "label": "Karusellin Viive" + }, + "compassNorthTop": { + "description": "Kiinnitä pohjoinen kompassin yläreunaan", + "label": "Kompassin pohjoinen ylhäällä" + }, + "displayMode": { + "description": "Näytön asettelun vaihtoehdot", + "label": "Näyttötila" + }, + "displayUnits": { + "description": "Näytä metriset tai imperiaaliset yksiköt", + "label": "Näyttöyksiköt" + }, + "flipScreen": { + "description": "Käännä näyttöä 180 astetta", + "label": "Käännä näyttö" + }, + "gpsDisplayUnits": { + "description": "Koordinaattien näyttömuoto", + "label": "GPS näyttöyksiköt" + }, + "oledType": { + "description": "Laitteeseen liitetyn OLED-näytön tyyppi", + "label": "OLED-tyyppi" + }, + "screenTimeout": { + "description": "Sammuta näyttö tämän ajan jälkeen", + "label": "Näytön aikakatkaisu" + }, + "twelveHourClock": { + "description": "Käytä 12 tunnin kelloa", + "label": "12 tunnin kello" + }, + "wakeOnTapOrMotion": { + "description": "Herätä laite napauttamalla tai liikkeestä", + "label": "Herätä napauttamalla tai liikkeellä" + } + }, + "lora": { + "title": "Mesh-verkon asetukset", + "description": "LoRa-verkon asetukset", + "bandwidth": { + "description": "Kanavan kaistanleveys MHz", + "label": "Kaistanleveys" + }, + "boostedRxGain": { + "description": "RX tehostettu vahvistus", + "label": "RX tehostettu vahvistus" + }, + "codingRate": { + "description": "Koodausnopeuden nimittäjä", + "label": "Koodausnopeus" + }, + "frequencyOffset": { + "description": "Taajuuskorjaus kalibrointivirheiden korjaamiseksi", + "label": "Taajuuspoikkeama" + }, + "frequencySlot": { + "description": "LoRa-taajuuden kanavanumero", + "label": "Taajuuspaikka" + }, + "hopLimit": { + "description": "Maksimimäärä hyppyjä", + "label": "Hyppyraja" + }, + "ignoreMqtt": { + "description": "Älä välitä MQTT-viestejä mesh-verkon yli", + "label": "Ohita MQTT" + }, + "modemPreset": { + "description": "Käytössä olevan modeemin esiasetus", + "label": "Modeemin esiasetus" + }, + "okToMqtt": { + "description": "Kun asetetaan arvoksi true, tämä asetus tarkoittaa, että käyttäjä hyväksyy paketin lähettämisen MQTT:lle. Jos asetetaan arvoksi false, etälaitteita pyydetään olemaan välittämättä paketteja MQTT:lle", + "label": "MQTT päällä" + }, + "overrideDutyCycle": { + "description": "Ohita käyttöaste (Duty Cycle)", + "label": "Ohita käyttöaste (Duty Cycle)" + }, + "overrideFrequency": { + "description": "Käytä mukautettua taajuutta", + "label": "Mukautettu taajuus" + }, + "region": { + "description": "Asettaa alueen laitteelle", + "label": "Alue" + }, + "spreadingFactor": { + "description": "Ilmaisee symbolia kohden lähetettävien taajuuksien määrän", + "label": "Levennyskerroin" + }, + "transmitEnabled": { + "description": "LoRa-radion lähetyksen (TX) käyttöönotto tai poiskytkentä", + "label": "Lähetys käytössä" + }, + "transmitPower": { + "description": "Suurin lähetysteho", + "label": "Lähetysteho" + }, + "usePreset": { + "description": "Käytä ennalta määriteltyä modeemin esiasetusta", + "label": "Käytä esiasetusta" + }, + "meshSettings": { + "description": "LoRa-verkon asetukset", + "label": "Mesh-verkon asetukset" + }, + "waveformSettings": { + "description": "LoRa-aaltomuodon asetukset", + "label": "Signaalimuodon asetukset" + }, + "radioSettings": { + "label": "Radioasetukset", + "description": "LoRa-laitteen asetukset" + } + }, + "network": { + "title": "WiFi-asetukset", + "description": "WiFi-radion asetukset", + "note": "Huomautus: Jotkin laitteet (ESP32) eivät voi käyttää sekä Bluetoothia että WiFiä samanaikaisesti.", + "addressMode": { + "description": "Osoitteen määrityksen valinta", + "label": "Osoitetila" + }, + "dns": { + "description": "DNS-palvelin", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Ota käyttöön tai poista käytöstä ethernet-portti", + "label": "Käytössä" + }, + "gateway": { + "description": "Oletusyhdyskäytävä", + "label": "Yhdyskäytävä" + }, + "ip": { + "description": "IP-osoite", + "label": "IP" + }, + "psk": { + "description": "Verkon salasana", + "label": "PSK" + }, + "ssid": { + "description": "Verkon nimi", + "label": "SSID" + }, + "subnet": { + "description": "Aliverkon peite", + "label": "Aliverkko" + }, + "wifiEnabled": { + "description": "Ota WiFi käyttöön tai poista se käytöstä", + "label": "Käytössä" + }, + "meshViaUdp": { + "label": "Mesh UDP:n kautta" + }, + "ntpServer": { + "label": "NTP-palvelin" + }, + "rsyslogServer": { + "label": "Rsyslog-palvelin" + }, + "ethernetConfigSettings": { + "description": "Ethernet-portin asetukset", + "label": "Ethernet-asetukset" + }, + "ipConfigSettings": { + "description": "IP-osoitteen asetukset", + "label": "IP-osoitteen asetukset" + }, + "ntpConfigSettings": { + "description": "NTP-asetukset", + "label": "NTP-asetukset" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog määritykset", + "label": "Rsyslog määritykset" + }, + "udpConfigSettings": { + "description": "UDP-yhdeyden asetukset", + "label": "UDP-asetukset" + } + }, + "position": { + "title": "Sijainnin asetukset", + "description": "Sijaintimoduulin asetukset", + "broadcastInterval": { + "description": "Kuinka usein sijainti lähetetään mesh-verkon yli", + "label": "Lähetyksen aikaväli" + }, + "enablePin": { + "description": "GPS-moduulin käyttöönottopinnin korvaus", + "label": "Ota pinni käytöön" + }, + "fixedPosition": { + "description": "Älä raportoi GPS-sijaintia, vaan käytä manuaalisesti määritettyä sijaintia", + "label": "Kiinteä sijainti" + }, + "gpsMode": { + "description": "Määritä, onko laitteen GPS käytössä, pois päältä vai puuttuuko se kokonaan", + "label": "GSP-tila" + }, + "gpsUpdateInterval": { + "description": "Kuinka usein GPS-paikannus suoritetaan", + "label": "GPS-päivitysväli" + }, + "positionFlags": { + "description": "Valinnaiset kentät, jotka voidaan sisällyttää sijaintiviesteihin. Mitä enemmän kenttiä valitaan, sitä suurempi viesti on, mikä johtaa pidempään lähetysaikaan ja suurempaan pakettihäviöriskiin.", + "label": "Sijaintimerkinnät" + }, + "receivePin": { + "description": "GPS-moduulin käyttöönottopinnin korvaus", + "label": "Vastaanoton pinni" + }, + "smartPositionEnabled": { + "description": "Lähetä sijainti vain, kun sijainnissa on tapahtunut merkittävä muutos", + "label": "Ota älykäs sijainti käyttöön" + }, + "smartPositionMinDistance": { + "description": "Vähimmäisetäisyys (metreinä), joka on kuljettava ennen sijaintipäivityksen lähettämistä", + "label": "Älykkään sijainnin minimietäisyys" + }, + "smartPositionMinInterval": { + "description": "Lyhin aikaväli (sekunteina), joka on kuluttava ennen sijaintipäivityksen lähettämistä", + "label": "Älykkään sijainnin vähimmäisetäisyys" + }, + "transmitPin": { + "description": "GPS-moduulin käyttöönottopinnin korvaus", + "label": "Lähetyksen pinni" + }, + "intervalsSettings": { + "description": "Kuinka usein sijaintipäivitykset lähetetään", + "label": "Aikaväli" + }, + "flags": { + "placeholder": "Valitse sijaintiasetukset...", + "altitude": "Korkeus", + "altitudeGeoidalSeparation": "Korkeuden geoidinen erotus", + "altitudeMsl": "Korkeus on mitattu merenpinnan tasosta", + "dop": "Tarkkuuden heikkenemä (DOP), oletuksena käytetään PDOP-arvoa", + "hdopVdop": "Jos DOP on asetettu, käytä HDOP- ja VDOP-arvoja PDOP:n sijaan", + "numSatellites": "Satelliittien määrä", + "sequenceNumber": "Sekvenssinumero", + "timestamp": "Aikaleima", + "unset": "Ei yhdistetty", + "vehicleHeading": "Ajoneuvon suunta", + "vehicleSpeed": "Ajoneuvon nopeus" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Käytetään akun jännitteen lukeman säätämiseen", + "label": "Korvaava AD-muuntimen kerroin" + }, + "ina219Address": { + "description": "Akkunäytön INA219 osoite", + "label": "INA219 Osoite" + }, + "lightSleepDuration": { + "description": "Kuinka kauan laite on kevyessä lepotilassa", + "label": "Kevyen lepotilan kesto" + }, + "minimumWakeTime": { + "description": "Vähimmäisaika, jonka laite pysyy hereillä paketin vastaanoton jälkeen", + "label": "Minimi heräämisaika" + }, + "noConnectionBluetoothDisabled": { + "description": "Jos laite ei saa Bluetooth-yhteyttä, BLE-radio poistetaan käytöstä tämän ajan kuluttua", + "label": "Ei yhteyttä. Bluetooth on pois käytöstä" + }, + "powerSavingEnabled": { + "description": "Valitse, jos laite saa virtaa matalavirtalähteestä (esim. aurinkopaneeli), jolloin virrankulutusta minimoidaan mahdollisimman paljon.", + "label": "Ota virransäästötila käyttöön" + }, + "shutdownOnBatteryDelay": { + "description": "Sammuta laite automaattisesti tämän ajan kuluttua akkukäytöllä, 0 tarkoittaa toistaiseksi päällä", + "label": "Viive laitteen sammuttamisessa akkukäytöllä" + }, + "superDeepSleepDuration": { + "description": "Kuinka pitkään laite on supersyvässä lepotilassa", + "label": "Supersyvän lepotilan kesto" + }, + "powerConfigSettings": { + "description": "Virtamoduulin asetukset", + "label": "Virran asetukset" + }, + "sleepSettings": { + "description": "Virtamoduulin lepotila-asetukset", + "label": "Lepotilan asetukset" + } + }, + "security": { + "description": "Turvallisuuskokoonpanon asetukset", + "title": "Turvallisuusasetukset", + "button_backupKey": "Varmuuskopioi avain", + "adminChannelEnabled": { + "description": "Salli saapuva laitteen ohjaus suojaamattoman vanhan admin-kanavan kautta", + "label": "Salli vanha admin ylläpitäjä" + }, + "enableDebugLogApi": { + "description": "Lähetä reaaliaikainen debug-loki sarjaportin kautta, katso ja vie laitteen lokitiedostot, joista sijaintitiedot on poistettu, Bluetoothin kautta", + "label": "Ota käyttöön virheenkorjauslokin API-rajapinta" + }, + "managed": { + "description": "Jos tämä on käytössä, laitteen asetuksia voi muuttaa vain etäadmin-laitteen hallintaviestien kautta. Älä ota tätä käyttöön, ellei vähintään yhtä sopivaa etäadmin-laitetta ole määritetty ja julkinen avain ei ole tallennettu johonkin yllä olevista kentistä.", + "label": "Hallinnoitu" + }, + "privateKey": { + "description": "Käytetään jaetun avaimen luomiseen etälaitteen kanssa", + "label": "Yksityinen avain" + }, + "publicKey": { + "description": "Lähetetään muille mesh-verkon laitteille, jotta ne voivat laskea jaetun salaisen avaimen", + "label": "Julkinen avain" + }, + "primaryAdminKey": { + "description": "Ensisijainen julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", + "label": "Ensisijainen järjestelmänvalvojan avain" + }, + "secondaryAdminKey": { + "description": "Toissijainen julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", + "label": "Toissijainen järjestelmänvalvojan avain" + }, + "serialOutputEnabled": { + "description": "Sarjakonsoli Stream API:n yli", + "label": "Sarjaulostulo Käytössä" + }, + "tertiaryAdminKey": { + "description": "Kolmas julkinen avain, jolla on oikeus lähettää hallintaviestejä tälle laitteelle", + "label": "Kolmas järjestelmänvalvojan hallinta-avain" + }, + "adminSettings": { + "description": "Järjestelmänvalvojan asetukset", + "label": "Ylläpitäjän asetukset" + }, + "loggingSettings": { + "description": "Kirjautumisen asetukset", + "label": "Kirjautumisen asetukset" + } + } +} diff --git a/src/i18n/locales/fi-FI/dialog.json b/src/i18n/locales/fi-FI/dialog.json new file mode 100644 index 00000000..04c35775 --- /dev/null +++ b/src/i18n/locales/fi-FI/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "Tämä toiminto poistaa kaiken viestihistorian. Toimintoa ei voi perua. Haluatko varmasti jatkaa?", + "title": "Tyhjennä kaikki viestit" + }, + "deviceName": { + "description": "Laite käynnistyy uudelleen, kun asetus on tallennettu.", + "longName": "Pitkä nimi", + "shortName": "Lyhytnimi", + "title": "Vaihda laitteen nimi" + }, + "import": { + "description": "Nykyinen LoRa-asetus ylikirjoitetaan.", + "error": { + "invalidUrl": "Virheellinen Meshtastic verkko-osoite" + }, + "channelPrefix": "Kanava: ", + "channelSetUrl": "Kanavan asetus / QR-koodin URL-osoite", + "channels": "Kanavat:", + "usePreset": "Käytä esiasetusta?", + "title": "Tuo kanava-asetukset" + }, + "locationResponse": { + "altitude": "Korkeus: ", + "coordinates": "Koordinaatit: ", + "title": "Sijainti: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Luodaanko ennalta jaettu avain uudelleen?", + "description": "Haluatko varmasti luoda ennalta jaetun avaimen uudelleen?", + "regenerate": "Luo uudelleen" + }, + "newDeviceDialog": { + "title": "Yhdistä uuteen laitteeseen", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Sarjaliitäntä", + "useHttps": "Käytä HTTPS", + "connecting": "Yhdistetään...", + "connect": "Yhdistä", + "connectionFailedAlert": { + "title": "Yhteys epäonnistui", + "descriptionPrefix": "Laitteeseen ei saatu yhteyttä. ", + "httpsHint": "Jos käytät HTTPS:ää, sinun on ehkä ensin hyväksyttävä itse allekirjoitettu varmenne. ", + "openLinkPrefix": "Avaa ", + "openLinkSuffix": " uuteen välilehteen", + "acceptTlsWarningSuffix": ", hyväksy mahdolliset TLS-varoitukset, jos niitä ilmenee ja yritä sitten uudelleen.", + "learnMoreLink": "Lue lisää" + }, + "httpConnection": { + "label": "IP-osoite / isäntänimi", + "placeholder": "000.000.000 / meshtastinen.paikallinen" + }, + "serialConnection": { + "noDevicesPaired": "Yhtään laitetta ei ole vielä yhdistetty.", + "newDeviceButton": "Uusi laite", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "Yhtään laitetta ei ole vielä yhdistetty.", + "newDeviceButton": "Uusi laite" + }, + "validation": { + "requiresFeatures": "Tämä yhteystyyppi vaatii <0>. Käytä tuettua selainta, kuten Chromea tai Edgeä.", + "requiresSecureContext": "Tämä sovellus vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia.", + "additionallyRequiresSecureContext": "Lisäksi se vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia." + } + }, + "nodeDetails": { + "message": "Viesti", + "requestPosition": "Pyydä sijaintia", + "traceRoute": "Reitinselvitys", + "airTxUtilization": "Ilmatien TX käyttöaste", + "allRawMetrics": "Kaikki raakatiedot:", + "batteryLevel": "Akun varaus", + "channelUtilization": "Kanavan käyttöaste", + "details": "Tiedot:", + "deviceMetrics": "Laitteen mittausloki:", + "hardware": "Laitteisto: ", + "lastHeard": "Viimeksi kuultu: ", + "nodeHexPrefix": "Laitteen Hex: !", + "nodeNumber": "Laitteen numero: ", + "position": "Sijainti:", + "role": "Rooli: ", + "uptime": "Käyttöaika: ", + "voltage": "Jännite", + "title": "Tiedot laitteelle {{identifier}}", + "ignoreNode": "Älä huomioi laitetta", + "removeNode": "Poista laite", + "unignoreNode": "Poista laitteen ohitus käytöstä" + }, + "pkiBackup": { + "description": "Suosittelemme avaintietojen säännöllistä varmuuskopiointia. Haluatko varmuuskopioida nyt?", + "loseKeysWarning": "Jos menetät avaimesi, sinun täytyy palauttaa laite tehdasasetuksiin.", + "secureBackup": "On tärkeää varmuuskopioida julkiset ja yksityiset avaimet ja säilyttää niiden varmuuskopioita turvallisesti!", + "footer": "=== AVAIMIEN LOPPU ===", + "header": "=== MESHTASTIC AVAIMET {{longName}} ({{shortName}}) LAITTEELLE ===", + "privateKey": "Yksityinen avain:", + "publicKey": "Julkinen avain:", + "fileName": "meshtastic_avaimet_{{longName}}_{{shortName}}.txt", + "title": "Varmuuskopioi avaimet" + }, + "pkiRegenerate": { + "description": "Haluatko varmasti luoda avainparin uudelleen?", + "title": "Luo avainpari uudelleen" + }, + "qr": { + "addChannels": "Lisää kanavia", + "replaceChannels": "Korvaa kanavia", + "description": "Nykyinen LoRa-kokoonpano tullaan myös jakamaan.", + "sharableUrl": "Jaettava URL", + "title": "Generoi QR-koodi" + }, + "rebootOta": { + "title": "Ajasta uudelleenkäynnistys", + "description": "Käynnistä yhdistetty laite uudelleen viiveen jälkeen OTA-tilaan (langaton päivitys).", + "enterDelay": "Anna viive (sekuntia)", + "scheduled": "Uudelleenkäynnistys on ajastettu" + }, + "reboot": { + "title": "Ajasta uudelleenkäynnistys", + "description": "Käynnistä yhdistetty laite x minuutin jälkeen." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "Tämä poistaa laitteen laitteesta ja pyytää uusia avaimia.", + "keyMismatchReasonSuffix": ". Tämä johtuu siitä, että etälaitteen nykyinen julkinen avain ei vastaa aiemmin tallennettua avainta tälle laitteelle.", + "unableToSendDmPrefix": "Laitteesi ei pysty lähettämään suoraa viestiä laitteelle: " + }, + "acceptNewKeys": "Hyväksy uudet avaimet", + "title": "Avaimet eivät täsmää - {{identifier}}" + }, + "removeNode": { + "description": "Haluatko varmasti poistaa tämän laitteen?", + "title": "Poista laite?" + }, + "shutdown": { + "title": "Ajasta sammutus", + "description": "Sammuta yhdistetty laite x minuutin päästä." + }, + "traceRoute": { + "routeToDestination": "Reitin määränpää:", + "routeBack": "Reitti takaisin:" + }, + "tracerouteResponse": { + "title": "Reitinselvitys: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Kyllä, tiedän mitä teen", + "conjunction": " ja blogikirjoitukset ", + "postamble": " ja ymmärrän roolin muuttamisen vaikutukset.", + "preamble": "Olen lukenut ", + "choosingRightDeviceRole": "Valitse laitteelle oikea rooli", + "deviceRoleDocumentation": "Roolien dokumentaatio laitteelle", + "title": "Oletko varma?" + } +} diff --git a/src/i18n/locales/fi-FI/messages.json b/src/i18n/locales/fi-FI/messages.json new file mode 100644 index 00000000..b37421ef --- /dev/null +++ b/src/i18n/locales/fi-FI/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Viestit: {{chatName}}" + }, + "emptyState": { + "title": "Valitse keskustelu", + "text": "Ei vielä viestejä." + }, + "selectChatPrompt": { + "text": "Valitse kanava tai laite aloittaaksesi viestinnän." + }, + "sendMessage": { + "placeholder": "Kirjoita viesti tähän...", + "sendButton": "Lähetä" + }, + "actionsMenu": { + "addReactionLabel": "Lisää reaktio", + "replyLabel": "Vastaa" + }, + "item": { + "status": { + "delivered": { + "label": "Viesti toimitettu", + "displayText": "Viesti toimitettu" + }, + "failed": { + "label": "Viestin toimitus epäonnistui", + "displayText": "Toimitus epäonnistui" + }, + "unknown": { + "label": "Viestin tila tuntematon", + "displayText": "Tuntematon tila" + }, + "waiting": { + "ariaLabel": "Lähetetään viestiä", + "displayText": "Odottaa toimitusta" + } + } + } +} diff --git a/src/i18n/locales/fi-FI/moduleConfig.json b/src/i18n/locales/fi-FI/moduleConfig.json new file mode 100644 index 00000000..2eb76dfe --- /dev/null +++ b/src/i18n/locales/fi-FI/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ympäristövalaistus", + "tabAudio": "Ääni", + "tabCannedMessage": "Ennalta asetettu", + "tabDetectionSensor": "Havaitsemisanturi", + "tabExternalNotification": "Ext-ilmoitus", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Naapuritieto", + "tabPaxcounter": "PAX-laskuri", + "tabRangeTest": "Kuuluvuustesti", + "tabSerial": "Sarjaliitäntä", + "tabStoreAndForward": "S&V", + "tabTelemetry": "Telemetria" + }, + "ambientLighting": { + "title": "Ympäristövalaistuksen asetukset", + "description": "Ympäristövalaistuksen moduulin asetukset", + "ledState": { + "label": "Ledin tila", + "description": "Aseta ledi päälle tai pois päältä" + }, + "current": { + "label": "Virta", + "description": "Asettaa nykyisen ledin ulostulon. Oletus on 10" + }, + "red": { + "label": "Punainen", + "description": "Asettaa punaisen ledin tason. Arvot ovat 0-255" + }, + "green": { + "label": "Vihreä", + "description": "Asettaa vihreän ledin tason. Arvot ovat 0-255" + }, + "blue": { + "label": "Sininen", + "description": "Asettaa sinisen ledin tason. Arvot ovat 0-255" + } + }, + "audio": { + "title": "Ääniasetukset", + "description": "Äänimoduulin asetukset", + "codec2Enabled": { + "label": "Codec 2 käytössä", + "description": "Ota Codec 2 äänenkoodaus käyttöön" + }, + "pttPin": { + "label": "PTT pinni", + "description": "PTT:lle käytettävä GPIO-pinni" + }, + "bitrate": { + "label": "Tiedonsiirtonopeus", + "description": "Tiedonsiirtonopeus äänenkoodaukselle" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO-pinni jota käytetään i2S WS:ssä" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO-pinni jota käytetään i2S SD:ssä" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO-pinni jota käytetään i2S DIN:ssä" + }, + "i2sSck": { + "label": "i2S SD", + "description": "GPIO-pinni jota käytetään i2S SCK:ssa" + } + }, + "cannedMessage": { + "title": "Välitettyjen viestien asetukset", + "description": "Asetukset välitettyjen viestien moduulissa", + "moduleEnabled": { + "label": "Moduuli Käytössä", + "description": "Ota käyttöön välitetyt viestit" + }, + "rotary1Enabled": { + "label": "Kiertovalitsin #1 käytössä", + "description": "Ota kiertovalitsimen kooderi käyttöön" + }, + "inputbrokerPinA": { + "label": "Kooderin pinni A", + "description": "GPIO-pinni (1–39) kooderin portille A" + }, + "inputbrokerPinB": { + "label": "Kooderin pinni B", + "description": "GPIO-pinni (1–39) kooderin portille B" + }, + "inputbrokerPinPress": { + "label": "Kooderin pinni painallukselle", + "description": "GPIO-pinni (1–39) kooderin painallukselle" + }, + "inputbrokerEventCw": { + "label": "Myötäpäiväinen liike", + "description": "Valitse syöttötapahtuma." + }, + "inputbrokerEventCcw": { + "label": "Myötäpäiväisen liikkeen laskuri", + "description": "Valitse syöttötapahtuma." + }, + "inputbrokerEventPress": { + "label": "Painamisen tapahtuma", + "description": "Valitse syöttötapahtuma" + }, + "updown1Enabled": { + "label": "Ylös alas käytössä", + "description": "Ota käyttöön ylös / alas-suuntaa tunnistava kooderi" + }, + "allowInputSource": { + "label": "Salli syöttölaitteen lähde", + "description": "Valitse '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Lähetä äänimerkki", + "description": "Lähettää äänimerkkimerkin jokaisen viestin mukana" + } + }, + "detectionSensor": { + "title": "Tunnistinsensorin asetukset", + "description": "Tunnistinsensori-moduulin asetukset", + "enabled": { + "label": "Käytössä", + "description": "Ota käyttöön tai poista käytöstä tunnistinsensorin moduuli" + }, + "minimumBroadcastSecs": { + "label": "Minimilähetys (sekuntia)", + "description": "Aikaväli sekunteina kuinka usein viestejä voi lähettää mesh-verkkoon tilamuutoksen havaitsemisen jälkeen" + }, + "stateBroadcastSecs": { + "label": "Tilatiedon lähetys (sekuntia)", + "description": "Kuinka usein sekunteina lähetetään viesti mesh-verkkoon nykytilasta, vaikka tilassa ei olisi muutoksia" + }, + "sendBell": { + "label": "Lähetä äänimerkki", + "description": "Lähetä ASCII-äänimerkki hälytyssanoman mukana" + }, + "name": { + "label": "Käyttäjäystävälinen nimi", + "description": "Käytetään muotoilemaan mesh-verkkoon lähetettävä viesti, enintään 20 merkkiä" + }, + "monitorPin": { + "label": "Valvonta pinni", + "description": "GPIO-pinni valvonnan tilan muutoksien seurantaan" + }, + "detectionTriggerType": { + "label": "Tunnistuksen havaintotyyppi", + "description": "Käytettävän tunnistustapahtuman tyyppi" + }, + "usePullup": { + "label": "Käytä vetokytkintä (pullup)", + "description": "Käytetäänkö GPIO-pinnin INPUT_PULLUP-tilaa" + } + }, + "externalNotification": { + "title": "Ulkoisten ilmoituksien asetukset", + "description": "Määritä ulkoisten ilmoitusten moduulin asetukset", + "enabled": { + "label": "Moduuli käytössä", + "description": "Ota ulkoiset ilmoitukset käyttöön" + }, + "outputMs": { + "label": "Ulostulo MS", + "description": "Ulostulo MS" + }, + "output": { + "label": "Ulostulo", + "description": "Ulostulo" + }, + "outputVibra": { + "label": "Värinän ulostulo", + "description": "Värinän ulostulo" + }, + "outputBuzzer": { + "label": "Summerin ulostulo", + "description": "Summerin ulostulo" + }, + "active": { + "label": "Käytössä", + "description": "Käytössä" + }, + "alertMessage": { + "label": "Hälytysviesti", + "description": "Hälytysviesti" + }, + "alertMessageVibra": { + "label": "Hälytysviestin värinä", + "description": "Hälytysviestin värinä" + }, + "alertMessageBuzzer": { + "label": "Hälytysviestin summeri", + "description": "Hälytysviestin summeri" + }, + "alertBell": { + "label": "Hälytysääni", + "description": "Pitäisikö hälytyksen aktivoitua, kun vastaanotetaan äänimerkki?" + }, + "alertBellVibra": { + "label": "Hälytysäänen värinä", + "description": "Hälytysäänen värinä" + }, + "alertBellBuzzer": { + "label": "Hälytysäänen summeri", + "description": "Hälytysäänen summeri" + }, + "usePwm": { + "label": "Käytä PWM", + "description": "Käytä PWM" + }, + "nagTimeout": { + "label": "Toistokehotuksen aikakatkaisu", + "description": "Toistokehotuksen aikakatkaisu" + }, + "useI2sAsBuzzer": { + "label": "Use I²S pinniä summerille", + "description": "Määritä I²S-pinni summerin ulostuloon" + } + }, + "mqtt": { + "title": "MQTT-asetukset", + "description": "MQTT-moduulin asetukset", + "enabled": { + "label": "Käytössä", + "description": "Ota MQTT käyttöön tai poista se käytöstä" + }, + "address": { + "label": "MQTT-palvelimen osoite", + "description": "MQTT-palvelimen osoite, jota käytetään oletus- tai mukautetuissa palvelimissa" + }, + "username": { + "label": "MQTT käyttäjänimi", + "description": "MQTT käyttäjänimi, jota käytetään oletus- tai mukautetuissa palvelimissa" + }, + "password": { + "label": "MQTT salasana", + "description": "MQTT salasana, jota käytetään oletus- tai mukautetuissa palvelimissa" + }, + "encryptionEnabled": { + "label": "Salaus käytössä", + "description": "Ota MQTT-salaus käyttöön tai pois käytöstä. Huom: Jos tämä asetus ei ole käytössä, kaikki viestit lähetetään MQTT-välittäjälle salaamattomina, vaikka lähetyskanavillasi olisi salausavaimet asetettuna. Tämä koskee myös sijaintitietoja." + }, + "jsonEnabled": { + "label": "JSON käytössä", + "description": "Lähetetäänkö / otetaanko vastaan JSON-paketteja MQTT:llä" + }, + "tlsEnabled": { + "label": "TLS käytössä", + "description": "Ota TLS käyttöön tai poista se käytöstä" + }, + "root": { + "label": "Palvelimen osoite (root topic)", + "description": "MQTT-palvelimen osoite, jota käytetään oletus- tai mukautetuissa palvelimissa" + }, + "proxyToClientEnabled": { + "label": "MQTT-välityspalvelin käytössä", + "description": "Käyttää verkkoyhteyttä välittämään MQTT-viestejä asiakkaalle." + }, + "mapReportingEnabled": { + "label": "Karttaraportointi käytössä", + "description": "Laitteesi lähettää säännöllisin väliajoin salaamattoman karttaraporttipaketin määritettyyn MQTT-palvelimeen. Paketti sisältää tunnisteen, lyhyen ja pitkän nimen, likimääräisen sijainnin, laitteistomallin, roolin, laiteohjelmistoversion, LoRa-alueen, modeemin esiasetukset sekä ensisijaisen kanavan nimen." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Karttaraportoinnin aikaväli (s)", + "description": "Aikaväli sekunneissa karttaraporttien julkaisemiseksi" + }, + "positionPrecision": { + "label": "Arvioitu sijainti", + "description": "Jaetun sijainnin tarkkuus on tämän etäisyyden rajoissa", + "options": { + "metric_km23": "23 kilometrin säteellä", + "metric_km12": "12 kilometrin säteellä", + "metric_km5_8": "5,8 kilometrin säteellä", + "metric_km2_9": "2,9 kilometrin säteellä", + "metric_km1_5": "1,5 kilometrin säteellä", + "metric_m700": "700 metrin säteellä", + "metric_m350": "350 metrin säteellä", + "metric_m200": "200 metrin säteellä", + "metric_m90": "90 metrin säteellä", + "metric_m50": "50 metrin säteellä", + "imperial_mi15": "15 mailin säteellä", + "imperial_mi7_3": "7,3 mailin säteellä", + "imperial_mi3_6": "3,6 mailin säteellä", + "imperial_mi1_8": "1,8 mailin säteellä", + "imperial_mi0_9": "0,9 mailin säteellä", + "imperial_mi0_5": "0,5 mailin säteellä", + "imperial_mi0_2": "0,2 mailin säteellä", + "imperial_ft600": "600 jalan säteellä", + "imperial_ft300": "300 jalan säteellä", + "imperial_ft150": "150 jalan säteellä" + } + } + } + }, + "neighborInfo": { + "title": "Naapuritiedon asetukset", + "description": "Naapuritietojen moduulin asetukset", + "enabled": { + "label": "Käytössä", + "description": "Ota käyttöön tai poista käytöstä naapuruustietomoduuli" + }, + "updateInterval": { + "label": "Päivitysväli", + "description": "Aikaväli sekunneissa siitä, kuinka usein mesh-verkossa lähetetään naapuritietoja verkkoon" + } + }, + "paxcounter": { + "title": "Pax-laskurin asetukset", + "description": "Pax-laskurin moduulin asetukset", + "enabled": { + "label": "Moduuli käytössä", + "description": "Ota pax-laskuri käyttöön" + }, + "paxcounterUpdateInterval": { + "label": "Päivityksen aikaväli (sekuntia)", + "description": "Kuinka kauan odotetaan pax-laskurin pakettien lähettämisen välillä" + }, + "wifiThreshold": { + "label": "WiFi-RSSI kynnysarvo", + "description": "Millä WiFi RSSI tasolla laskurin täytyisi kasvaa. Oletus on -80." + }, + "bleThreshold": { + "label": "WiFi-RSSI kynnysarvo", + "description": "Millä BLE RSSI-arvolla laskuri kasvaa. Oletus: -80." + } + }, + "rangeTest": { + "title": "Kuuluvuustestin asetukset", + "description": "Kuuluvuustesti moduulin asetukset", + "enabled": { + "label": "Moduuli käytössä", + "description": "Ota kuuluvuustesti käytöön" + }, + "sender": { + "label": "Viestin aikaväli", + "description": "Kuinka kauan odotetaan testipakettien lähettämisen välillä" + }, + "save": { + "label": "Tallenna CSV tallennustilaan", + "description": "Vain ESP32" + } + }, + "serial": { + "title": "Sarjaliitännän asetukset", + "description": "Sarjaliitäntä-moduulin asetukset", + "enabled": { + "label": "Sarjaliitäntä käytössä", + "description": "Ota sarjaliitäntä käyttöön" + }, + "echo": { + "label": "Toista", + "description": "Kaikki lähettämäsi paketit toistetaan takaisin laitteellesi" + }, + "rxd": { + "label": "Vastaanota PIN-koodi", + "description": "Määritä GPIO-pinni käyttämään aiemmin asetettua RXD-pinniä." + }, + "txd": { + "label": "Lähetä PIN-koodi", + "description": "Määritä GPIO-pinni käyttämään aiemmin asetettua TXD-pinniä." + }, + "baud": { + "label": "Baud-siirtonopeus", + "description": "Sarjaliitännän baud-siirtonopeus" + }, + "timeout": { + "label": "Aikakatkaisu", + "description": "Kuinka monta sekuntia odotetaan, ennen kuin paketti merkitään valmiiksi" + }, + "mode": { + "label": "Tila", + "description": "Valitse tila" + }, + "overrideConsoleSerialPort": { + "label": "Ohita konsolin sarjaliitännän portti", + "description": "Jos sinulla on sarjaportti kytkettynä konsoliin, tämä ohittaa sen." + } + }, + "storeForward": { + "title": "Varastoi & välitä asetukset", + "description": "Varastoi & välitä moduulin asetukset", + "enabled": { + "label": "Moduuli käytössä", + "description": "Ota varastoi & välitä käyttöön" + }, + "heartbeat": { + "label": "Heartbeat käytössä", + "description": "Ota varastoi & välitä heartbeat käyttöön" + }, + "records": { + "label": "Kirjausten määrä", + "description": "Tallennettavien tietueiden määrä" + }, + "historyReturnMax": { + "label": "Historian maksimimäärä", + "description": "Enimmäismäärä tietueita palautettaviksi" + }, + "historyReturnWindow": { + "label": "Historian aikamäärä", + "description": "Enimmäismäärä tietueita palautettaviksi" + } + }, + "telemetry": { + "title": "Telemetrian asetukset", + "description": "Telemetria-moduulin asetukset", + "deviceUpdateInterval": { + "label": "Laitteen mittausloki", + "description": "Laitteen mittaustietojen päivitysväli (sekuntia)" + }, + "environmentUpdateInterval": { + "label": "Ympäristötietojen päivitysväli (sekuntia)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Moduuli käytössä", + "description": "Ota käyttöön ympäristön telemetria" + }, + "environmentScreenEnabled": { + "label": "Näytetään näytöllä", + "description": "Näytä moduulin telemetriatiedot OLED-näytöllä" + }, + "environmentDisplayFahrenheit": { + "label": "Näytä fahrenheitissa", + "description": "Näytä lämpötila fahrenheitissa" + }, + "airQualityEnabled": { + "label": "Ilmanlaatu käytössä", + "description": "Ota ilmanlaadun telemetria käyttöön" + }, + "airQualityInterval": { + "label": "Ilmanlaadun päivitysväli", + "description": "Kuinka usein ilmanlaadun tiedot lähetetään mesh-verkon kautta" + }, + "powerMeasurementEnabled": { + "label": "Tehomittaus käytössä", + "description": "Ota tehomittauksen telemetria käyttöön" + }, + "powerUpdateInterval": { + "label": "Tehomittauksen päivitysväli", + "description": "Kuinka usein tehomittauksen tiedot lähetetään mesh-verkon kautta" + }, + "powerScreenEnabled": { + "label": "Tehomittauksen näyttö käytössä", + "description": "Ota tehomittauksen telemetrian näyttö käyttöön" + } + } +} diff --git a/src/i18n/locales/fi-FI/nodes.json b/src/i18n/locales/fi-FI/nodes.json new file mode 100644 index 00000000..8c2b7401 --- /dev/null +++ b/src/i18n/locales/fi-FI/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Julkinen avain käytössä" + }, + "noPublicKey": { + "label": "Ei julkinen avain" + }, + "directMessage": { + "label": "Suora Viesti {{shortName}}" + }, + "favorite": { + "label": "Suosikki" + }, + "notFavorite": { + "label": "Ei suosikki" + }, + "status": { + "heard": "Kuultu", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Korkeus" + }, + "channelUtil": { + "label": "Kanavan käyttö" + }, + "airtimeUtil": { + "label": "Lähetysajan käyttö" + } + }, + "nodesTable": { + "headings": { + "longName": "Pitkä nimi", + "connection": "Yhteys", + "lastHeard": "Viimeksi kuultu", + "encryption": "Salaus", + "model": "Malli", + "macAddress": "MAC-osoite" + }, + "connectionStatus": { + "direct": "Suora", + "away": "poissa", + "unknown": "-", + "viaMqtt": ", MQTT välityksellä" + }, + "lastHeardStatus": { + "never": "Ei koskaan" + } + } +} diff --git a/src/i18n/locales/fi-FI/ui.json b/src/i18n/locales/fi-FI/ui.json new file mode 100644 index 00000000..f0fb9477 --- /dev/null +++ b/src/i18n/locales/fi-FI/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigointi", + "messages": "Viestit", + "map": "Kartta", + "config": "Asetukset", + "radioConfig": "Radion asetukset", + "moduleConfig": "Moduulin asetukset", + "channels": "Kanavat", + "nodes": "Laitteet" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Avaa sivupalkki", + "close": "Sulje sivupalkki" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volttia", + "firmware": { + "title": "Laiteohjelmisto", + "version": "v{{version}}", + "buildDate": "Koontipäivä: {{date}}" + }, + "deviceName": { + "title": "Laitteen nimi", + "changeName": "Vaihda laitteen nimi", + "placeholder": "Anna laitteelle nimi" + }, + "editDeviceName": "Muokkaa laitteen nimeä" + } + }, + "batteryStatus": { + "charging": "{{level}} % latauksessa", + "pluggedIn": "Kytketty verkkovirtaan", + "title": "Akku" + }, + "search": { + "nodes": "Etsi laitteita...", + "channels": "Etsi kanavia...", + "commandPalette": "Etsi komentoja..." + }, + "toast": { + "positionRequestSent": { + "title": "Sijaintipyyntö lähetetty." + }, + "requestingPosition": { + "title": "Pyydetään sijaintia, odota..." + }, + "sendingTraceroute": { + "title": "Reitinselvitys lähetetty, odota..." + }, + "tracerouteSent": { + "title": "Reitinselvitys lähetetty." + }, + "savedChannel": { + "title": "Tallennettu Kanava: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Keskustelu käyttää PKI-salausta." + }, + "pskEncryption": { + "title": "Keskustelu käyttää PKI-salausta." + } + }, + "configSaveError": { + "title": "Virhe asetusten tallentamisessa", + "description": "Asetusten tallennuksessa tapahtui virhe." + }, + "validationError": { + "title": "Asetuksissa on virheitä", + "description": "Ole hyvä ja korjaa asetusvirheet ennen tallentamista." + }, + "saveSuccess": { + "title": "Tallennetaan asetukset", + "description": "Asetuksien muutos {{case}} on tallennettu." + } + }, + "notifications": { + "copied": { + "label": "Kopioitu!" + }, + "copyToClipboard": { + "label": "Kopioi leikepöydälle" + }, + "hidePassword": { + "label": "Piilota salasana" + }, + "showPassword": { + "label": "Näytä salasana" + }, + "deliveryStatus": { + "delivered": "Toimitettu", + "failed": "Toimitus epäonnistui", + "waiting": "Odottaa", + "unknown": "Tuntematon" + } + }, + "general": { + "label": "Yleinen" + }, + "hardware": { + "label": "Laite" + }, + "metrics": { + "label": "Mittaustiedot" + }, + "role": { + "label": "Rooli" + }, + "filter": { + "label": "Suodatus" + }, + "clearInput": { + "label": "Tyhjennä kenttä" + }, + "resetFilters": { + "label": "Tyhjennä suodattimet" + }, + "nodeName": { + "label": "Laitteen nimi tai numero", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Ajan käyttöaste (%)" + }, + "batteryLevel": { + "label": "Akun varaus (%)", + "labelText": "Akun varaus (%): {{value}}" + }, + "batteryVoltage": { + "label": "Akun jännite (V)", + "title": "Jännite" + }, + "channelUtilization": { + "label": "Kanavan käyttö (%)" + }, + "hops": { + "direct": "Suora", + "label": "Hyppyjen määrä", + "text": "Hyppyjen määrä: {{value}}" + }, + "lastHeard": { + "label": "Viimeksi kuultu", + "labelText": "Viimeksi kuultu: {{value}}", + "nowLabel": "Nyt" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Suosikit" + }, + "hide": { + "label": "Piilota" + }, + "showOnly": { + "label": "Näytä pelkästään" + }, + "viaMqtt": { + "label": "Yhdistetty MQTT-yhteydellä" + }, + "language": { + "label": "Kieli", + "changeLanguage": "Vaihda kieli" + }, + "theme": { + "dark": "Tumma", + "light": "Vaalea", + "system": "Automaattinen", + "changeTheme": "Vaihda väriteema" + }, + "errorPage": { + "title": "Tämä on hieman noloa...", + "description1": "Pahoittelemme, mutta verkkosovelluksessa tapahtui virhe, joka aiheutti kaatumisen.
\nTämän ei pitäisi tapahtua ja me työskentelemme ahkerasti ongelman korjaamiseksi.", + "description2": "Paras tapa estää tämän tapahtuminen uudelleen sinulle tai kenellekään muulle, on ilmoittaa meille ongelmasta.", + "reportInstructions": "Lisääthän raporttiisi seuraavat tiedot:", + "reportSteps": { + "step1": "Mitä olit tekemässä virheen tapahtuessa", + "step2": "Mitä odotit tapahtuvan", + "step3": "Mitä todellisuudessa tapahtui", + "step4": "Muut mahdollisesti oleelliset tiedot" + }, + "reportLink": "Voit raportoida ongelmasta <0>GitHubissa", + "dashboardLink": "Palaa takaisin <0>dashboard", + "detailsSummary": "Virheen tiedot", + "errorMessageLabel": "Virheilmoitus:", + "stackTraceLabel": "Virheen jäljityslista:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® on Meshtastic LLC:n rekisteröity tavaramerkki. | <1>Oikeudelliset tiedot", + "commitSha": "Versiokomentoviestin SHA-tunniste: {{sha}}" + } +} diff --git a/src/i18n/locales/fr-FR/channels.json b/src/i18n/locales/fr-FR/channels.json new file mode 100644 index 00000000..45c4d611 --- /dev/null +++ b/src/i18n/locales/fr-FR/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Canaux", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Principal", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Paramètres du canal", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Rôle", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Nom", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/fr-FR/commandPalette.json b/src/i18n/locales/fr-FR/commandPalette.json new file mode 100644 index 00000000..dcf72f2d --- /dev/null +++ b/src/i18n/locales/fr-FR/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messages", + "map": "Carte", + "config": "Config", + "channels": "Canaux", + "nodes": "Noeuds" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/fr-FR/common.json b/src/i18n/locales/fr-FR/common.json new file mode 100644 index 00000000..b3e4bc9b --- /dev/null +++ b/src/i18n/locales/fr-FR/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Appliquer", + "backupKey": "Backup Key", + "cancel": "Annuler", + "clearMessages": "Clear Messages", + "close": "Fermer", + "confirm": "Confirm", + "delete": "Effacer", + "dismiss": "Annuler", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Message", + "now": "Now", + "ok": "D'accord", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Supprimer", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Réinitialiser", + "save": "Sauvegarder", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Inconnu", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/fr-FR/dashboard.json b/src/i18n/locales/fr-FR/dashboard.json new file mode 100644 index 00000000..3ad917f9 --- /dev/null +++ b/src/i18n/locales/fr-FR/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Série", + "connectionType_network": "Réseau", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/fr-FR/deviceConfig.json b/src/i18n/locales/fr-FR/deviceConfig.json new file mode 100644 index 00000000..d98bc2a7 --- /dev/null +++ b/src/i18n/locales/fr-FR/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Appareil", + "tabDisplay": "Écran", + "tabLora": "LoRa", + "tabNetwork": "Réseau", + "tabPosition": "Position", + "tabPower": "Alimentation", + "tabSecurity": "Sécurité" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "Zone horaire POSIX" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Rôle" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Activé" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Mode d'appariement" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bande Passante" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignorer MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK vers MQTT" + }, + "overrideDutyCycle": { + "description": "Ne pas prendre en compte la limite d'utilisation", + "label": "Ne pas prendre en compte la limite d'utilisation" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Région" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Activé" + }, + "gateway": { + "description": "Default Gateway", + "label": "Passerelle" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Sous-réseau" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Activé" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configuration UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Horodatage", + "unset": "Désactivé", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Activer le mode économie d'énergie" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Configuration de l'alimentation" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Clé privée" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Clé publique" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/fr-FR/dialog.json b/src/i18n/locales/fr-FR/dialog.json new file mode 100644 index 00000000..b7b9c962 --- /dev/null +++ b/src/i18n/locales/fr-FR/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Série", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Message", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Tension", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Générer un QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Êtes-vous sûr ?" + } +} diff --git a/src/i18n/locales/fr-FR/messages.json b/src/i18n/locales/fr-FR/messages.json new file mode 100644 index 00000000..50f9b606 --- /dev/null +++ b/src/i18n/locales/fr-FR/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Envoyer" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Répondre" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/fr-FR/moduleConfig.json b/src/i18n/locales/fr-FR/moduleConfig.json new file mode 100644 index 00000000..c9675a27 --- /dev/null +++ b/src/i18n/locales/fr-FR/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Lumière ambiante", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Capteur de détection", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Informations sur les voisins", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Test de portée", + "tabSerial": "Série", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Télémetrie (Capteurs)" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Actif", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Rouge", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Vert", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Bleu", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Activé", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Activé", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Sujet principal", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Activé", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Écho", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Délai d'expiration", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Nombre d'enregistrements", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Intervalle de mise à jour des métriques de l'appareil (secondes)" + }, + "environmentUpdateInterval": { + "label": "Intervalle de mise à jour des métriques d'environnement (secondes)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/fr-FR/nodes.json b/src/i18n/locales/fr-FR/nodes.json new file mode 100644 index 00000000..1e088170 --- /dev/null +++ b/src/i18n/locales/fr-FR/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favoris" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Capté", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direk", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/fr-FR/ui.json b/src/i18n/locales/fr-FR/ui.json new file mode 100644 index 00000000..ff4ef6b8 --- /dev/null +++ b/src/i18n/locales/fr-FR/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messages", + "map": "Carte", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Canaux", + "nodes": "Noeuds" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Batterie" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Masquer le mot de passe" + }, + "showPassword": { + "label": "Afficher le mot de passe" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "En attente . . .", + "unknown": "Inconnu" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Matériel" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Rôle" + }, + "filter": { + "label": "Filtre" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Tension" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direk", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Dernière écoute", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Langue", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Sombre", + "light": "Clair", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/it-IT/channels.json b/src/i18n/locales/it-IT/channels.json new file mode 100644 index 00000000..c25a7b70 --- /dev/null +++ b/src/i18n/locales/it-IT/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Canali", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Principale", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Impostazioni Canale", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Ruolo", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Nome", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/it-IT/commandPalette.json b/src/i18n/locales/it-IT/commandPalette.json new file mode 100644 index 00000000..28f2f942 --- /dev/null +++ b/src/i18n/locales/it-IT/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Messaggi", + "map": "Mappa", + "config": "Config", + "channels": "Canali", + "nodes": "Nodi" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Importa", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/it-IT/common.json b/src/i18n/locales/it-IT/common.json new file mode 100644 index 00000000..665205de --- /dev/null +++ b/src/i18n/locales/it-IT/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Applica", + "backupKey": "Backup Key", + "cancel": "Annulla", + "clearMessages": "Clear Messages", + "close": "Chiudi", + "confirm": "Confirm", + "delete": "Elimina", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Importa", + "message": "Messaggio", + "now": "Now", + "ok": "Ok", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Elimina", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Salva", + "scanQr": "Scansiona codice QR", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/it-IT/dashboard.json b/src/i18n/locales/it-IT/dashboard.json new file mode 100644 index 00000000..5b521ab1 --- /dev/null +++ b/src/i18n/locales/it-IT/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Seriale", + "connectionType_network": "Rete", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/it-IT/deviceConfig.json b/src/i18n/locales/it-IT/deviceConfig.json new file mode 100644 index 00000000..6ca4ef4d --- /dev/null +++ b/src/i18n/locales/it-IT/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Dispositivo", + "tabDisplay": "Schermo", + "tabLora": "LoRa", + "tabNetwork": "Rete", + "tabPosition": "Posizione", + "tabPower": "Alimentazione", + "tabSecurity": "Sicurezza" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Ruolo" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Modalità abbinamento" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Larghezza di banda" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignora MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Configurazione Modem" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK per MQTT" + }, + "overrideDutyCycle": { + "description": "Ignora limite di Duty Cycle", + "label": "Ignora limite di Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Regione" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configurazione UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Data e ora", + "unset": "Non impostato", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Abilita modalità risparmio energetico" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Configurazione Alimentazione" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Chiave Privata" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Chiave Pubblica" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/it-IT/dialog.json b/src/i18n/locales/it-IT/dialog.json new file mode 100644 index 00000000..6c0197a4 --- /dev/null +++ b/src/i18n/locales/it-IT/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seriale", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Messaggio", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Tensione", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Sei sicuro?" + } +} diff --git a/src/i18n/locales/it-IT/messages.json b/src/i18n/locales/it-IT/messages.json new file mode 100644 index 00000000..2f2dca24 --- /dev/null +++ b/src/i18n/locales/it-IT/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Invia" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Rispondi" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/it-IT/moduleConfig.json b/src/i18n/locales/it-IT/moduleConfig.json new file mode 100644 index 00000000..544512d5 --- /dev/null +++ b/src/i18n/locales/it-IT/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Luce Ambientale", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Sensore Di Rilevamento", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Informazioni Vicinato", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Test Distanza", + "tabSerial": "Seriale", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetria" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Attuale", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Rosso", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Verde", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blu", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Numero di record", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "Cronologia ritorno max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "Finestra di ritorno cronologia", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Intervallo aggiornamento metriche dispositivo (secondi)" + }, + "environmentUpdateInterval": { + "label": "Intervallo aggiornamento metriche ambientali (secondi)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/it-IT/nodes.json b/src/i18n/locales/it-IT/nodes.json new file mode 100644 index 00000000..cfaa76be --- /dev/null +++ b/src/i18n/locales/it-IT/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Preferito" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Diretto", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/it-IT/ui.json b/src/i18n/locales/it-IT/ui.json new file mode 100644 index 00000000..110b4ffb --- /dev/null +++ b/src/i18n/locales/it-IT/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Messaggi", + "map": "Mappa", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Canali", + "nodes": "Nodi" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Batteria" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Nascondi password" + }, + "showPassword": { + "label": "Visualizza password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Statistiche" + }, + "role": { + "label": "Ruolo" + }, + "filter": { + "label": "Filtro" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Tensione" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Diretto", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Ricevuto più di recente", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Lingua", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Scuro", + "light": "Chiaro", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/ja-JP/channels.json b/src/i18n/locales/ja-JP/channels.json new file mode 100644 index 00000000..5dc28596 --- /dev/null +++ b/src/i18n/locales/ja-JP/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "チャンネル", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "プライマリ", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "チャンネル設定", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "役割", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "名前", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/ja-JP/commandPalette.json b/src/i18n/locales/ja-JP/commandPalette.json new file mode 100644 index 00000000..d43e0ee4 --- /dev/null +++ b/src/i18n/locales/ja-JP/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "メッセージ", + "map": "地図", + "config": "Config", + "channels": "チャンネル", + "nodes": "ノード" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "インポート", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/ja-JP/common.json b/src/i18n/locales/ja-JP/common.json new file mode 100644 index 00000000..e594bfd1 --- /dev/null +++ b/src/i18n/locales/ja-JP/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "適用", + "backupKey": "Backup Key", + "cancel": "キャンセル", + "clearMessages": "Clear Messages", + "close": "終了", + "confirm": "Confirm", + "delete": "削除", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "インポート", + "message": "メッセージ", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "削除", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "リセット", + "save": "保存", + "scanQr": "QRコードをスキャン", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SN比", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/ja-JP/dashboard.json b/src/i18n/locales/ja-JP/dashboard.json new file mode 100644 index 00000000..890b4644 --- /dev/null +++ b/src/i18n/locales/ja-JP/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "シリアル", + "connectionType_network": "ネットワーク", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/ja-JP/deviceConfig.json b/src/i18n/locales/ja-JP/deviceConfig.json new file mode 100644 index 00000000..eaaa6010 --- /dev/null +++ b/src/i18n/locales/ja-JP/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "接続するデバイスを選択", + "tabDisplay": "表示", + "tabLora": "LoRa", + "tabNetwork": "ネットワーク", + "tabPosition": "位置", + "tabPower": "電源", + "tabSecurity": "セキュリティ" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX 時間帯" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "役割" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "ペアリングモード" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "帯域" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "MQTT を無視" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "モデムプリセット" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "MQTTを許可" + }, + "overrideDutyCycle": { + "description": "デューティサイクルを上書き", + "label": "デューティサイクルを上書き" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "リージョン" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "ゲートウェイ" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "サブネット" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "タイムスタンプ", + "unset": "削除", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "省電力モードを有効化" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "電源設定" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "秘密鍵" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "公開鍵" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/ja-JP/dialog.json b/src/i18n/locales/ja-JP/dialog.json new file mode 100644 index 00000000..ca055f94 --- /dev/null +++ b/src/i18n/locales/ja-JP/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "シリアル", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "メッセージ", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "電圧", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "よろしいですか?" + } +} diff --git a/src/i18n/locales/ja-JP/messages.json b/src/i18n/locales/ja-JP/messages.json new file mode 100644 index 00000000..b6835744 --- /dev/null +++ b/src/i18n/locales/ja-JP/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "送信" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "返信" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/ja-JP/moduleConfig.json b/src/i18n/locales/ja-JP/moduleConfig.json new file mode 100644 index 00000000..c6d82c85 --- /dev/null +++ b/src/i18n/locales/ja-JP/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "環境照明", + "tabAudio": "オーディオ", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "検出センサー", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "隣接ノード情報", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "レンジテスト", + "tabSerial": "シリアル", + "tabStoreAndForward": "S&F", + "tabTelemetry": "テレメトリー" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "電流", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "赤", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "緑", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "青", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "ルート トピック", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "タイムアウト", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "サーバーの最大保管レコード数 (デフォルト 約11,000レコード)", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "リクエスト可能な最大の履歴件数", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "リクエスト可能な履歴の期間 (分)", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "デバイスのメトリック更新間隔 (秒)" + }, + "environmentUpdateInterval": { + "label": "環境メトリック更新間隔 (秒)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/ja-JP/nodes.json b/src/i18n/locales/ja-JP/nodes.json new file mode 100644 index 00000000..c019ff57 --- /dev/null +++ b/src/i18n/locales/ja-JP/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "お気に入り" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "直接", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/ja-JP/ui.json b/src/i18n/locales/ja-JP/ui.json new file mode 100644 index 00000000..95fa0250 --- /dev/null +++ b/src/i18n/locales/ja-JP/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "メッセージ", + "map": "地図", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "チャンネル", + "nodes": "ノード" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "ファームウェア", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "バッテリー" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "パスワードを非表示" + }, + "showPassword": { + "label": "パスワードを表示" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "ハードウェア" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "役割" + }, + "filter": { + "label": "絞り込み" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "電圧" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "直接", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "最後の通信", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "言語設定", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "ダーク", + "light": "ライト", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/nl-NL/channels.json b/src/i18n/locales/nl-NL/channels.json new file mode 100644 index 00000000..ef9b4d4b --- /dev/null +++ b/src/i18n/locales/nl-NL/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanalen", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primair", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Kanaalinstellingen", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Functie", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Naam", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/nl-NL/commandPalette.json b/src/i18n/locales/nl-NL/commandPalette.json new file mode 100644 index 00000000..87c47c87 --- /dev/null +++ b/src/i18n/locales/nl-NL/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Berichten", + "map": "Kaart", + "config": "Config", + "channels": "Kanalen", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Importeer", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/nl-NL/common.json b/src/i18n/locales/nl-NL/common.json new file mode 100644 index 00000000..28b10515 --- /dev/null +++ b/src/i18n/locales/nl-NL/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Toepassen", + "backupKey": "Backup Key", + "cancel": "Annuleer", + "clearMessages": "Clear Messages", + "close": "Sluit", + "confirm": "Confirm", + "delete": "Verwijder", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Importeer", + "message": "Bericht", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Verwijder", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Reset", + "save": "Opslaan", + "scanQr": "Scan QR-code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/nl-NL/dashboard.json b/src/i18n/locales/nl-NL/dashboard.json new file mode 100644 index 00000000..3f7c26d6 --- /dev/null +++ b/src/i18n/locales/nl-NL/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serieel", + "connectionType_network": "Netwerk", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/nl-NL/deviceConfig.json b/src/i18n/locales/nl-NL/deviceConfig.json new file mode 100644 index 00000000..19db7dae --- /dev/null +++ b/src/i18n/locales/nl-NL/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Apparaat", + "tabDisplay": "Weergave", + "tabLora": "LoRa", + "tabNetwork": "Netwerk", + "tabPosition": "Positie", + "tabPower": "Vermogen", + "tabSecurity": "Beveiliging" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Functie" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Koppelmodus" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandbreedte" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Negeer MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Overschrijf Duty Cycle", + "label": "Overschrijf Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Regio" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP-adres" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Configuratie" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Tijdstempel", + "unset": "Terugzetten", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Energiebesparingsmodus inschakelen" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Energie configuratie" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Privésleutel" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Publieke sleutel" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/nl-NL/dialog.json b/src/i18n/locales/nl-NL/dialog.json new file mode 100644 index 00000000..d575cca2 --- /dev/null +++ b/src/i18n/locales/nl-NL/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serieel", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Verbinding maken", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Bericht", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Spanning", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Weet u het zeker?" + } +} diff --git a/src/i18n/locales/nl-NL/messages.json b/src/i18n/locales/nl-NL/messages.json new file mode 100644 index 00000000..48c98b4a --- /dev/null +++ b/src/i18n/locales/nl-NL/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Verzend" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/nl-NL/moduleConfig.json b/src/i18n/locales/nl-NL/moduleConfig.json new file mode 100644 index 00000000..2906dd8b --- /dev/null +++ b/src/i18n/locales/nl-NL/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Sfeerverlichting", + "tabAudio": "Geluid", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detectie Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Bereik Test", + "tabSerial": "Serieel", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetrie" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Huidige", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Rood", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Groen", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blauw", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Time-Out", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Aantal records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/nl-NL/nodes.json b/src/i18n/locales/nl-NL/nodes.json new file mode 100644 index 00000000..5ff9d341 --- /dev/null +++ b/src/i18n/locales/nl-NL/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favoriet" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/nl-NL/ui.json b/src/i18n/locales/nl-NL/ui.json new file mode 100644 index 00000000..6db74c2a --- /dev/null +++ b/src/i18n/locales/nl-NL/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Berichten", + "map": "Kaart", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Kanalen", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Batterij" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Wachtwoord verbergen" + }, + "showPassword": { + "label": "Wachtwoord tonen" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Functie" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Spanning" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Laatst gehoord", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Taal", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Donker", + "light": "Licht", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/pt-PT/channels.json b/src/i18n/locales/pt-PT/channels.json new file mode 100644 index 00000000..ab1e9169 --- /dev/null +++ b/src/i18n/locales/pt-PT/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Canal", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Principal", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Configurações de canal", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Papel", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Nome", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/pt-PT/commandPalette.json b/src/i18n/locales/pt-PT/commandPalette.json new file mode 100644 index 00000000..6835f1a5 --- /dev/null +++ b/src/i18n/locales/pt-PT/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Mensagens", + "map": "Mapa", + "config": "Config", + "channels": "Canal", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Importar", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Depuração", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/pt-PT/common.json b/src/i18n/locales/pt-PT/common.json new file mode 100644 index 00000000..369852e3 --- /dev/null +++ b/src/i18n/locales/pt-PT/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Aplicar", + "backupKey": "Backup Key", + "cancel": "Cancelar", + "clearMessages": "Clear Messages", + "close": "Fechar", + "confirm": "Confirm", + "delete": "Excluir", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Importar", + "message": "Mensagem", + "now": "Now", + "ok": "Okay", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Remover", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Redefinir", + "save": "Salvar", + "scanQr": "Ler código QR", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/pt-PT/dashboard.json b/src/i18n/locales/pt-PT/dashboard.json new file mode 100644 index 00000000..b68c6190 --- /dev/null +++ b/src/i18n/locales/pt-PT/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Série", + "connectionType_network": "Rede", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/pt-PT/deviceConfig.json b/src/i18n/locales/pt-PT/deviceConfig.json new file mode 100644 index 00000000..091a01c8 --- /dev/null +++ b/src/i18n/locales/pt-PT/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Dispositivo", + "tabDisplay": "Ecrã", + "tabLora": "LoRa", + "tabNetwork": "Rede", + "tabPosition": "Posição", + "tabPower": "Energia", + "tabSecurity": "Segurança" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "Fuso horário POSIX" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Papel" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Modo de emparelhamento" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Largura de banda" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignorar MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Predefinição de modem" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "Disponibilizar no MQTT" + }, + "overrideDutyCycle": { + "description": "Ignorar ciclo de trabalho", + "label": "Ignorar ciclo de trabalho" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Região" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Configuração UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Data e hora", + "unset": "Não Definido", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Ativar modo de poupança de energia" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Configuração de Energia" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Chave privada" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Chave pública" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/pt-PT/dialog.json b/src/i18n/locales/pt-PT/dialog.json new file mode 100644 index 00000000..91c118c9 --- /dev/null +++ b/src/i18n/locales/pt-PT/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Série", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Ligar", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Mensagem", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltagem", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Confirma?" + } +} diff --git a/src/i18n/locales/pt-PT/messages.json b/src/i18n/locales/pt-PT/messages.json new file mode 100644 index 00000000..13cbef08 --- /dev/null +++ b/src/i18n/locales/pt-PT/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Enviar" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Responder" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/pt-PT/moduleConfig.json b/src/i18n/locales/pt-PT/moduleConfig.json new file mode 100644 index 00000000..e3a638f8 --- /dev/null +++ b/src/i18n/locales/pt-PT/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Iluminação ambiente", + "tabAudio": "Áudio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Sensor de deteção", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Informações da vizinhança", + "tabPaxcounter": "Contador de pessoas", + "tabRangeTest": "Teste de Alcance", + "tabSerial": "Série", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetria" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Atual", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Vermelho", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Verde", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Azul", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Tópico principal", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Número de registos", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Intervalo de atualização de métricas do dispositivo (segundos)" + }, + "environmentUpdateInterval": { + "label": "Intervalo de atualização de métricas de ambiente (segundos)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/pt-PT/nodes.json b/src/i18n/locales/pt-PT/nodes.json new file mode 100644 index 00000000..6d0cd384 --- /dev/null +++ b/src/i18n/locales/pt-PT/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favoritos" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direto", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/pt-PT/ui.json b/src/i18n/locales/pt-PT/ui.json new file mode 100644 index 00000000..05b6bb5e --- /dev/null +++ b/src/i18n/locales/pt-PT/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Mensagens", + "map": "Mapa", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Canal", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Bateria" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Ocultar palavra-passe" + }, + "showPassword": { + "label": "Mostrar palavra-passe" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Papel" + }, + "filter": { + "label": "Filtrar" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltagem" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direto", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Último recebido", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Idioma", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Escuro", + "light": "Claro", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/sv-SE/channels.json b/src/i18n/locales/sv-SE/channels.json new file mode 100644 index 00000000..de35fc36 --- /dev/null +++ b/src/i18n/locales/sv-SE/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanaler", + "channelName": "Kanal: {channelName}", + "broadcastLabel": "Primär", + "channelIndex": "# {{index}}" + }, + "validation": { + "pskInvalid": "Ange en giltig {{bits}}-bitars PSK." + }, + "settings": { + "label": "Kanalinställningar", + "description": "Krypto, MQTT & diverse inställningar" + }, + "role": { + "label": "Roll", + "description": "Enhetens telemetri skickas över PRIMÄR. Endast en PRIMÄR kanal tillåts", + "options": { + "primary": "PRIMÄR", + "disabled": "INAKTIVERAD", + "secondary": "SEKUNDÄR" + } + }, + "psk": { + "label": "Delad nyckel (PSK)", + "description": "PSK-längder som stöds: 256-bit, 128-bit, 8-bit eller tom (0-bit)", + "generate": "Generera" + }, + "name": { + "label": "Namn", + "description": "Ett unikt namn för kanalen, <12 bytes. Lämna tomt för standardnamn" + }, + "uplinkEnabled": { + "label": "Upplänk aktiverad", + "description": "Skicka meddelanden från det lokala nätet till MQTT" + }, + "downlinkEnabled": { + "label": "Nedlänk aktiverad", + "description": "Skicka meddelanden från MQTT till det lokala nätet" + }, + "positionPrecision": { + "label": "Plats", + "description": "Platsprecisionen som kan delas med kanalen. Kan inaktiveras.", + "options": { + "none": "Dela inte plats", + "precise": "Exakt plats", + "metric_km23": "Inom 23 kilometer", + "metric_km12": "Inom 12 kilometer", + "metric_km5_8": "Inom 5,8 kilometer", + "metric_km2_9": "Inom 2,9 kilometer", + "metric_km1_5": "Inom 1,5 kilometer", + "metric_m700": "Inom 700 meter", + "metric_m350": "Inom 350 meter", + "metric_m200": "Inom 200 meter", + "metric_m90": "Inom 90 meter", + "metric_m50": "Inom 50 meter", + "imperial_mi15": "Inom 15 engelska mil", + "imperial_mi7_3": "Inom 7,3 engelska mil", + "imperial_mi3_6": "Inom 3,6 engelska mil", + "imperial_mi1_8": "Inom 1,8 engelska mil", + "imperial_mi0_9": "Inom 0,9 engelska mil", + "imperial_mi0_5": "Inom 0,5 engelska mil", + "imperial_mi0_2": "Inom 0,2 engelska mil", + "imperial_ft600": "Inom 600 fot", + "imperial_ft300": "Inom 300 fot", + "imperial_ft150": "Inom 150 fot" + } + } +} diff --git a/src/i18n/locales/sv-SE/commandPalette.json b/src/i18n/locales/sv-SE/commandPalette.json new file mode 100644 index 00000000..08f5814d --- /dev/null +++ b/src/i18n/locales/sv-SE/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "Inga resultat hittades.", + "page": { + "title": "Snabbmeny" + }, + "pinGroup": { + "label": "Lägg till grupp i favoriter" + }, + "unpinGroup": { + "label": "Ta bort grupp från favoriter" + }, + "goto": { + "label": "Gå till", + "command": { + "messages": "Meddelanden", + "map": "Karta", + "config": "Inställningar", + "channels": "Kanaler", + "nodes": "Noder" + } + }, + "manage": { + "label": "Hantera", + "command": { + "switchNode": "Byt nod", + "connectNewNode": "Anslut ny nod" + } + }, + "contextual": { + "label": "Kontextuell", + "command": { + "qrCode": "QR-kod", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schemalägg avstängning", + "scheduleReboot": "Schemalägg omstart", + "rebootToOtaMode": "Starta om till OTA-läge", + "resetNodeDb": "Töm noddatabasen", + "factoryResetDevice": "Fabriksåterställ enhet", + "factoryResetConfig": "Fabriksåterställ konfigurationen" + } + }, + "debug": { + "label": "Felsökning", + "command": { + "reconfigure": "Konfigurera om", + "clearAllStoredMessages": "Radera alla sparade meddelanden" + } + } +} diff --git a/src/i18n/locales/sv-SE/common.json b/src/i18n/locales/sv-SE/common.json new file mode 100644 index 00000000..c3dae4e5 --- /dev/null +++ b/src/i18n/locales/sv-SE/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Verkställ", + "backupKey": "Säkerhetskopiera nyckel", + "cancel": "Avbryt", + "clearMessages": "Ta bort meddelanden", + "close": "Stäng", + "confirm": "Bekräfta", + "delete": "Radera", + "dismiss": "Stäng", + "download": "Ladda ner", + "export": "Exportera", + "generate": "Generera", + "regenerate": "Förnya", + "import": "Importera", + "message": "Meddelande", + "now": "Nu", + "ok": "Okej", + "print": "Skriv ut", + "rebootOtaNow": "Starta om till OTA-läge nu", + "remove": "Ta bort", + "requestNewKeys": "Begär nya nycklar", + "requestPosition": "Begär position", + "reset": "Nollställ", + "save": "Spara", + "scanQr": "Skanna QR-kod", + "traceRoute": "Spåra rutt" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic webbklient" + }, + "loading": "Laddar...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "hopp", + "plural": "hopp" + }, + "hopsAway": { + "one": "{{count}} hopp bort", + "plural": "{{count}} hopp bort", + "unknown": "Okänt antal hopp bort" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meter", + "suffix": "m" + }, + "minute": { + "one": "minut", + "plural": "minuter" + }, + "millisecond": { + "one": "millisekund", + "plural": "millisekunder", + "suffix": "ms" + }, + "second": { + "one": "sekund", + "plural": "sekunder" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volt", + "suffix": "V" + }, + "record": { + "one": "Post", + "plural": "Poster" + } + }, + "security": { + "256bit": "256 bitar" + }, + "unknown": { + "longName": "Okänd", + "shortName": "UNK", + "notAvailable": "–", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "EJ SATT", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Texten är för lång. Ange en text mindre än eller lika med {{maximum}} tecken långt.", + "number": "Värdet är för stort. Ange ett numeriskt värde mindre än eller lika med {{maximum}}.", + "bytes": "Värdet är för stort. En längd mindre än eller lika med {{params.maximum}} bytes krävs." + }, + "tooSmall": { + "string": "Texten är för kort. Ange en text längre än eller lika med {{minimum}} tecken långt.", + "number": "Värdet är för litet. Ange ett numeriskt värde större än eller lika med {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Ogiltigt format, en giltig IPv4-adress krävs.", + "key": "Ogiltigt format, en giltig Base64-kodad nyckel krävs (PSK)." + }, + "invalidType": { + "number": "Ogiltig typ, fältet måste innehålla ett tal." + }, + "pskLength": { + "0bit": "Fältet måste vara tomt.", + "8bit": "Nyckeln måste vara en 8-bitars nyckel (PSK).", + "128bit": "Nyckeln måste vara en 128-bitars nyckel (PSK).", + "256bit": "Nyckeln måste vara en 256-bitars nyckel (PSK)." + }, + "required": { + "generic": "Obligatoriskt fält.", + "managed": "Åtminstone en administratörsnyckel krävs om noden fjärrhanteras.", + "key": "En nyckel måste anges." + } + } +} diff --git a/src/i18n/locales/sv-SE/dashboard.json b/src/i18n/locales/sv-SE/dashboard.json new file mode 100644 index 00000000..69c12fff --- /dev/null +++ b/src/i18n/locales/sv-SE/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Anslutna enheter", + "description": "Hantera dina anslutna Meshtastic-enheter.", + "connectionType_ble": "BLE", + "connectionType_serial": "Seriell kommunikation", + "connectionType_network": "Nätverk", + "noDevicesTitle": "Inga enheter anslutna", + "noDevicesDescription": "Anslut en ny enhet för att komma igång.", + "button_newConnection": "Ny anslutning" + } +} diff --git a/src/i18n/locales/sv-SE/deviceConfig.json b/src/i18n/locales/sv-SE/deviceConfig.json new file mode 100644 index 00000000..d582dff5 --- /dev/null +++ b/src/i18n/locales/sv-SE/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Konfiguration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Enhet", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Nätverk", + "tabPosition": "Plats", + "tabPower": "Ström", + "tabSecurity": "Säkerhet" + }, + "sidebar": { + "label": "Moduler" + }, + "device": { + "title": "Enhetsinställningar", + "description": "Inställningar för enheten", + "buttonPin": { + "description": "Stift för knapp", + "label": "Knapp-stift" + }, + "buzzerPin": { + "description": "Stift för summer", + "label": "Summer-stift" + }, + "disableTripleClick": { + "description": "Inaktivera trippeltryck", + "label": "Inaktivera trippeltryck" + }, + "doubleTapAsButtonPress": { + "description": "Behandla dubbeltryck som knapptryck", + "label": "Dubbeltryck som knapptryck" + }, + "ledHeartbeatDisabled": { + "description": "Inaktivera blinkande LED", + "label": "LED-puls inaktiverad" + }, + "nodeInfoBroadcastInterval": { + "description": "Hur ofta nod-info ska sändas", + "label": "Sändningsintervall för nod-info" + }, + "posixTimezone": { + "description": "POSIX-tidszonsträng för enheten", + "label": "POSIX-tidszon" + }, + "rebroadcastMode": { + "description": "Hur enheten hanterar återutsändning", + "label": "Återutsändningsläge" + }, + "role": { + "description": "Vilken roll enheten har på nätet", + "label": "Roll" + } + }, + "bluetooth": { + "title": "Bluetooth-inställningar", + "description": "Inställningar för Bluetooth-modulen", + "note": "OBS! Vissa enheter (ESP32) kan inte använda både Bluetooth och WiFi samtidigt.", + "enabled": { + "description": "Aktivera eller inaktivera Bluetooth", + "label": "Aktiverad" + }, + "pairingMode": { + "description": "Metod för parkoppling", + "label": "Parkopplingsläge" + }, + "pin": { + "description": "Pinkod för parkoppling", + "label": "Pinkod" + } + }, + "display": { + "description": "Inställningar för enhetens display", + "title": "Displayinställningar", + "headingBold": { + "description": "Visa rubriktexten i fetstil", + "label": "Fetstil för rubriktext" + }, + "carouselDelay": { + "description": "Tid mellan automatiskt byte av sida", + "label": "Karusellfördröjning" + }, + "compassNorthTop": { + "description": "Fixera norr till toppen av kompassen", + "label": "Kompassens norrläge" + }, + "displayMode": { + "description": "Variant på displaylayout", + "label": "Visningsläge" + }, + "displayUnits": { + "description": "Visa metriska eller Brittiska enheter", + "label": "Enheter" + }, + "flipScreen": { + "description": "Vänd displayen 180 grader", + "label": "Vänd skärmen" + }, + "gpsDisplayUnits": { + "description": "Koordinatformat för visning", + "label": "Koordinatformat" + }, + "oledType": { + "description": "Typ av OLED-skärm ansluten till enheten", + "label": "OLED-typ" + }, + "screenTimeout": { + "description": "Stäng av skärmen efter denna tid", + "label": "Tidsgräns för display" + }, + "twelveHourClock": { + "description": "Använd 12-timmarsformat", + "label": "12-timmars klocka" + }, + "wakeOnTapOrMotion": { + "description": "Väck enheten när rörelse upptäcks av enhetens accelerometer", + "label": "Vakna vid rörelse" + } + }, + "lora": { + "title": "Inställningar för nät", + "description": "Inställningar för LoRa-nätet", + "bandwidth": { + "description": "Kanalens bandbredd i MHz", + "label": "Bandbredd" + }, + "boostedRxGain": { + "description": "Ökad RX-förstärkning", + "label": "Ökad RX-förstärkning" + }, + "codingRate": { + "description": "Nämnaren för kodningshastighet", + "label": "Kodningshastighet" + }, + "frequencyOffset": { + "description": "Frekvensförskjutning för att korrigera vid kalibreringsfel i kristallen", + "label": "Frekvensförskjutning" + }, + "frequencySlot": { + "description": "LoRa-kanalnummer för frekvens", + "label": "Frekvens-slot" + }, + "hopLimit": { + "description": "Maximalt antal hopp", + "label": "Hoppgräns" + }, + "ignoreMqtt": { + "description": "Vidarebefordra inte MQTT-meddelanden över nätet", + "label": "Ignorera MQTT" + }, + "modemPreset": { + "description": "Modem-förinställningar som enheten använder", + "label": "Modem-förinställningar" + }, + "okToMqtt": { + "description": "När den är aktiverad anger denna konfiguration att användaren godkänner att paketet sänds till MQTT. Om avaktiverad uppmanas andra noder att inte vidarebefordra enhetens paket till MQTT", + "label": "OK till MQTT" + }, + "overrideDutyCycle": { + "description": "Ersätt gräns för driftsperiod", + "label": "Åsidosätt gräns för driftsperiod" + }, + "overrideFrequency": { + "description": "Åsidosätt frekvens", + "label": "Åsidosätt frekvens" + }, + "region": { + "description": "Anger regionen för din nod", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indikerar antalet chirps per symbol", + "label": "Spridningsfaktor" + }, + "transmitEnabled": { + "description": "Aktivera/inaktivera sändning (TX) från LoRa-radion", + "label": "Sändning aktiverad" + }, + "transmitPower": { + "description": "Max sändningseffekt", + "label": "Sändningseffekt" + }, + "usePreset": { + "description": "Använd en av de fördefinierade modeminställningarna", + "label": "Använd förinställning" + }, + "meshSettings": { + "description": "Inställningar för LoRa-nät", + "label": "Inställningar för nät" + }, + "waveformSettings": { + "description": "Inställningar för LoRa-vågformen", + "label": "Inställningar för vågform" + }, + "radioSettings": { + "label": "Radioinställningar", + "description": "Inställningar för LoRa-radio" + } + }, + "network": { + "title": "Wifi-konfiguration", + "description": "Konfiguration av WiFi-radio", + "note": "OBS! Vissa enheter (ESP32) kan inte använda både Bluetooth och WiFi samtidigt.", + "addressMode": { + "description": "Val för tilldelning av IP-adress", + "label": "Adress-läge" + }, + "dns": { + "description": "DNS-server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Aktivera eller inaktivera Ethernet-porten", + "label": "Aktiverad" + }, + "gateway": { + "description": "Standard-gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP-adress", + "label": "Ip-adress" + }, + "psk": { + "description": "Nätverkslösenord", + "label": "PSK" + }, + "ssid": { + "description": "Nätverksnamn", + "label": "SSID" + }, + "subnet": { + "description": "Subnätmask", + "label": "Subnät" + }, + "wifiEnabled": { + "description": "Aktivera eller inaktivera WiFi-radio", + "label": "Aktiverad" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP-server" + }, + "rsyslogServer": { + "label": "Rsyslog-server" + }, + "ethernetConfigSettings": { + "description": "Ethernet-portens konfiguration", + "label": "Ethernet-konfiguration" + }, + "ipConfigSettings": { + "description": "IP-konfiguration", + "label": "IP-konfiguration" + }, + "ntpConfigSettings": { + "description": "NTP-konfiguration", + "label": "NTP-konfiguration" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog-konfiguration", + "label": "Rsyslog-konfiguration" + }, + "udpConfigSettings": { + "description": "UDP över nät-konfiguration", + "label": "UDP-konfiguration" + } + }, + "position": { + "title": "Platsinställningar", + "description": "Inställningar för platsmodulen", + "broadcastInterval": { + "description": "Hur ofta din plats skickas ut över nätet", + "label": "Sändningsintervall" + }, + "enablePin": { + "description": "Stift för aktivering av GPS-modulen", + "label": "Stift för aktivering" + }, + "fixedPosition": { + "description": "Rapportera inte den inhämtade GPS-positionen, utan en manuellt angiven sådan", + "label": "Fast plats" + }, + "gpsMode": { + "description": "Konfigurera om enhetens GPS är aktiverad, inaktiverad eller saknas", + "label": "GPS-läge" + }, + "gpsUpdateInterval": { + "description": "Hur ofta en GPS-position ska inhämtas", + "label": "Intervall för GPS-uppdatering" + }, + "positionFlags": { + "description": "Valfria fält att inkludera vid sammansättning av positionsmeddelanden. Ju fler fält som väljs, desto större kommer meddelandet att bli. Längre meddelanden leder till högre sändningsutnyttnande och en högre risk för paketförlust.", + "label": "Positionsflaggor" + }, + "receivePin": { + "description": "RX-stift för GPS-modulen", + "label": "RX-stift" + }, + "smartPositionEnabled": { + "description": "Sänd bara positionsuppdatering när det har skett en tillräckligt stor förändring av positionen", + "label": "Aktivera smart position" + }, + "smartPositionMinDistance": { + "description": "Minsta avstånd (i meter) som enheten måste förflyttas innan en positionsuppdatering sänds", + "label": "Minimiavstånd för smart position" + }, + "smartPositionMinInterval": { + "description": "Minsta tidsintervall (i sekunder) som måste passera innan en positionsuppdatering skickas", + "label": "Minimiintervall för smart position" + }, + "transmitPin": { + "description": "TX-stift för GPS-modulen", + "label": "TX-stift" + }, + "intervalsSettings": { + "description": "Hur ofta enheten skickar positionsuppdateringar", + "label": "Intervall" + }, + "flags": { + "placeholder": "Välj positionsflaggor...", + "altitude": "Altitud", + "altitudeGeoidalSeparation": "Geoidhöjd", + "altitudeMsl": "Altitud är medelhavsnivå", + "dop": "Bidrag till osäkerhet i precision (DOP) PDOP används som standard", + "hdopVdop": "Om DOP är satt, använd HDOP / VDOP värden istället för PDOP", + "numSatellites": "Antal satelliter", + "sequenceNumber": "Sekvensnummer", + "timestamp": "Tidsstämpel", + "unset": "Ej inställd", + "vehicleHeading": "Rörelseriktning", + "vehicleSpeed": "Rörelsehastighet" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Används för att justera batterispänningsavläsning", + "label": "ADC faktor" + }, + "ina219Address": { + "description": "I2C-adress till INA219 batterimonitorn", + "label": "INA219-adress" + }, + "lightSleepDuration": { + "description": "Hur länge enheten kommer att vara i lätt strömsparläge", + "label": "Tid för lätt strömsparläge" + }, + "minimumWakeTime": { + "description": "Minsta tid enheten kommer att vara vaken efter att ha tagit emot ett paket", + "label": "Minsta vakna tid" + }, + "noConnectionBluetoothDisabled": { + "description": "Om enheten inte har en aktiv Bluetooth-anslutning inaktiveras Bluetooth-radion efter så här lång tid", + "label": "Bluetooth inaktiverad vid frånkoppling" + }, + "powerSavingEnabled": { + "description": "Välj om du strömmatar enheten från en lågströmkälla (sol) för att minimera strömförbrukningen så mycket som möjligt.", + "label": "Aktivera strömsparläge" + }, + "shutdownOnBatteryDelay": { + "description": "Automatisk avstängning av enheten efter att ha strömmatats från batteri så här lång tid, 0 för obestämd tid", + "label": "Fördröjd avstängning vid batteridrift" + }, + "superDeepSleepDuration": { + "description": "Hur länge enheten kommer att vara i djupt strömsparläge", + "label": "Tid för djupt strömsparläge" + }, + "powerConfigSettings": { + "description": "Inställningar för strömmodulen", + "label": "Ströminställningar" + }, + "sleepSettings": { + "description": "Strömsparlägesinställningar för strömmodulen", + "label": "Inställningar för strömsparläge" + } + }, + "security": { + "description": "Inställningar för säkerhet", + "title": "Säkerhetsinställningar", + "button_backupKey": "Säkerhetskopiera nyckel", + "adminChannelEnabled": { + "description": "Tillåt inkommande styrning via den förlegade, osäkra, administrationskanalen", + "label": "Tillåt förlegad administration" + }, + "enableDebugLogApi": { + "description": "Skriv felsökningsloggar över seriell kommunikation samt visa och exportera positions-rensade loggar över Bluetooth", + "label": "Aktivera API för felsökningslogg" + }, + "managed": { + "description": "Om aktiverad, kan enhetens konfigurationsalternativ bara ändras på distans av en fjärradministratörsnod via administratörsmeddelanden. Aktivera inte detta alternativ om inte minst en lämplig fjärradministratörsnod har konfigurerats och den publika nyckeln matats in i något av fälten ovan.", + "label": "Fjärrhanterad" + }, + "privateKey": { + "description": "Används för att skapa en delad nyckel med en fjärrnod", + "label": "Privat nyckel" + }, + "publicKey": { + "description": "Sänds ut till andra noder på nätet för att de ska kunna beräkna en delad hemlig nyckel", + "label": "Publik nyckel" + }, + "primaryAdminKey": { + "description": "Den primära publika nyckeln hos en fjärradministratörsnod auktoriserad att skicka administratörsmeddelanden till den här noden", + "label": "Primär administratörsnyckel" + }, + "secondaryAdminKey": { + "description": "Den sekundära publika nyckeln hos en fjärradministratörsnod auktoriserad att skicka administratörsmeddelanden till den här noden", + "label": "Sekundär administratörsnyckel" + }, + "serialOutputEnabled": { + "description": "Seriell kommunikation över Stream API", + "label": "Seriell kommunikation aktiverad" + }, + "tertiaryAdminKey": { + "description": "Den tertiära publika nyckeln hos en fjärradministratörsnod auktoriserad att skicka administratörsmeddelanden till den här noden", + "label": "Tertiär administratörsnyckel" + }, + "adminSettings": { + "description": "Inställningar för fjärradministration", + "label": "Fjärradministrationsinställningar" + }, + "loggingSettings": { + "description": "Inställningar för loggning", + "label": "Loggningsinställningar" + } + } +} diff --git a/src/i18n/locales/sv-SE/dialog.json b/src/i18n/locales/sv-SE/dialog.json new file mode 100644 index 00000000..1a256bb5 --- /dev/null +++ b/src/i18n/locales/sv-SE/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "Den här åtgärden kommer att rensa all meddelandehistorik. Detta kan inte ångras. Är du säker på att du vill fortsätta?", + "title": "Rensa alla meddelanden" + }, + "deviceName": { + "description": "Enheten kommer att starta om när inställningarna har sparats.", + "longName": "Långt namn", + "shortName": "Kort namn", + "title": "Ändra enhetens namn" + }, + "import": { + "description": "Den aktuella LoRa konfigurationen kommer att skrivas över.", + "error": { + "invalidUrl": "Ogiltig Meshtastic URL" + }, + "channelPrefix": "Kanal: ", + "channelSetUrl": "Kanalinställning/QR-kod URL", + "channels": "Kanaler:", + "usePreset": "Använd förinställning?", + "title": "Importera kanaluppsättning" + }, + "locationResponse": { + "altitude": "Höjd:", + "coordinates": "Koordinater: ", + "title": "Plats: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Förnya nyckel?", + "description": "Är du säker på att du vill förnya den fördelade nyckeln?", + "regenerate": "Förnya" + }, + "newDeviceDialog": { + "title": "Anslut ny enhet", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seriell kommunikation", + "useHttps": "Använd HTTPS", + "connecting": "Ansluter...", + "connect": "Anslut", + "connectionFailedAlert": { + "title": "Anslutningen misslyckades", + "descriptionPrefix": "Kunde inte ansluta till enheten. ", + "httpsHint": "Om du använder HTTPS kan du behöva godkänna ett självsignerat certifikat först. ", + "openLinkPrefix": "Vänligen öppna ", + "openLinkSuffix": " i en ny flik", + "acceptTlsWarningSuffix": ", acceptera eventuella TLS-varningar om du uppmanas och försök igen", + "learnMoreLink": "Läs mer" + }, + "httpConnection": { + "label": "IP-adress/värdnamn", + "placeholder": "000.000.000.000 / meshtastic.lokal" + }, + "serialConnection": { + "noDevicesPaired": "Inga enheter parkopplade ännu.", + "newDeviceButton": "Ny enhet", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "Inga enheter parkopplade ännu.", + "newDeviceButton": "Ny enhet" + }, + "validation": { + "requiresFeatures": "Den här anslutningstypen kräver <0>. Använd en webbläsare som stöds, till exempel Chrome eller Edge.", + "requiresSecureContext": "Denna applikation kräver en <0>säker kontext. Anslut med HTTPS eller localhost.", + "additionallyRequiresSecureContext": "Dessutom kräver den ett <0>säker kontext. Vänligen anslut med HTTPS eller localhost." + } + }, + "nodeDetails": { + "message": "Meddelande", + "requestPosition": "Begär plats", + "traceRoute": "Spåra rutt", + "airTxUtilization": "Sändningsutnyttjande", + "allRawMetrics": "All oformaterad data", + "batteryLevel": "Batterinivå", + "channelUtilization": "Kanalutnyttjande", + "details": "Detaljer:", + "deviceMetrics": "Enhetens mätvärden:", + "hardware": "Hårdvara: ", + "lastHeard": "Senast hörd: ", + "nodeHexPrefix": "Nod-hex: !", + "nodeNumber": "Nodnummer: ", + "position": "Plats:", + "role": "Roll: ", + "uptime": "Drifttid: ", + "voltage": "Spänning", + "title": "Nodinformation för {{identifier}}", + "ignoreNode": "Ignorera nod", + "removeNode": "Ta bort nod", + "unignoreNode": "Ta bort favoritmarkering" + }, + "pkiBackup": { + "description": "Vi rekommenderar att du säkerhetskopierar dina nycklar regelbundet. Vill du säkerhetskopiera nu?", + "loseKeysWarning": "Om du förlorar dina nycklar måste du återställa din enhet.", + "secureBackup": "Det är viktigt att säkerhetskopiera dina publika och privata nycklar och förvara din säkerhetskopia säkert.", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Privat nyckel:", + "publicKey": "Publik nyckel:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Säkerhetskopiera nycklar" + }, + "pkiRegenerate": { + "description": "Är du säker på att du vill förnya nyckelpar?", + "title": "Förnya nyckelpar" + }, + "qr": { + "addChannels": "Lägg till kanaler", + "replaceChannels": "Ersätt kanaler", + "description": "Den aktuella LoRa-konfigurationen kommer också att delas.", + "sharableUrl": "Delbar URL", + "title": "Generera QR-kod" + }, + "rebootOta": { + "title": "Schemalägg omstart", + "description": "Starta om den anslutna noden till OTA- (Over-the-Air) läge efter en fördröjning.", + "enterDelay": "Ange fördröjning (sekunder)", + "scheduled": "Omstart har schemalagts" + }, + "reboot": { + "title": "Schemalägg omstart", + "description": "Starta om den anslutna noden efter x minuter." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "Detta kommer att ta bort noden från enheten och begära nya nycklar.", + "keyMismatchReasonSuffix": ". Detta beror på att fjärrnodens nuvarande publika nyckel inte matchar den tidigare lagrade nyckeln för den här noden.", + "unableToSendDmPrefix": "Din nod kan inte skicka ett direkt meddelande till noden: " + }, + "acceptNewKeys": "Godkänn nya nycklar", + "title": "Nycklarna matchar inte - {{identifier}}" + }, + "removeNode": { + "description": "Är du säker på att du vill ta bort den här noden?", + "title": "Ta bort noden?" + }, + "shutdown": { + "title": "Schemalägg avstängning", + "description": "Stäng av den anslutna noden efter x minuter." + }, + "traceRoute": { + "routeToDestination": "Rutt till destination:", + "routeBack": "Rutt tillbaka:" + }, + "tracerouteResponse": { + "title": "Spåra rutt: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Ja, jag vet vad jag gör", + "conjunction": " och blogginlägget om ", + "postamble": " och förstår konsekvenserna av att ändra roll.", + "preamble": "Jag har läst ", + "choosingRightDeviceRole": "Att välja rätt enhetsroll", + "deviceRoleDocumentation": "Dokumentation för enhetsroll", + "title": "Är du säker?" + } +} diff --git a/src/i18n/locales/sv-SE/messages.json b/src/i18n/locales/sv-SE/messages.json new file mode 100644 index 00000000..ae25ae8d --- /dev/null +++ b/src/i18n/locales/sv-SE/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Meddelanden: {{chatName}}" + }, + "emptyState": { + "title": "Välj en chatt", + "text": "Det finns inga meddelanden ännu." + }, + "selectChatPrompt": { + "text": "Välj en kanal eller nod för att börja chatta." + }, + "sendMessage": { + "placeholder": "Skriv ditt meddelande här...", + "sendButton": "Skicka" + }, + "actionsMenu": { + "addReactionLabel": "Lägg till reaktion", + "replyLabel": "Svara" + }, + "item": { + "status": { + "delivered": { + "label": "Meddelandet har levererats", + "displayText": "Meddelandet har levererats" + }, + "failed": { + "label": "Meddelandeleverans misslyckades", + "displayText": "Leverans misslyckades" + }, + "unknown": { + "label": "Okänd meddelandestatus", + "displayText": "Okänd status" + }, + "waiting": { + "ariaLabel": "Skickar meddelande", + "displayText": "Väntar på leverans" + } + } + } +} diff --git a/src/i18n/locales/sv-SE/moduleConfig.json b/src/i18n/locales/sv-SE/moduleConfig.json new file mode 100644 index 00000000..075451c9 --- /dev/null +++ b/src/i18n/locales/sv-SE/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Omgivande belysning", + "tabAudio": "Ljud", + "tabCannedMessage": "Fördefinierade meddelanden", + "tabDetectionSensor": "Detekteringssensor", + "tabExternalNotification": "Extern avisering", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Granninformation", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Räckvidd", + "tabSerial": "Seriell kommunikation", + "tabStoreAndForward": "Lagra & vidarebefodra", + "tabTelemetry": "Telemetri" + }, + "ambientLighting": { + "title": "Inställningar för omgivande belysning", + "description": "Inställningar för modulen för omgivande belysning", + "ledState": { + "label": "LED-läge", + "description": "Anger om lysdioden ska vara på eller av" + }, + "current": { + "label": "Ström", + "description": "Ställer in strömmen för LED-utgången. Standardvärdet är 10" + }, + "red": { + "label": "Rött", + "description": "Anger nivån för den röda lysdioden. Värdena är 0-255" + }, + "green": { + "label": "Grönt", + "description": "Anger nivån för den gröna lysdioden. Värdena är 0-255" + }, + "blue": { + "label": "Blått", + "description": "Anger nivån för den blåa lysdioden. Värdena är 0-255" + } + }, + "audio": { + "title": "Ljudinställningar", + "description": "Inställningar för ljudmodulen", + "codec2Enabled": { + "label": "Codec 2 aktiverad", + "description": "Aktivera Codec 2-ljudkodning" + }, + "pttPin": { + "label": "PTT-stift", + "description": "GPIO-stift för PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate att använda för ljudkodning" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO-stift att använda för i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO-stift att använda för i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO-stift att använda för i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO-stift att använda för i2S SCK" + } + }, + "cannedMessage": { + "title": "Inställningar för fördefinierade meddelanden", + "description": "Inställningar för modulen för fördefinierade meddelanden", + "moduleEnabled": { + "label": "Modul aktiverad", + "description": "Aktivera fördefinierade meddelanden" + }, + "rotary1Enabled": { + "label": "Vridomkopplare #1 aktiverad", + "description": "Aktivera vridomkopplare" + }, + "inputbrokerPinA": { + "label": "Vridomkopplarstift A", + "description": "GPIO-stift (1-39) för vridomkopplarens A-stift" + }, + "inputbrokerPinB": { + "label": "Vridomkopplarstift B", + "description": "GPIO-stift (1-39) för vridomkopplarens B-stift" + }, + "inputbrokerPinPress": { + "label": "Vridomkopplarens knappstift", + "description": "GPIO-stift (1-39) för vridomkopplarens knapp-stift" + }, + "inputbrokerEventCw": { + "label": "Medurs inmatningshändelse", + "description": "Välj inmatningshändelse." + }, + "inputbrokerEventCcw": { + "label": "Moturs inmatningshändelse", + "description": "Välj inmatningshändelse." + }, + "inputbrokerEventPress": { + "label": "Inmatningshändelse för tryck", + "description": "Välj inmatningshändelse." + }, + "updown1Enabled": { + "label": "Upp/ned aktiverad", + "description": "Aktivera upp/ner vridomkopplaren" + }, + "allowInputSource": { + "label": "Tillåten inmatningskälla", + "description": "Välj från: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Skicka klocka", + "description": "Skickar det speciella klock-tecknet med varje meddelande" + } + }, + "detectionSensor": { + "title": "Inställningar för detekteringssensor", + "description": "Inställningar för detekteringssensor-modulen", + "enabled": { + "label": "Aktiverad", + "description": "Aktivera eller inaktivera detekteringssensor-modulen" + }, + "minimumBroadcastSecs": { + "label": "Minsta sändningsintervall", + "description": "Tidsintervall i sekunder hur ofta vi kan skicka ett meddelande till nätet när en tillståndsändring upptäckts" + }, + "stateBroadcastSecs": { + "label": "Högsta sändningsintervall", + "description": "Tidsintervall i sekunder hur ofta vi ska skicka ett meddelande till nätet med nuvarande tillstånd oavsett eventuella förändringar" + }, + "sendBell": { + "label": "Skicka klocka", + "description": "Skicka det speciella klock-tecknet med meddelandet" + }, + "name": { + "label": "Visningsnamn", + "description": "Används för att formatera meddelandet som skickas till nätet, max 20 tecken" + }, + "monitorPin": { + "label": "Stift att övervaka", + "description": "GPIO-stiftet att övervaka för tillståndsändringar" + }, + "detectionTriggerType": { + "label": "Typ för utlösande händelse", + "description": "Typ av utlösande händelse som ska användas" + }, + "usePullup": { + "label": "Använd Pullup", + "description": "Huruvida INPUT_PULLUP-läget ska användas för GPIO-stiftet " + } + }, + "externalNotification": { + "title": "Inställningar för extern avisering", + "description": "Konfigurera modulen för extern avisering", + "enabled": { + "label": "Modul aktiverad", + "description": "Aktivera extern avisering" + }, + "outputMs": { + "label": "Längd", + "description": "Hur länge ska notifikationen vara aktiverad" + }, + "output": { + "label": "Utgång", + "description": "GPIO-stift för utgång" + }, + "outputVibra": { + "label": "Vibrationsutgång", + "description": "GPIO-stift för vibrationsutgång" + }, + "outputBuzzer": { + "label": "Summerutgång", + "description": "GPIO-stift för summerutgång" + }, + "active": { + "label": "Aktiv", + "description": "Aktiv" + }, + "alertMessage": { + "label": "Meddelande-utgång", + "description": "Aktivera utgång när nytt meddelande tas emot" + }, + "alertMessageVibra": { + "label": "Meddelande-vibrationsutgång", + "description": "Aktivera vibrationsutgång när nytt meddelande tas emot" + }, + "alertMessageBuzzer": { + "label": "Meddelande-summer", + "description": "Aktivera summerutgång när nytt meddelande tas emot" + }, + "alertBell": { + "label": "Klock-tecken-utgång", + "description": "Aktivera utgång när ett inkommande meddelande innehåller det speciella klock-tecknet?" + }, + "alertBellVibra": { + "label": "Klock-tecken-vibration", + "description": "Aktivera vibrationsutgång när ett inkommande meddelande innehåller det speciella klock-tecknet" + }, + "alertBellBuzzer": { + "label": "Klock-tecken-summer", + "description": "Aktivera summerutgång när ett inkommande meddelande innehåller det speciella klock-tecknet" + }, + "usePwm": { + "label": "Använd PWM", + "description": "Använd pulsbreddsmodulering (PWM)" + }, + "nagTimeout": { + "label": "Time-out för påminnelse", + "description": "Time-out för påminnelse" + }, + "useI2sAsBuzzer": { + "label": "Använd I²S-stift som summer", + "description": "Ange I²S-stift som summerutgång" + } + }, + "mqtt": { + "title": "MQTT Inställningar", + "description": "Inställningar för MQTT-modulen", + "enabled": { + "label": "Aktiverad", + "description": "Aktivera eller inaktivera MQTT" + }, + "address": { + "label": "MQTT-serveradress", + "description": "MQTT-serveradress att använda för standard/anpassade servrar" + }, + "username": { + "label": "MQTT-användarnamn", + "description": "MQTT-användarnamn att använda för standard/anpassade servrar" + }, + "password": { + "label": "MQTT-lösenord", + "description": "MQTT-lösenord att använda för standard/anpassade servrar" + }, + "encryptionEnabled": { + "label": "Aktivera kryptering ", + "description": "Aktivera eller inaktivera MQTT-kryptering. OBS: Alla meddelanden skickas okrypterade till MQTT-servern om det här alternativet inte är aktiverat, även när dina kanaler med aktiverad MQTT-upplänk har krypteringsnycklar. Detta inkluderar positionsdata." + }, + "jsonEnabled": { + "label": "JSON aktiverat", + "description": "Om du vill skicka/ta emot JSON-paket på MQTT" + }, + "tlsEnabled": { + "label": "TLS aktiverat", + "description": "Aktivera eller inaktivera TLS" + }, + "root": { + "label": "Rotämne (root topic)", + "description": "MQTT rotämne (root topic) att använda för standard/anpassade servrar " + }, + "proxyToClientEnabled": { + "label": "MQTT-klientproxy aktiverad", + "description": "Utnyttja nätverksanslutningen för att vidarebefodra MQTT-meddelanden till klienten." + }, + "mapReportingEnabled": { + "label": "Kartrapportering aktiverad", + "description": "Din nod kommer periodvis skicka ett okrypterat paket till den konfigurerade MQTT-servern som inkluderar id, kort och långt namn, ungefärlig plats, hardvarumodell, enhetsroll, mjukvaru-version, LoRa-region, modeminställning och den primära kanalens namn." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Intervall för kartrapportering", + "description": "Intervall i sekunder för hur ofta kartrapportering ska ske" + }, + "positionPrecision": { + "label": "Ungefärlig plats", + "description": "Den delade platsen kommer att avrundas till denna noggrannhet", + "options": { + "metric_km23": "Inom 23 km", + "metric_km12": "Inom 12 km", + "metric_km5_8": "Inom 5,8 km", + "metric_km2_9": "Inom 2,9 km", + "metric_km1_5": "Inom 1,5 km", + "metric_m700": "Inom 700 m", + "metric_m350": "Inom 350 m", + "metric_m200": "Inom 200 m", + "metric_m90": "Inom 90 meter", + "metric_m50": "inom 50 m", + "imperial_mi15": "Inom 15 engelska mil", + "imperial_mi7_3": "Inom 7,3 engelska mil", + "imperial_mi3_6": "Inom 3,6 engelska mil", + "imperial_mi1_8": "Inom 1,8 engelska mil", + "imperial_mi0_9": "Inom 0,9 engelska mil", + "imperial_mi0_5": "Inom 0,5 engelska mil", + "imperial_mi0_2": "Inom 0,2 engelska mil", + "imperial_ft600": "Inom 600 fot", + "imperial_ft300": "Inom 300 fot", + "imperial_ft150": "Inom 150 fot" + } + } + } + }, + "neighborInfo": { + "title": "Inställningar för granninformation", + "description": "Inställningar för granninformation-modulen", + "enabled": { + "label": "Aktiverad", + "description": "Aktivera eller inaktivera granninformation-modulen" + }, + "updateInterval": { + "label": "Uppdateringsintervall", + "description": "Intervall i sekunder av hur ofta granninformation ska försöka skickas till nätet" + } + }, + "paxcounter": { + "title": "Inställningar för Paxcounter", + "description": "Inställningar för Paxcounter-modulen", + "enabled": { + "label": "Modul aktiverad", + "description": "Aktivera Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Uppdateringsintervall (sekunder)", + "description": "Hur lång tid mellan paxcounter paket skickas" + }, + "wifiThreshold": { + "label": "Tröskelvärde för WiFi RSSI ", + "description": "På vilken WiFi RSSI-nivå ska räknaren öka. Standardvärdet är -80." + }, + "bleThreshold": { + "label": "Tröskelvärde för Bluetooth RSSI ", + "description": "På vilken Bluetooth RSSI-nivå ska räknaren öka. Standardvärdet är -80." + } + }, + "rangeTest": { + "title": "Inställningar för räckviddstest", + "description": "Inställningar för räckviddstest-modulen", + "enabled": { + "label": "Modul aktiverad", + "description": "Aktivera räckviddstest" + }, + "sender": { + "label": "Meddelandeintervall", + "description": "Hur lång tid mellan utsändning av testpaket" + }, + "save": { + "label": "Spara CSV till lagring", + "description": "Spara CSV till enhetens egna flashminne. Endast tillgängligt på ESP32-enheter." + } + }, + "serial": { + "title": "Inställningar för seriell kommunikation", + "description": "Inställningar för den seriella modulen", + "enabled": { + "label": "Modul aktiverad", + "description": "Aktivera seriell utmatning" + }, + "echo": { + "label": "Eko", + "description": "Alla paket du skickar kommer att upprepas tillbaka till din enhet" + }, + "rxd": { + "label": "Stift för mottagning", + "description": "Ställ in GPIO-stift till det RXD-stift du har konfigurerat." + }, + "txd": { + "label": "Stift för sändning", + "description": "Ställ in GPIO-stift till det TXD-stift du har konfigurerat." + }, + "baud": { + "label": "Hastighet", + "description": "Den seriella kommunikationens hastighet" + }, + "timeout": { + "label": "Timeout", + "description": "Tid att vänta innan ditt paket betraktas som \"klart\"." + }, + "mode": { + "label": "Typ", + "description": "Välj typ av paket" + }, + "overrideConsoleSerialPort": { + "label": "Åsidosätt konsolens serieport", + "description": "Om du har en seriell port ansluten till konsolen kommer detta att ersätta den." + } + }, + "storeForward": { + "title": "Inställningar för lagra & vidarebefodra", + "description": "Inställningar för lagra & vidarebefodra-modulen", + "enabled": { + "label": "Modul aktiverad", + "description": "Aktivera lagra & vidarebefodra-modulen" + }, + "heartbeat": { + "label": "Puls aktiverad", + "description": "Aktivera sändning av lagra & vidarebefodra-puls " + }, + "records": { + "label": "Antal poster", + "description": "Antal poster att lagra" + }, + "historyReturnMax": { + "label": "Maxstorlek för historik", + "description": "Maximalt antal poster att returnera" + }, + "historyReturnWindow": { + "label": "Returfönstrets storlek för historik", + "description": "Maximalt antal poster att returnera" + } + }, + "telemetry": { + "title": "Inställningar för telemetri", + "description": "Inställningar för telemetrimodulen", + "deviceUpdateInterval": { + "label": "Enhetens mätvärden", + "description": "Uppdateringsintervall för enhetsdata" + }, + "environmentUpdateInterval": { + "label": "Uppdateringsintervall för miljömätningar", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Modul aktiverad", + "description": "Aktivera miljötelemetri" + }, + "environmentScreenEnabled": { + "label": "Visa på display", + "description": "Visa telemetri-värden på OLED-displayen" + }, + "environmentDisplayFahrenheit": { + "label": "Visa Fahrenheit", + "description": "Visa temperatur i Fahrenheit" + }, + "airQualityEnabled": { + "label": "Aktivera luftkvalitet ", + "description": "Aktivera telemetri för luftkvalitet" + }, + "airQualityInterval": { + "label": "Intervall för uppdatering av luftkvalitet", + "description": "Hur ofta att skicka data om luftkvalitet över nätet" + }, + "powerMeasurementEnabled": { + "label": "Effektmätning aktiverad", + "description": "Aktivera telemetri för effektmätning" + }, + "powerUpdateInterval": { + "label": "Intervall för effektuppdatering", + "description": "Hur ofta ska effektdata skickas över nätet" + }, + "powerScreenEnabled": { + "label": "Aktivera strömskärm", + "description": "Aktivera skärmen för strömdata" + } + } +} diff --git a/src/i18n/locales/sv-SE/nodes.json b/src/i18n/locales/sv-SE/nodes.json new file mode 100644 index 00000000..57a5bafa --- /dev/null +++ b/src/i18n/locales/sv-SE/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Publik nyckel aktiverad" + }, + "noPublicKey": { + "label": "Publik nyckel saknas" + }, + "directMessage": { + "label": "Direktmeddelande {{shortName}}" + }, + "favorite": { + "label": "Favorit" + }, + "notFavorite": { + "label": "Inte en favorit" + }, + "status": { + "heard": "Hörd", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Höjd" + }, + "channelUtil": { + "label": "Kanalutnyttjande" + }, + "airtimeUtil": { + "label": "Sändningstidsutnyttjande" + } + }, + "nodesTable": { + "headings": { + "longName": "Långt namn", + "connection": "Anslutning", + "lastHeard": "Senast hörd", + "encryption": "Kryptering", + "model": "Modell", + "macAddress": "MAC-adress" + }, + "connectionStatus": { + "direct": "Direkt", + "away": "bort", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Aldrig" + } + } +} diff --git a/src/i18n/locales/sv-SE/ui.json b/src/i18n/locales/sv-SE/ui.json new file mode 100644 index 00000000..50044c1f --- /dev/null +++ b/src/i18n/locales/sv-SE/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigering", + "messages": "Meddelanden", + "map": "Karta", + "config": "Inställningar", + "radioConfig": "Radioinställningar", + "moduleConfig": "Modulinställningar", + "channels": "Kanaler", + "nodes": "Noder" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic logotyp" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Öppna sidopanel", + "close": "Stäng sidopanel" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volt", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Kompileringsdatum: {{date}}" + }, + "deviceName": { + "title": "Enhetsnamn", + "changeName": "Ändra enhetens namn", + "placeholder": "Ange enhetsnamn" + }, + "editDeviceName": "Redigera enhetsnamn" + } + }, + "batteryStatus": { + "charging": "{{level}}%, laddar", + "pluggedIn": "Ansluten", + "title": "Batteri" + }, + "search": { + "nodes": "Sök noder...", + "channels": "Sök kanaler...", + "commandPalette": "Sök kommandon..." + }, + "toast": { + "positionRequestSent": { + "title": "Platsbegäran skickad." + }, + "requestingPosition": { + "title": "Begär plats, var god vänta..." + }, + "sendingTraceroute": { + "title": "Skickar Traceroute (spåra rutt), vänligen vänta..." + }, + "tracerouteSent": { + "title": "Traceroute (spåra rutt) skickat.." + }, + "savedChannel": { + "title": "Sparat kanal: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chatten använder PKI-kryptering." + }, + "pskEncryption": { + "title": "Chatten använder PSK-kryptering." + } + }, + "configSaveError": { + "title": "Kunde inte spara inställningarna", + "description": "Ett fel inträffade när inställningarna sparades." + }, + "validationError": { + "title": "Det förekommer inställningsfel", + "description": "Vänligen åtgärda felen i inställningarna innan du sparar." + }, + "saveSuccess": { + "title": "Sparar inställningarna", + "description": "Ändrignarna av {{case}}-inställningarna har sparats." + } + }, + "notifications": { + "copied": { + "label": "Kopierat!" + }, + "copyToClipboard": { + "label": "Kopiera till Urklipp" + }, + "hidePassword": { + "label": "Dölj lösenord" + }, + "showPassword": { + "label": "Visa lösenord" + }, + "deliveryStatus": { + "delivered": "Levererad", + "failed": "Leverans misslyckades", + "waiting": "Väntar", + "unknown": "Okänd" + } + }, + "general": { + "label": "Allmänt" + }, + "hardware": { + "label": "Hårdvara" + }, + "metrics": { + "label": "Telemetri" + }, + "role": { + "label": "Roll" + }, + "filter": { + "label": "Filter" + }, + "clearInput": { + "label": "Rensa inmatning" + }, + "resetFilters": { + "label": "Återställ filter" + }, + "nodeName": { + "label": "Nodnamn/nummer", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Sändningstidsutnyttjande (%)" + }, + "batteryLevel": { + "label": "Batterinivå (%)", + "labelText": "Batterinivå (%): {{value}}" + }, + "batteryVoltage": { + "label": "Batterispänning (V)", + "title": "Spänning" + }, + "channelUtilization": { + "label": "Kanalutnyttjande (%)" + }, + "hops": { + "direct": "Direkt", + "label": "Antal hopp", + "text": "Antal hopp: {{value}}" + }, + "lastHeard": { + "label": "Senast hörd", + "labelText": "Senast hörd: {{value}}", + "nowLabel": "Nu" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favoriter" + }, + "hide": { + "label": "Dölj" + }, + "showOnly": { + "label": "Visa endast" + }, + "viaMqtt": { + "label": "Ansluten via MQTT" + }, + "language": { + "label": "Språk", + "changeLanguage": "Ändra språk" + }, + "theme": { + "dark": "Mörkt", + "light": "Ljust", + "system": "Automatisk", + "changeTheme": "Ändra färgschema" + }, + "errorPage": { + "title": "Det här är lite pinsamt...", + "description1": "Vi är verkligen ledsna men ett fel inträffade i webbklienten som fick den att krascha.
Detta var inte meningen, men vi arbetar hårt för att åtgärda det.", + "description2": "Det bästa sättet att förhindra att detta händer igen för dig eller någon annan är att rapportera problemet till oss.", + "reportInstructions": "Vänligen inkludera följande information i din rapport:", + "reportSteps": { + "step1": "Vad du gjorde när felet inträffade", + "step2": "Vad du förväntade dig skulle hända", + "step3": "Vad som faktiskt hände", + "step4": "All annan relevant information" + }, + "reportLink": "Du kan rapportera problemet på vår <0>GitHub", + "dashboardLink": "Återvänd till <0>start", + "detailsSummary": "Detaljer om felet", + "errorMessageLabel": "Felmeddelande:", + "stackTraceLabel": "Stackspårning:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Drivs av <0>▲ Vercel | Meshtastic® är ett registrerat varumärke som tillhör Meshtastic LLC. | <1>Juridisk information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/tr-TR/channels.json b/src/i18n/locales/tr-TR/channels.json new file mode 100644 index 00000000..74fe0384 --- /dev/null +++ b/src/i18n/locales/tr-TR/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanallar", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Birincil", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Kanal Ayarları", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Rol", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "İsmi", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/tr-TR/commandPalette.json b/src/i18n/locales/tr-TR/commandPalette.json new file mode 100644 index 00000000..cc73c62a --- /dev/null +++ b/src/i18n/locales/tr-TR/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Mesajlar", + "map": "Harita", + "config": "Config", + "channels": "Kanallar", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "İçeri aktar", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Hata Ayıklama", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/tr-TR/common.json b/src/i18n/locales/tr-TR/common.json new file mode 100644 index 00000000..52768d33 --- /dev/null +++ b/src/i18n/locales/tr-TR/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Uygula", + "backupKey": "Backup Key", + "cancel": "İptal", + "clearMessages": "Clear Messages", + "close": "Kapat", + "confirm": "Confirm", + "delete": "Sil", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "İçeri aktar", + "message": "Mesaj", + "now": "Now", + "ok": "Tamam", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Kaldır", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Sıfırla", + "save": "Kaydet", + "scanQr": "QR Kodu Tara", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/tr-TR/dashboard.json b/src/i18n/locales/tr-TR/dashboard.json new file mode 100644 index 00000000..003f8732 --- /dev/null +++ b/src/i18n/locales/tr-TR/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Seri", + "connectionType_network": "Ağ", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/tr-TR/deviceConfig.json b/src/i18n/locales/tr-TR/deviceConfig.json new file mode 100644 index 00000000..2f21752b --- /dev/null +++ b/src/i18n/locales/tr-TR/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Cihaz", + "tabDisplay": "Ekran", + "tabLora": "LoRa", + "tabNetwork": "Ağ", + "tabPosition": "Konum", + "tabPower": "Güç", + "tabSecurity": "Güvenlik" + }, + "sidebar": { + "label": "Modüller" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Zaman Dilimi" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Rol" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Eşleştirme Modu" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bant genişliği" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "MQTT'yi Yoksay" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "MQTT'ye Tamam" + }, + "overrideDutyCycle": { + "description": "Görev Döngüsünü Geçersiz Kıl", + "label": "Görev Döngüsünü Geçersiz Kıl" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Bölge" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Ağ geçidi" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Alt ağ" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Ayarları" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Zaman Damgası", + "unset": "Ayarlanmamış", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Güç tasarrufu modunu etkinleştir" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Güç Ayarı" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Özel Anahtar" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Genel Anahtar" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/tr-TR/dialog.json b/src/i18n/locales/tr-TR/dialog.json new file mode 100644 index 00000000..2419a70d --- /dev/null +++ b/src/i18n/locales/tr-TR/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seri", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Bağlan", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Mesaj", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltaj", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Emin misiniz?" + } +} diff --git a/src/i18n/locales/tr-TR/messages.json b/src/i18n/locales/tr-TR/messages.json new file mode 100644 index 00000000..ebfacb84 --- /dev/null +++ b/src/i18n/locales/tr-TR/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Gönder" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/tr-TR/moduleConfig.json b/src/i18n/locales/tr-TR/moduleConfig.json new file mode 100644 index 00000000..3ba00a84 --- /dev/null +++ b/src/i18n/locales/tr-TR/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ortam Işıklandırması", + "tabAudio": "Ses", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Algılama Sensörü", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Komşu Bilgisi", + "tabPaxcounter": "Pax sayacı", + "tabRangeTest": "Mesafe Testi", + "tabSerial": "Seri", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetri" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Akım", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Kırmızı", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Yeşil", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Mavi", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Ana konu", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Zaman Aşımı", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Kayıt sayısı", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "Geçmiş geri dönüş maksimum", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "Geçmiş geri dönüş penceresi", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Cihaz metrikleri güncelleme aralığı (saniye)" + }, + "environmentUpdateInterval": { + "label": "Çevre metrikleri güncelleme aralığı (saniye)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/tr-TR/nodes.json b/src/i18n/locales/tr-TR/nodes.json new file mode 100644 index 00000000..38af1597 --- /dev/null +++ b/src/i18n/locales/tr-TR/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favori" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Doğrudan", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/tr-TR/ui.json b/src/i18n/locales/tr-TR/ui.json new file mode 100644 index 00000000..6b59b9ab --- /dev/null +++ b/src/i18n/locales/tr-TR/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Mesajlar", + "map": "Harita", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Kanallar", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Yazılım", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Pil" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Şifreyi gizle" + }, + "showPassword": { + "label": "Şifreyi göster" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Donanım" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Rol" + }, + "filter": { + "label": "Filtre" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltaj" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Doğrudan", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Son duyulma", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Dil", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Koyu", + "light": "Açık", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/uk-UA/channels.json b/src/i18n/locales/uk-UA/channels.json new file mode 100644 index 00000000..5e74e00a --- /dev/null +++ b/src/i18n/locales/uk-UA/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Channels", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Channel Settings", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Role", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Ім'я", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/uk-UA/commandPalette.json b/src/i18n/locales/uk-UA/commandPalette.json new file mode 100644 index 00000000..42dac9c8 --- /dev/null +++ b/src/i18n/locales/uk-UA/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Повідомлення", + "map": "Мапа", + "config": "Config", + "channels": "Channels", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/uk-UA/common.json b/src/i18n/locales/uk-UA/common.json new file mode 100644 index 00000000..2ad86595 --- /dev/null +++ b/src/i18n/locales/uk-UA/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "Застосувати", + "backupKey": "Backup Key", + "cancel": "Скасувати", + "clearMessages": "Clear Messages", + "close": "Закрити", + "confirm": "Confirm", + "delete": "Видалити", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Повідомлення", + "now": "Now", + "ok": "Гаразд", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Видалити", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Скинути", + "save": "Зберегти", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/uk-UA/dashboard.json b/src/i18n/locales/uk-UA/dashboard.json new file mode 100644 index 00000000..3a3cd869 --- /dev/null +++ b/src/i18n/locales/uk-UA/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Serial", + "connectionType_network": "Network", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/uk-UA/deviceConfig.json b/src/i18n/locales/uk-UA/deviceConfig.json new file mode 100644 index 00000000..a5619c72 --- /dev/null +++ b/src/i18n/locales/uk-UA/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Device", + "tabDisplay": "Display", + "tabLora": "LoRa", + "tabNetwork": "Network", + "tabPosition": "Position", + "tabPower": "Power", + "tabSecurity": "Security" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Role" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Регіон" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "Gateway" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP Config" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Timestamp", + "unset": "Скинути", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Power Config" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Private Key" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Public Key" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/uk-UA/dialog.json b/src/i18n/locales/uk-UA/dialog.json new file mode 100644 index 00000000..deb2c712 --- /dev/null +++ b/src/i18n/locales/uk-UA/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Serial", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Повідомлення", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Voltage", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Are you sure?" + } +} diff --git a/src/i18n/locales/uk-UA/messages.json b/src/i18n/locales/uk-UA/messages.json new file mode 100644 index 00000000..90e2d3b3 --- /dev/null +++ b/src/i18n/locales/uk-UA/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "Надіслати" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/uk-UA/moduleConfig.json b/src/i18n/locales/uk-UA/moduleConfig.json new file mode 100644 index 00000000..caacbe17 --- /dev/null +++ b/src/i18n/locales/uk-UA/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Range Test", + "tabSerial": "Serial", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetry" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Current", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Timeout", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/uk-UA/nodes.json b/src/i18n/locales/uk-UA/nodes.json new file mode 100644 index 00000000..5202f039 --- /dev/null +++ b/src/i18n/locales/uk-UA/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Favorite" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Direct", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/uk-UA/ui.json b/src/i18n/locales/uk-UA/ui.json new file mode 100644 index 00000000..e9f80e00 --- /dev/null +++ b/src/i18n/locales/uk-UA/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Повідомлення", + "map": "Мапа", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Channels", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Battery" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Hide password" + }, + "showPassword": { + "label": "Show password" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Role" + }, + "filter": { + "label": "Фільтри" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Voltage" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Direct", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Last heard", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "Мова", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Темна", + "light": "Світла", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/zh-CN/channels.json b/src/i18n/locales/zh-CN/channels.json new file mode 100644 index 00000000..3ad45930 --- /dev/null +++ b/src/i18n/locales/zh-CN/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "频道", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "主要", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "频道设置", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "角色", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "名称", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "启用上传", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "启用下载", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "位置", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/zh-CN/commandPalette.json b/src/i18n/locales/zh-CN/commandPalette.json new file mode 100644 index 00000000..685ec409 --- /dev/null +++ b/src/i18n/locales/zh-CN/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "消息", + "map": "地图", + "config": "配置", + "channels": "频道", + "nodes": "节点" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "导入", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "调试", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json new file mode 100644 index 00000000..d5c38965 --- /dev/null +++ b/src/i18n/locales/zh-CN/common.json @@ -0,0 +1,119 @@ +{ + "button": { + "apply": "申请", + "backupKey": "Backup Key", + "cancel": "取消", + "clearMessages": "Clear Messages", + "close": "关闭", + "confirm": "Confirm", + "delete": "删除", + "dismiss": "收起键盘", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "导入", + "message": "信息", + "now": "Now", + "ok": "好的", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "移除", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "重置", + "save": "保存", + "scanQr": "扫描二维码", + "traceRoute": "Trace Route" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "256bit": "256 bit" + }, + "unknown": { + "longName": "未知", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "formValidation": { + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/zh-CN/dashboard.json b/src/i18n/locales/zh-CN/dashboard.json new file mode 100644 index 00000000..a7b78399 --- /dev/null +++ b/src/i18n/locales/zh-CN/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "串口", + "connectionType_network": "网络", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/zh-CN/deviceConfig.json b/src/i18n/locales/zh-CN/deviceConfig.json new file mode 100644 index 00000000..590aeb25 --- /dev/null +++ b/src/i18n/locales/zh-CN/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "蓝牙", + "tabDevice": "设备", + "tabDisplay": "显示", + "tabLora": "LoRa", + "tabNetwork": "网络", + "tabPosition": "定位", + "tabPower": "电源", + "tabSecurity": "安全" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX 时区" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "转播模式" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "角色" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "启用" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "配对模式" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "显示模式" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "显示单位" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED 类型" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "带宽" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "编码率" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "忽略 MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "调制解调器预设" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "使用MQTT" + }, + "overrideDutyCycle": { + "description": "覆盖占空比", + "label": "覆盖占空比" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "区域" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "启用传输" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "使用预设" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "启用" + }, + "gateway": { + "description": "Default Gateway", + "label": "网关" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "共享密钥/PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "子网" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "启用" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP 设置" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "广播间隔" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "如果设置了 DOP,则使用 HDOP / VDOP 值而不是 PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "时间戳", + "unset": "未设置", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "启用节能模式" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "电源配置" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "私钥" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "公钥" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "一级管理员密钥" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "二级管理员密钥" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "三级管理员密钥" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/zh-CN/dialog.json b/src/i18n/locales/zh-CN/dialog.json new file mode 100644 index 00000000..fc2afbb7 --- /dev/null +++ b/src/i18n/locales/zh-CN/dialog.json @@ -0,0 +1,159 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "长名称", + "shortName": "短名称", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "蓝牙", + "tabSerial": "串口", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "连接", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "信息", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "电压", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "生成二维码" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "是否确认?" + } +} diff --git a/src/i18n/locales/zh-CN/messages.json b/src/i18n/locales/zh-CN/messages.json new file mode 100644 index 00000000..b61de68d --- /dev/null +++ b/src/i18n/locales/zh-CN/messages.json @@ -0,0 +1,40 @@ +{ + "page": { + "title": "Messages: {{chatName}}" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Type your message here...", + "sendButton": "传送" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "回复" + }, + "item": { + "status": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "ariaLabel": "Sending message", + "displayText": "Waiting for delivery" + } + } + } +} diff --git a/src/i18n/locales/zh-CN/moduleConfig.json b/src/i18n/locales/zh-CN/moduleConfig.json new file mode 100644 index 00000000..4bcce7d2 --- /dev/null +++ b/src/i18n/locales/zh-CN/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "氛围灯", + "tabAudio": "音频", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "检测传感器", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "邻居信息", + "tabPaxcounter": "客流计数", + "tabRangeTest": "拉距测试", + "tabSerial": "串口", + "tabStoreAndForward": "S&F", + "tabTelemetry": "遥测(传感器)" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED 状态", + "description": "Sets LED to on or off" + }, + "current": { + "label": "电流", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "红", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "绿", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "蓝", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "发送铃声", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "启用", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "发送铃声", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "启用", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "启用加密", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "启用 JSON", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "启用 TLS", + "description": "Enable or disable TLS" + }, + "root": { + "label": "根主题", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "启用", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "回声", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "超时", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "模式", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "记录数", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "历史记录最大返回值", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "历史记录返回窗口", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "设备指标", + "description": "设备计量更新间隔 (秒)" + }, + "environmentUpdateInterval": { + "label": "环境计量更新间隔 (秒)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "展示华氏度", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/zh-CN/nodes.json b/src/i18n/locales/zh-CN/nodes.json new file mode 100644 index 00000000..6f1ac1b4 --- /dev/null +++ b/src/i18n/locales/zh-CN/nodes.json @@ -0,0 +1,51 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "收藏" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "status": { + "heard": "收到", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "长名称", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "模型", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "直频", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + } +} diff --git a/src/i18n/locales/zh-CN/ui.json b/src/i18n/locales/zh-CN/ui.json new file mode 100644 index 00000000..e93db7f6 --- /dev/null +++ b/src/i18n/locales/zh-CN/ui.json @@ -0,0 +1,201 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "消息", + "map": "地图", + "config": "配置", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "频道", + "nodes": "节点" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "固件", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "电池" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "隐藏密码" + }, + "showPassword": { + "label": "显示密码" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "等待中...", + "unknown": "未知" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "硬件" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "角色" + }, + "filter": { + "label": "筛选器csvfganw" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "电压" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "直频", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "最后听到", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "language": { + "label": "语言", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "深色", + "light": "浅色", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} From 118f84830837b18849917afcd4b84ef0fc48cea5 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 16 Jun 2025 16:22:45 -0400 Subject: [PATCH 12/37] feat: add support for 3 languages (#661) --- src/i18n/config.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/i18n/config.ts b/src/i18n/config.ts index a028a25c..fddfde8f 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -11,6 +11,11 @@ export type Lang = { export type LangCode = Lang["code"]; +/** + * Generates a flag emoji from a two-letter country code. + * @param regionCode - The two-letter, uppercase country code (e.g., "US", "FI"). + * @returns A string containing the flag emoji. + */ function getFlagEmoji(regionCode: string): string { const A_LETTER_CODE = 0x1F1E6; const a_char_code = "A".charCodeAt(0); @@ -22,10 +27,10 @@ function getFlagEmoji(regionCode: string): string { } export const supportedLanguages: Lang[] = [ - { code: "de", name: "German", flag: getFlagEmoji("de") }, - { code: "en", name: "English", flag: getFlagEmoji("us") }, - { code: "fi", name: "Finnish", flag: getFlagEmoji("fi") }, - { code: "sv", name: "Swedish", flag: getFlagEmoji("se") }, + { code: "de-DE", name: "Deutschland", flag: getFlagEmoji("DE") }, + { code: "en-US", name: "English", flag: getFlagEmoji("US") }, + { code: "fi-FI", name: "Suomi", flag: getFlagEmoji("FI") }, + { code: "sv-SE", name: "Svenska", flag: getFlagEmoji("SE") }, ]; i18next @@ -34,19 +39,18 @@ i18next .use(LanguageDetector) .init({ backend: { - // this will lazy load resources from the i18n folder + // With this setup, {{lng}} will correctly resolve to 'en-US', 'fi-FI', etc. loadPath: "/src/i18n/locales/{{lng}}/{{ns}}.json", }, react: { useSuspense: true, }, + nonExplicitSupportedLngs: true, detection: { - order: ["navigator", "localStorage"], + order: ["localStorage", "navigator"], caches: ["localStorage"], }, - fallbackLng: { - "default": ["en"], - }, + fallbackLng: "en-US", // Default to US English if detection fails fallbackNS: ["common", "ui", "dialog"], debug: import.meta.env.MODE === "development", ns: [ From ccc4202aa406638976076c109a6e6449462d3b76 Mon Sep 17 00:00:00 2001 From: Jeremy Gallant <8975765+philon-@users.noreply.github.com> Date: Tue, 17 Jun 2025 16:24:58 +0200 Subject: [PATCH 13/37] Minor i18n fixes (#663) * i18n fixes Add PKI Backup Reminder dialog + ensure en-US is UI default * Revert edits to i18n components --- src/components/KeyBackupReminder.tsx | 2 +- src/core/hooks/useKeyBackupReminder.tsx | 14 ++++++++++---- src/i18n/locales/en/common.json | 1 + src/i18n/locales/en/dialog.json | 8 +++++++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/components/KeyBackupReminder.tsx b/src/components/KeyBackupReminder.tsx index aefe60ec..32cacd1a 100644 --- a/src/components/KeyBackupReminder.tsx +++ b/src/components/KeyBackupReminder.tsx @@ -7,7 +7,7 @@ export const KeyBackupReminder = () => { const { t } = useTranslation("dialog"); useBackupReminder({ - message: t("pkiBackup.description"), + message: t("pkiBackupReminder.description"), onAccept: () => setDialogOpen("pkiBackup", true), enabled: true, }); diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx index 9e71c2fa..eaadce14 100644 --- a/src/core/hooks/useKeyBackupReminder.tsx +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -2,6 +2,7 @@ import { Button } from "@components/UI/Button.tsx"; import { useCallback, useEffect, useRef } from "react"; import { useToast } from "@core/hooks/useToast.ts"; import useLocalStorage from "@core/hooks/useLocalStorage.ts"; +import { useTranslation } from "react-i18next"; interface UseBackupReminderOptions { reminderInDays?: number; @@ -36,6 +37,8 @@ export function useBackupReminder({ onAccept = () => {}, reminderInDays = REMINDER_DAYS_ONE_WEEK, }: UseBackupReminderOptions) { + const { t } = useTranslation("dialog"); + const { toast } = useToast(); const toastShownRef = useRef(false); const [reminderState, setReminderState] = useLocalStorage< @@ -59,7 +62,7 @@ export function useBackupReminder({ toastShownRef.current = true; const { dismiss } = toast({ - title: "Backup Reminder", + title: t("pkiBackupReminder.title"), duration: TOAST_DURATION, delay: TOAST_APPEAR_DELAY, description: message, @@ -75,7 +78,10 @@ export function useBackupReminder({ setReminderExpiry(reminderInDays); }} > - Remind me in {reminderInDays} day{reminderInDays > 1 ? "s" : ""} + {t("pkiBackupReminder.remindLaterPrefix")} {reminderInDays}{" "} + {reminderInDays > 1 + ? t("common:unit.day.plural").toLowerCase() + : t("common:unit.day.one").toLowerCase()}
), diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index efb44b14..5597f53a 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -54,6 +54,7 @@ "suffix": "ms" }, "second": { "one": "Second", "plural": "Seconds" }, + "day": { "one": "Day", "plural": "Days" }, "snr": "SNR", "volt": { "one": "Volt", "plural": "Volts", "suffix": "V" }, "record": { "one": "Records", "plural": "Records" } diff --git a/src/i18n/locales/en/dialog.json b/src/i18n/locales/en/dialog.json index 23393156..28427867 100644 --- a/src/i18n/locales/en/dialog.json +++ b/src/i18n/locales/en/dialog.json @@ -93,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -103,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" From c91e5e6b7b99b70a4b3f8665d0af8de5b8764dbf Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Tue, 17 Jun 2025 11:09:43 -0400 Subject: [PATCH 14/37] fix: add rewrites to vercel.json (#662) --- vercel.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vercel.json b/vercel.json index 24bca4be..52503763 100644 --- a/vercel.json +++ b/vercel.json @@ -1,5 +1,11 @@ { - "github": { "silent": true }, + "$schema": "https://openapi.vercel.sh/vercel.json", + "rewrites": [ + { + "source": "/((?!api|.*\\..*).*)", + "destination": "/index.html" + } + ], "headers": [ { "source": "/", From a5339af0dd25eae677c26f68619c2c088806af89 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Tue, 17 Jun 2025 16:23:57 -0400 Subject: [PATCH 15/37] Fix language default in picker. Misc i18n fixes (#664) * fix: fix language default in picker. Misc i18n fixes * Update src/i18n/config.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * PR fixes * duplicate key --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .githooks/_/pre-commit | 12 +++++ src/components/LanguageSwitcher.tsx | 14 ++---- src/components/UI/ErrorPage.tsx | 2 +- src/core/hooks/useLang.ts | 71 ++++++++--------------------- src/i18n/config.ts | 34 ++++++-------- vite.config.ts | 1 - 6 files changed, 52 insertions(+), 82 deletions(-) create mode 100755 .githooks/_/pre-commit diff --git a/.githooks/_/pre-commit b/.githooks/_/pre-commit new file mode 100755 index 00000000..a6e72484 --- /dev/null +++ b/.githooks/_/pre-commit @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ "$SKIP_SIMPLE_GIT_HOOKS" = "1" ]; then + echo "[INFO] SKIP_SIMPLE_GIT_HOOKS is set to 1, skipping hook." + exit 0 +fi + +if [ -f "$SIMPLE_GIT_HOOKS_RC" ]; then + . "$SIMPLE_GIT_HOOKS_RC" +fi + +deno task lint:fix && deno task format \ No newline at end of file diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx index d33bc474..64da5a05 100644 --- a/src/components/LanguageSwitcher.tsx +++ b/src/components/LanguageSwitcher.tsx @@ -16,15 +16,11 @@ interface LanguageSwitcherProps { disableHover?: boolean; } -export default function LanguageSwitcher( - { disableHover = false }: LanguageSwitcherProps, -) { +export default function LanguageSwitcher({ + disableHover = false, +}: LanguageSwitcherProps) { const { i18n } = useTranslation("ui"); - const { set: setLanguage } = useLang(); - - const currentLanguage = - supportedLanguages.find((lang) => lang.code === i18n.language) || - supportedLanguages[0]; + const { set: setLanguage, currentLanguage } = useLang(); const handleLanguageChange = async (languageCode: LangCode) => { await setLanguage(languageCode, true); @@ -65,7 +61,7 @@ export default function LanguageSwitcher( "group-hover:text-gray-900 dark:group-hover:text-white", )} > - {currentLanguage.name} + {currentLanguage?.name} diff --git a/src/components/UI/ErrorPage.tsx b/src/components/UI/ErrorPage.tsx index 0f7037db..40da4ad1 100644 --- a/src/components/UI/ErrorPage.tsx +++ b/src/components/UI/ErrorPage.tsx @@ -60,7 +60,7 @@ export function ErrorPage({ error }: { error: Error }) {
Chirpy the Meshtastic error diff --git a/src/core/hooks/useLang.ts b/src/core/hooks/useLang.ts index 156e697c..0b408d7b 100644 --- a/src/core/hooks/useLang.ts +++ b/src/core/hooks/useLang.ts @@ -1,86 +1,55 @@ import { useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; -import { LangCode } from "@app/i18n/config.ts"; +import { + FALLBACK_LANGUAGE_CODE, + Lang, + LangCode, + supportedLanguages, +} from "../../i18n/config.ts"; import useLocalStorage from "./useLocalStorage.ts"; -/** - * Hook to set the i18n language - * - * @returns The `set` function - */ const STORAGE_KEY = "language"; type LanguageState = { - language: string; + language: LangCode; }; + function useLang() { const { i18n } = useTranslation(); - const [_, setLanguage] = useLocalStorage( + const [_, setLanguageInStorage] = useLocalStorage( STORAGE_KEY, null, ); - const regionNames = useMemo(() => { - return new Intl.DisplayNames(i18n.language, { - type: "region", - fallback: "none", - style: "long", - }); + const currentLanguage = useMemo((): Lang | undefined => { + const lang = supportedLanguages.find((l) => l.code === i18n.language); + if (lang) { + return lang; + } + return supportedLanguages.find((l) => l.code === FALLBACK_LANGUAGE_CODE); }, [i18n.language]); const collator = useMemo(() => { - return new Intl.Collator(i18n.language, {}); + return new Intl.Collator(i18n.language, { sensitivity: "base" }); }, [i18n.language]); - /** - * Sets the i18n language. - * - * @param lng - The language tag to set - * @param persist - Whether to persist the language setting in local storage - */ const set = useCallback( async (lng: LangCode, persist = true) => { if (i18n.language === lng) { return; } - try { - console.info("setting language:", lng); if (persist) { - setLanguage({ language: lng }); + setLanguageInStorage({ language: lng }); } await i18n.changeLanguage(lng); } catch (e) { - console.warn(e); - } - }, - [i18n], - ); - - /** - * Get the localized country name - * - * @param code - Two-letter country code - */ - const getCountryName = useCallback( - (code: LangCode) => { - let name = null; - try { - name = regionNames.of(code); - } catch (e) { - console.warn(e); + console.warn("Failed to change language:", e); } - return name; }, - [regionNames], + [i18n, setLanguageInStorage], ); - /** - * Compare two strings according to the sort order of the current language - * - * @param a - The first string to compare - * @param b - The second string to compare - */ const compare = useCallback( (a: string, b: string) => { return collator.compare(a, b); @@ -88,7 +57,7 @@ function useLang() { [collator], ); - return { compare, set, getCountryName }; + return { compare, set, currentLanguage }; } export default useLang; diff --git a/src/i18n/config.ts b/src/i18n/config.ts index fddfde8f..097e3791 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -7,32 +7,20 @@ export type Lang = { code: Intl.Locale["language"]; name: string; flag: string; + region?: Intl.Locale["region"]; }; export type LangCode = Lang["code"]; -/** - * Generates a flag emoji from a two-letter country code. - * @param regionCode - The two-letter, uppercase country code (e.g., "US", "FI"). - * @returns A string containing the flag emoji. - */ -function getFlagEmoji(regionCode: string): string { - const A_LETTER_CODE = 0x1F1E6; - const a_char_code = "A".charCodeAt(0); - const codePoints = regionCode - .toUpperCase() - .split("") - .map((char) => A_LETTER_CODE + char.charCodeAt(0) - a_char_code); - return String.fromCodePoint(...codePoints); -} - export const supportedLanguages: Lang[] = [ - { code: "de-DE", name: "Deutschland", flag: getFlagEmoji("DE") }, - { code: "en-US", name: "English", flag: getFlagEmoji("US") }, - { code: "fi-FI", name: "Suomi", flag: getFlagEmoji("FI") }, - { code: "sv-SE", name: "Svenska", flag: getFlagEmoji("SE") }, + { code: "de", name: "Deutsch", flag: "🇩🇪" }, + { code: "en", name: "English", flag: "🇺🇸" }, + { code: "fi", name: "Suomi", flag: "🇫🇮" }, + { code: "sv", name: "Svenska", flag: "🇸🇪" }, ]; +export const FALLBACK_LANGUAGE_CODE: LangCode = "en"; + i18next .use(Backend) .use(initReactI18next) @@ -50,7 +38,13 @@ i18next order: ["localStorage", "navigator"], caches: ["localStorage"], }, - fallbackLng: "en-US", // Default to US English if detection fails + fallbackLng: { + default: [FALLBACK_LANGUAGE_CODE], + "en-GB": [FALLBACK_LANGUAGE_CODE], + "fi": ["fi-FI"], + "sv": ["sv-SE"], + "de": ["de-DE"], + }, fallbackNS: ["common", "ui", "dialog"], debug: import.meta.env.MODE === "development", ns: [ diff --git a/vite.config.ts b/vite.config.ts index dcccf7a0..64f63903 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,5 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; -import { VitePWA } from "vite-plugin-pwa"; import { viteStaticCopy } from "vite-plugin-static-copy"; import { execSync } from "node:child_process"; import process from "node:process"; From 7adbe017231d88a98ab5487a597c30b4dfc4db19 Mon Sep 17 00:00:00 2001 From: Jeremy Gallant <8975765+philon-@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:02:42 +0200 Subject: [PATCH 16/37] Add advanced filters (#655) * Add advanced filters * Review edits --------- Co-authored-by: philon- --- .../generic/Filter/FilterControl.tsx | 32 ++++++++++++++++--- .../generic/Filter/useFilterNode.test.ts | 22 +++++++++++++ .../generic/Filter/useFilterNode.ts | 18 +++++++++++ src/i18n/locales/en/ui.json | 9 ++++++ 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/components/generic/Filter/FilterControl.tsx b/src/components/generic/Filter/FilterControl.tsx index 87ff3723..f3c0c14c 100644 --- a/src/components/generic/Filter/FilterControl.tsx +++ b/src/components/generic/Filter/FilterControl.tsx @@ -190,10 +190,12 @@ export function FilterControl({ ); const handleBoolChange = useCallback( - (key: K, value: string) => { - const typedValue = value === "" - ? undefined - : JSON.parse(value.toLowerCase()); + (key: K, value: string | boolean) => { + const typedValue = value === true || value === "true" + ? true + : value === false || value === "false" + ? false + : undefined; setFilterState((prev) => ({ ...prev, @@ -386,6 +388,28 @@ export function FilterControl({ formatEnumLabel(Protobuf.Mesh.HardwareModel[val])} /> + + + + + + + + ); +}; diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index e7f91f51..3fe802d6 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -14,6 +14,7 @@ import { type Path, type SubmitHandler, useForm, + type UseFormReturn, } from "react-hook-form"; import { Heading } from "@components/UI/Typography/Heading.tsx"; import { ZodType } from "zod/v4"; @@ -44,13 +45,18 @@ export interface GenericFormElementProps { control: Control; disabled?: boolean; field: Y; + isDirty?: boolean; + invalid?: boolean; } export interface DynamicFormProps { + propMethods?: UseFormReturn; onSubmit: SubmitHandler; + onFormInit?: DynamicFormFormInit; submitType?: "onChange" | "onSubmit"; hasSubmitButton?: boolean; defaultValues?: DefaultValues; + values?: T; fieldGroups: { label: string; description: string; @@ -63,11 +69,18 @@ export interface DynamicFormProps { formId?: string; } +export type DynamicFormFormInit = ( + methods: UseFormReturn, +) => void; + export function DynamicForm({ + propMethods, onSubmit, + onFormInit, submitType = "onChange", hasSubmitButton, defaultValues, + values, fieldGroups, validationSchema, formId, @@ -78,17 +91,29 @@ export function DynamicForm({ removeError, } = useAppStore(); - const methods = useForm< - T - >({ - mode: "onChange", - defaultValues: defaultValues, - resolver: validationSchema - ? createZodResolver(validationSchema) - : undefined, - shouldFocusError: false, - }); - const { handleSubmit, control, getValues, formState } = methods; + let methods = propMethods; + if (!methods) { + methods = useForm< + T + >({ + mode: "onChange", + defaultValues: defaultValues, + resolver: validationSchema + ? createZodResolver(validationSchema) + : undefined, + shouldFocusError: false, + resetOptions: { keepDefaultValues: true }, + values, + }); + } + const { handleSubmit, control, getValues, formState, getFieldState } = + methods; + + useEffect(() => { + if (!propMethods) { + onFormInit?.(methods); + } + }, [onFormInit, propMethods, methods]); useEffect(() => { const errorKeys = Object.keys(formState.errors); @@ -155,25 +180,22 @@ export function DynamicForm({ label={field.label} fieldName={field.name} description={field.description} - valid={validationSchema // keep backwards compat with not updated cfg pages - ? !error - : field.validationText === undefined || - field.validationText === ""} - validationText={validationSchema - ? (error - ? String( - t([`formValidation.${error.type}`, error.message], { - returnObjects: false, - ...error.params, - }), - ) - : "") - : field.validationText} + valid={!error} + validationText={error + ? String( + t([`formValidation.${error.type}`, error.message], { + returnObjects: false, + ...error.params, + }), + ) + : ""} > ); diff --git a/src/components/Form/DynamicFormField.tsx b/src/components/Form/DynamicFormField.tsx index 320db39f..34508613 100644 --- a/src/components/Form/DynamicFormField.tsx +++ b/src/components/Form/DynamicFormField.tsx @@ -31,19 +31,29 @@ export interface DynamicFormFieldProps { field: FieldProps; control: Control; disabled?: boolean; + isDirty?: boolean; + invalid?: boolean; } export function DynamicFormField({ field, control, disabled, + isDirty, + invalid, }: DynamicFormFieldProps) { switch (field.type) { case "text": case "password": case "number": return ( - + ); case "toggle": @@ -52,6 +62,8 @@ export function DynamicFormField({ field={field} control={control} disabled={disabled} + isDirty={isDirty} + invalid={invalid} /> ); case "select": @@ -60,6 +72,8 @@ export function DynamicFormField({ field={field} control={control} disabled={disabled} + isDirty={isDirty} + invalid={invalid} /> ); case "passwordGenerator": @@ -68,11 +82,19 @@ export function DynamicFormField({ field={field} control={control} disabled={disabled} + isDirty={isDirty} + invalid={invalid} /> ); case "multiSelect": return ( - + ); } } diff --git a/src/components/Form/FormInput.tsx b/src/components/Form/FormInput.tsx index c0af74ae..cd7ffea0 100644 --- a/src/components/Form/FormInput.tsx +++ b/src/components/Form/FormInput.tsx @@ -31,6 +31,8 @@ export function GenericInput({ control, disabled, field, + isDirty, + invalid, }: GenericFormElementProps>) { const { fieldLength, ...restProperties } = field.properties || {}; const [currentLength, setCurrentLength] = useState( @@ -78,6 +80,7 @@ export function GenericInput({ className={field.properties?.className} {...restProperties} disabled={disabled} + variant={invalid ? "invalid" : isDirty ? "dirty" : "default"} /> {fieldLength?.showCharacterCount && fieldLength?.max && ( diff --git a/src/components/Form/FormMultiSelect.tsx b/src/components/Form/FormMultiSelect.tsx index cea9a511..82354c88 100644 --- a/src/components/Form/FormMultiSelect.tsx +++ b/src/components/Form/FormMultiSelect.tsx @@ -6,6 +6,7 @@ import type { FieldValues } from "react-hook-form"; import { useTranslation } from "react-i18next"; import type { FLAGS_CONFIG } from "@core/hooks/usePositionFlags.ts"; import { MultiSelect, MultiSelectItem } from "../UI/MultiSelect.tsx"; +import { cn } from "@core/utils/cn.ts"; export interface MultiSelectFieldProps extends BaseFormBuilderProps { type: "multiSelect"; @@ -23,9 +24,11 @@ export interface MultiSelectFieldProps extends BaseFormBuilderProps { export function MultiSelectInput({ field, + isDirty, + invalid, }: GenericFormElementProps>) { const { t } = useTranslation("deviceConfig"); - const { enumValue, ...remainingProperties } = field.properties; + const { enumValue, className, ...remainingProperties } = field.properties; const isNewConfigStructure = typeof Object.values(enumValue)[0] === "object" && @@ -48,7 +51,15 @@ export function MultiSelectInput({ ); return ( - + {optionsToRender.map((option) => { return ( ({ control, field, disabled, + isDirty, + invalid, }: GenericFormElementProps>) { const { isVisible } = usePasswordVisibilityToggle(); const { trigger } = useFormContext(); @@ -42,7 +44,11 @@ export function PasswordGenerator({ ( + render={( + { + field: { value, onChange, ...rest }, + }, + ) => ( ({ }} selectChange={field.selectChange ?? (() => {})} value={value} - variant={field.validationText ? "invalid" : "default"} + variant={invalid ? "invalid" : isDirty ? "dirty" : "default"} actionButtons={field.actionButtons} showPasswordToggle={field.showPasswordToggle} showCopyButton={field.showCopyButton} diff --git a/src/components/Form/FormSelect.tsx b/src/components/Form/FormSelect.tsx index e665db8c..3b4cce04 100644 --- a/src/components/Form/FormSelect.tsx +++ b/src/components/Form/FormSelect.tsx @@ -10,6 +10,7 @@ import { SelectValue, } from "@components/UI/Select.tsx"; import { type FieldValues, useController } from "react-hook-form"; +import { cn } from "@core/utils/cn.ts"; export interface SelectFieldProps extends BaseFormBuilderProps { type: "select"; @@ -38,6 +39,8 @@ export function SelectInput({ control, disabled, field, + isDirty, + invalid, }: GenericFormElementProps>) { const { field: { value, onChange, ref, onBlur, ...rest }, @@ -46,8 +49,13 @@ export function SelectInput({ control, }); - const { enumValue, formatEnumName, defaultValue, ...remainingProperties } = - field.properties; + const { + enumValue, + formatEnumName, + defaultValue, + className, + ...remainingProperties + } = field.properties; const valueToKeyMap: Record = {}; const optionsEnumValues: [string, number][] = []; @@ -82,6 +90,13 @@ export function SelectInput({ > extends BaseFormBuilderProps { type: "toggle"; @@ -14,12 +15,16 @@ export function ToggleInput({ control, disabled, field, + isDirty, + invalid, }: GenericFormElementProps>) { return ( ( + render={( + { field: { value, onChange, ...rest } }, + ) => ( { @@ -29,6 +34,15 @@ export function ToggleInput({ id={field.name} disabled={disabled} {...field.properties} + className={cn([ + field.properties?.className, + isDirty + ? "focus:ring-sky-500 ring-sky-500 ring-2 ring-offset-2" + : "", + invalid + ? "focus:ring-red-500 ring-red-500 ring-2 ring-offset-2" + : "", + ])} {...rest} /> )} diff --git a/src/components/PageComponents/Config/Bluetooth.tsx b/src/components/PageComponents/Config/Bluetooth.tsx index efd1111c..5d27c4a1 100644 --- a/src/components/PageComponents/Config/Bluetooth.tsx +++ b/src/components/PageComponents/Config/Bluetooth.tsx @@ -3,16 +3,29 @@ import { BluetoothValidationSchema, } from "@app/validation/config/bluetooth.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const Bluetooth = () => { - const { config, setWorkingConfig } = useDevice(); +interface BluetoothConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Bluetooth = ({ onFormInit }: BluetoothConfigProps) => { + const { config, setWorkingConfig, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { t } = useTranslation("deviceConfig"); const onSubmit = (data: BluetoothValidation) => { + if (deepCompareConfig(config.bluetooth, data, true)) { + removeWorkingConfig("bluetooth"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -26,9 +39,11 @@ export const Bluetooth = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={BluetoothValidationSchema} formId="Config_BluetoothConfig" defaultValues={config.bluetooth} + values={getEffectiveConfig("bluetooth")} fieldGroups={[ { label: t("bluetooth.title"), diff --git a/src/components/PageComponents/Config/ConfigSuspender.tsx b/src/components/PageComponents/Config/ConfigSuspender.tsx new file mode 100644 index 00000000..83eaa89d --- /dev/null +++ b/src/components/PageComponents/Config/ConfigSuspender.tsx @@ -0,0 +1,37 @@ +import { + useDevice, + ValidConfigType, + ValidModuleConfigType, +} from "@core/stores/deviceStore.ts"; +import { useEffect, useState } from "react"; + +export function ConfigSuspender({ + configCase, + moduleConfigCase, + children, +}: { + configCase?: ValidConfigType; + moduleConfigCase?: ValidModuleConfigType; + children: React.ReactNode; +}) { + const { config, moduleConfig } = useDevice(); + + let cfg = undefined; + if (configCase) { + cfg = config[configCase]; + } else if (moduleConfigCase) { + cfg = moduleConfig[moduleConfigCase]; + } else { + return children; + } + + const [ready, setReady] = useState(() => cfg !== undefined); + + useEffect(() => { + if (cfg !== undefined) setReady(true); + }, [cfg]); + + if (!ready) throw new Promise(() => {}); // triggers suspense fallback + + return children; +} diff --git a/src/components/PageComponents/Config/Device/index.tsx b/src/components/PageComponents/Config/Device/index.tsx index 68e4b8ad..2d1689b2 100644 --- a/src/components/PageComponents/Config/Device/index.tsx +++ b/src/components/PageComponents/Config/Device/index.tsx @@ -3,18 +3,31 @@ import { DeviceValidationSchema, } from "@app/validation/config/device.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useUnsafeRolesDialog } from "@components/Dialog/UnsafeRolesDialog/useUnsafeRolesDialog.ts"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const Device = () => { - const { config, setWorkingConfig } = useDevice(); +interface DeviceConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Device = ({ onFormInit }: DeviceConfigProps) => { + const { config, setWorkingConfig, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { t } = useTranslation("deviceConfig"); const { validateRoleSelection } = useUnsafeRolesDialog(); const onSubmit = (data: DeviceValidation) => { + if (deepCompareConfig(config.device, data, true)) { + removeWorkingConfig("device"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -24,12 +37,15 @@ export const Device = () => { }), ); }; + return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={DeviceValidationSchema} formId="Config_DeviceConfig" defaultValues={config.device} + values={getEffectiveConfig("device")} fieldGroups={[ { label: t("device.title"), @@ -97,7 +113,8 @@ export const Device = () => { properties: { fieldLength: { max: 64, - currentValueLength: config.device?.tzdef?.length, + currentValueLength: getEffectiveConfig("device")?.tzdef + ?.length, showCharacterCount: true, }, }, diff --git a/src/components/PageComponents/Config/Display.tsx b/src/components/PageComponents/Config/Display.tsx index 0cda0f33..42e0e546 100644 --- a/src/components/PageComponents/Config/Display.tsx +++ b/src/components/PageComponents/Config/Display.tsx @@ -3,16 +3,29 @@ import { DisplayValidationSchema, } from "@app/validation/config/display.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const Display = () => { - const { config, setWorkingConfig } = useDevice(); +interface DisplayConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Display = ({ onFormInit }: DisplayConfigProps) => { + const { config, setWorkingConfig, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { t } = useTranslation("deviceConfig"); const onSubmit = (data: DisplayValidation) => { + if (deepCompareConfig(config.display, data, true)) { + removeWorkingConfig("display"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -26,9 +39,11 @@ export const Display = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={DisplayValidationSchema} formId="Config_DisplayConfig" defaultValues={config.display} + values={getEffectiveConfig("display")} fieldGroups={[ { label: t("display.title"), diff --git a/src/components/PageComponents/Config/LoRa.tsx b/src/components/PageComponents/Config/LoRa.tsx index cf3abdd5..251f2fcb 100644 --- a/src/components/PageComponents/Config/LoRa.tsx +++ b/src/components/PageComponents/Config/LoRa.tsx @@ -3,16 +3,29 @@ import { LoRaValidationSchema, } from "@app/validation/config/lora.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const LoRa = () => { - const { config, setWorkingConfig } = useDevice(); +interface LoRaConfigProps { + onFormInit: DynamicFormFormInit; +} +export const LoRa = ({ onFormInit }: LoRaConfigProps) => { + const { config, setWorkingConfig, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { t } = useTranslation("deviceConfig"); const onSubmit = (data: LoRaValidation) => { + if (deepCompareConfig(config.lora, data, true)) { + removeWorkingConfig("lora"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -26,9 +39,11 @@ export const LoRa = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={LoRaValidationSchema} formId="Config_LoRaConfig" defaultValues={config.lora} + values={getEffectiveConfig("lora")} fieldGroups={[ { label: t("lora.title"), diff --git a/src/components/PageComponents/Config/Network/index.tsx b/src/components/PageComponents/Config/Network/index.tsx index 3d944668..12e72362 100644 --- a/src/components/PageComponents/Config/Network/index.tsx +++ b/src/components/PageComponents/Config/Network/index.tsx @@ -3,7 +3,10 @@ import { NetworkValidationSchema, } from "@app/validation/config/network.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { convertIntToIpAddress, @@ -11,35 +14,50 @@ import { } from "@core/utils/ip.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const Network = () => { - const { config, setWorkingConfig } = useDevice(); +interface NetworkConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Network = ({ onFormInit }: NetworkConfigProps) => { + const { config, setWorkingConfig, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { t } = useTranslation("deviceConfig"); + + const networkConfig = getEffectiveConfig("network"); + const onSubmit = (data: NetworkValidation) => { + const payload = { + ...data, + ipv4Config: create( + Protobuf.Config.Config_NetworkConfig_IpV4ConfigSchema, + { + ip: convertIpAddressToInt(data.ipv4Config?.ip ?? ""), + gateway: convertIpAddressToInt(data.ipv4Config?.gateway ?? ""), + subnet: convertIpAddressToInt(data.ipv4Config?.subnet ?? ""), + dns: convertIpAddressToInt(data.ipv4Config?.dns ?? ""), + }, + ), + }; + + if (deepCompareConfig(config.network, payload, true)) { + removeWorkingConfig("network"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { case: "network", - value: { - ...data, - ipv4Config: create( - Protobuf.Config.Config_NetworkConfig_IpV4ConfigSchema, - { - ip: convertIpAddressToInt(data.ipv4Config?.ip ?? ""), - gateway: convertIpAddressToInt(data.ipv4Config?.gateway ?? ""), - subnet: convertIpAddressToInt(data.ipv4Config?.subnet ?? ""), - dns: convertIpAddressToInt(data.ipv4Config?.dns ?? ""), - }, - ), - }, + value: payload, }, }), ); }; - return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={NetworkValidationSchema} formId="Config_NetworkConfig" defaultValues={{ @@ -57,6 +75,21 @@ export const Network = () => { enabledProtocols: config.network?.enabledProtocols ?? Protobuf.Config.Config_NetworkConfig_ProtocolFlags.NO_BROADCAST, }} + values={{ + ...networkConfig, + ipv4Config: { + ip: convertIntToIpAddress(networkConfig?.ipv4Config?.ip ?? 0), + gateway: convertIntToIpAddress( + networkConfig?.ipv4Config?.gateway ?? 0, + ), + subnet: convertIntToIpAddress( + networkConfig?.ipv4Config?.subnet ?? 0, + ), + dns: convertIntToIpAddress(networkConfig?.ipv4Config?.dns ?? 0), + }, + enabledProtocols: networkConfig?.enabledProtocols ?? + Protobuf.Config.Config_NetworkConfig_ProtocolFlags.NO_BROADCAST, + } as NetworkValidation} fieldGroups={[ { label: t("network.title"), diff --git a/src/components/PageComponents/Config/Position.tsx b/src/components/PageComponents/Config/Position.tsx index b306117c..d6fa1a05 100644 --- a/src/components/PageComponents/Config/Position.tsx +++ b/src/components/PageComponents/Config/Position.tsx @@ -7,20 +7,33 @@ import { PositionValidationSchema, } from "@app/validation/config/position.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useCallback } from "react"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const Position = () => { - const { config, setWorkingConfig } = useDevice(); +interface PositionConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Position = ({ onFormInit }: PositionConfigProps) => { + const { setWorkingConfig, config, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { flagsValue, activeFlags, toggleFlag, getAllFlags } = usePositionFlags( - config?.position?.positionFlags ?? 0, + getEffectiveConfig("position")?.positionFlags ?? 0, ); const { t } = useTranslation("deviceConfig"); const onSubmit = (data: PositionValidation) => { + if (deepCompareConfig(config.position, data, true)) { + removeWorkingConfig("position"); + return; + } + return setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -44,9 +57,11 @@ export const Position = () => { data.positionFlags = flagsValue; return onSubmit(data); }} + onFormInit={onFormInit} validationSchema={PositionValidationSchema} formId="Config_PositionConfig" defaultValues={config.position} + values={getEffectiveConfig("position")} fieldGroups={[ { label: t("position.title"), diff --git a/src/components/PageComponents/Config/Power.tsx b/src/components/PageComponents/Config/Power.tsx index b81e1aaa..c35c543d 100644 --- a/src/components/PageComponents/Config/Power.tsx +++ b/src/components/PageComponents/Config/Power.tsx @@ -3,16 +3,29 @@ import { PowerValidationSchema, } from "@app/validation/config/power.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -export const Power = () => { - const { config, setWorkingConfig } = useDevice(); +interface PowerConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Power = ({ onFormInit }: PowerConfigProps) => { + const { setWorkingConfig, config, getEffectiveConfig, removeWorkingConfig } = + useDevice(); const { t } = useTranslation("deviceConfig"); const onSubmit = (data: PowerValidation) => { + if (deepCompareConfig(config.power, data, true)) { + removeWorkingConfig("power"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -26,9 +39,11 @@ export const Power = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={PowerValidationSchema} formId="Config_PowerConfig" defaultValues={config.power} + values={getEffectiveConfig("power")} fieldGroups={[ { label: t("power.powerConfigSettings.label"), diff --git a/src/components/PageComponents/Config/Security/Security.tsx b/src/components/PageComponents/Config/Security/Security.tsx index 5b3f6e77..911227b5 100644 --- a/src/components/PageComponents/Config/Security/Security.tsx +++ b/src/components/PageComponents/Config/Security/Security.tsx @@ -1,5 +1,9 @@ import { PkiRegenerateDialog } from "@components/Dialog/PkiRegenerateDialog.tsx"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { ManagedModeDialog } from "@components/Dialog/ManagedModeDialog.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useAppStore } from "@core/stores/appStore.ts"; import { getX25519PrivateKey, getX25519PublicKey } from "@core/utils/x25519.ts"; import { @@ -7,37 +11,82 @@ import { type RawSecurity, RawSecuritySchema, } from "@app/validation/config/security.ts"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { create } from "@bufbuild/protobuf"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { fromByteArray, toByteArray } from "base64-js"; import { useTranslation } from "react-i18next"; +import { type DefaultValues, useForm } from "react-hook-form"; +import { createZodResolver } from "@components/Form/createZodResolver.ts"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; -type KeyState = { - publicKey: string; - privateKey: string; - privateKeyDialogOpen: boolean; -}; +interface SecurityConfigProps { + onFormInit: DynamicFormFormInit; +} +export const Security = ({ onFormInit }: SecurityConfigProps) => { + const { + config, + setWorkingConfig, + setDialogOpen, + getEffectiveConfig, + removeWorkingConfig, + } = useDevice(); -export const Security = () => { - const { config, setWorkingConfig, setDialogOpen } = useDevice(); const { removeError } = useAppStore(); const { t } = useTranslation("deviceConfig"); - const [keyState, setKeyState] = useState(() => ({ - publicKey: fromByteArray(config?.security?.publicKey ?? new Uint8Array(0)), - privateKey: fromByteArray( - config?.security?.privateKey ?? new Uint8Array(0), - ), - privateKeyDialogOpen: false, - })); + const securityConfig = getEffectiveConfig("security"); + const defaultValues = { + ...securityConfig, + ...{ + privateKey: fromByteArray( + securityConfig?.privateKey ?? new Uint8Array(0), + ), + publicKey: fromByteArray( + securityConfig?.publicKey ?? new Uint8Array(0), + ), + adminKey: [ + fromByteArray( + securityConfig?.adminKey?.at(0) ?? new Uint8Array(0), + ), + fromByteArray( + securityConfig?.adminKey?.at(1) ?? new Uint8Array(0), + ), + fromByteArray( + securityConfig?.adminKey?.at(2) ?? new Uint8Array(0), + ), + ], + }, + }; + + const formMethods = useForm({ + mode: "onChange", + defaultValues: defaultValues as DefaultValues, + resolver: createZodResolver(RawSecuritySchema), + shouldFocusError: false, + resetOptions: { keepDefaultValues: true }, + }); + const { setValue, formState } = formMethods; + + useEffect(() => { + onFormInit?.(formMethods); + }, [onFormInit, formMethods]); + + const [privateKeyDialogOpen, setPrivateKeyDialogOpen] = useState( + false, + ); + const [managedModeDialogOpen, setManagedModeDialogOpen] = useState( + false, + ); const onSubmit = (data: RawSecurity) => { + if (!formState.isReady) return; + const payload: ParsedSecurity = { ...data, - privateKey: toByteArray(keyState.privateKey), - publicKey: toByteArray(keyState.publicKey), + privateKey: toByteArray(data.privateKey), + publicKey: toByteArray(data.publicKey), adminKey: [ toByteArray(data.adminKey.at(0) ?? ""), toByteArray(data.adminKey.at(1) ?? ""), @@ -45,6 +94,11 @@ export const Security = () => { ], }; + if (deepCompareConfig(config.security, payload, true)) { + removeWorkingConfig("security"); + return; + } + setWorkingConfig( create(Protobuf.Config.ConfigSchema, { payloadVariant: { @@ -54,18 +108,10 @@ export const Security = () => { }), ); }; + const pkiRegenerate = () => { const privateKey = getX25519PrivateKey(); - updatePublicKey(fromByteArray(privateKey)); - - setKeyState((prev) => ({ - ...prev, - privateKey: fromByteArray(privateKey), - privateKeyDialogOpen: false, - })); - - removeError("privateKey"); }; const updatePublicKey = (privateKey: string) => { @@ -73,18 +119,14 @@ export const Security = () => { const publicKey = fromByteArray( getX25519PublicKey(toByteArray(privateKey)), ); - setKeyState((prev) => ({ - ...prev, - privateKey: privateKey, - publicKey: publicKey, - })); + setValue("privateKey", privateKey); + setValue("publicKey", publicKey); + removeError("privateKey"); removeError("publicKey"); + setPrivateKeyDialogOpen(false); } catch (_e) { - setKeyState((prev) => ({ - ...prev, - privateKey: privateKey, - })); + setValue("privateKey", privateKey); } }; @@ -99,31 +141,9 @@ export const Security = () => { return ( <> + propMethods={formMethods} onSubmit={onSubmit} - validationSchema={RawSecuritySchema} formId="Config_SecurityConfig" - defaultValues={{ - ...config.security, - ...{ - privateKey: fromByteArray( - config?.security?.privateKey ?? new Uint8Array(0), - ), - publicKey: fromByteArray( - config?.security?.publicKey ?? new Uint8Array(0), - ), - adminKey: [ - fromByteArray( - config?.security?.adminKey.at(0) ?? new Uint8Array(0), - ), - fromByteArray( - config?.security?.adminKey.at(1) ?? new Uint8Array(0), - ), - fromByteArray( - config?.security?.adminKey.at(2) ?? new Uint8Array(0), - ), - ], - }, - }} fieldGroups={[ { label: t("security.title"), @@ -144,11 +164,7 @@ export const Security = () => { actionButtons: [ { text: t("button.generate"), - onClick: () => - setKeyState((prev) => ({ - ...prev, - privateKeyDialogOpen: true, - })), + onClick: () => setPrivateKeyDialogOpen(true), variant: "success", }, { @@ -160,8 +176,6 @@ export const Security = () => { properties: { showCopyButton: true, showPasswordToggle: true, - - value: keyState.privateKey, }, }, { @@ -172,7 +186,6 @@ export const Security = () => { description: t("security.publicKey.description"), properties: { showCopyButton: true, - value: keyState.publicKey, }, }, ], @@ -240,6 +253,13 @@ export const Security = () => { name: "isManaged", label: t("security.managed.label"), description: t("security.managed.description"), + inputChange: (checked) => { + if (checked) { + setManagedModeDialogOpen(true); + } + + setValue("isManaged", false); + }, }, { type: "toggle", @@ -275,14 +295,19 @@ export const Security = () => { title: t("pkiRegenerate.title"), description: t("pkiRegenerate.description"), }} - open={keyState.privateKeyDialogOpen} - onOpenChange={() => - setKeyState((prev) => ({ - ...prev, - privateKeyDialogOpen: false, - }))} + open={privateKeyDialogOpen} + onOpenChange={() => setPrivateKeyDialogOpen((prev) => !prev)} onSubmit={pkiRegenerate} /> + + setManagedModeDialogOpen((prev) => !prev)} + onSubmit={() => { + setValue("isManaged", true); + setManagedModeDialogOpen(false); + }} + /> ); }; diff --git a/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx b/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx index 51f9cc5d..50da8ec6 100644 --- a/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx +++ b/src/components/PageComponents/ModuleConfig/AmbientLighting.tsx @@ -4,15 +4,35 @@ import { AmbientLightingValidationSchema, } from "@app/validation/moduleConfig/ambientLighting.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface AmbientLightingModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const AmbientLighting = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const AmbientLighting = ( + { onFormInit }: AmbientLightingModuleConfigProps, +) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: AmbientLightingValidation) => { + if (deepCompareConfig(moduleConfig.ambientLighting, data, true)) { + removeWorkingModuleConfig("ambientLighting"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +46,11 @@ export const AmbientLighting = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={AmbientLightingValidationSchema} formId="ModuleConfig_AmbientLightingConfig" defaultValues={moduleConfig.ambientLighting} + values={getEffectiveModuleConfig("ambientLighting")} fieldGroups={[ { label: t("ambientLighting.title"), diff --git a/src/components/PageComponents/ModuleConfig/Audio.tsx b/src/components/PageComponents/ModuleConfig/Audio.tsx index 4db01275..7a6ead8e 100644 --- a/src/components/PageComponents/ModuleConfig/Audio.tsx +++ b/src/components/PageComponents/ModuleConfig/Audio.tsx @@ -3,16 +3,34 @@ import { AudioValidationSchema, } from "@app/validation/moduleConfig/audio.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface AudioModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const Audio = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const Audio = ({ onFormInit }: AudioModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: AudioValidation) => { + if (deepCompareConfig(moduleConfig.audio, data, true)) { + removeWorkingModuleConfig("audio"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const Audio = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={AudioValidationSchema} formId="ModuleConfig_AudioConfig" defaultValues={moduleConfig.audio} + values={getEffectiveModuleConfig("audio")} fieldGroups={[ { label: t("audio.title"), diff --git a/src/components/PageComponents/ModuleConfig/CannedMessage.tsx b/src/components/PageComponents/ModuleConfig/CannedMessage.tsx index 80221028..b0e075e8 100644 --- a/src/components/PageComponents/ModuleConfig/CannedMessage.tsx +++ b/src/components/PageComponents/ModuleConfig/CannedMessage.tsx @@ -3,16 +3,36 @@ import { CannedMessageValidationSchema, } from "@app/validation/moduleConfig/cannedMessage.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface CannedMessageModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const CannedMessage = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const CannedMessage = ( + { onFormInit }: CannedMessageModuleConfigProps, +) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: CannedMessageValidation) => { + if (deepCompareConfig(moduleConfig.cannedMessage, data, true)) { + removeWorkingModuleConfig("cannedMessage"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +46,11 @@ export const CannedMessage = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={CannedMessageValidationSchema} formId="ModuleConfig_CannedMessageConfig" defaultValues={moduleConfig.cannedMessage} + values={getEffectiveModuleConfig("cannedMessage")} fieldGroups={[ { label: t("cannedMessage.title"), diff --git a/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx b/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx index 1ce0aaee..5d1fdb59 100644 --- a/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx +++ b/src/components/PageComponents/ModuleConfig/DetectionSensor.tsx @@ -4,15 +4,35 @@ import { DetectionSensorValidationSchema, } from "@app/validation/moduleConfig/detectionSensor.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface DetectionSensorModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const DetectionSensor = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const DetectionSensor = ( + { onFormInit }: DetectionSensorModuleConfigProps, +) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: DetectionSensorValidation) => { + if (deepCompareConfig(moduleConfig.detectionSensor, data, true)) { + removeWorkingModuleConfig("detectionSensor"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +46,11 @@ export const DetectionSensor = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={DetectionSensorValidationSchema} formId="ModuleConfig_DetectionSensorConfig" defaultValues={moduleConfig.detectionSensor} + values={getEffectiveModuleConfig("detectionSensor")} fieldGroups={[ { label: t("detectionSensor.title"), diff --git a/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx b/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx index 61796342..ff3141ea 100644 --- a/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx +++ b/src/components/PageComponents/ModuleConfig/ExternalNotification.tsx @@ -3,16 +3,36 @@ import { ExternalNotificationValidationSchema, } from "@app/validation/moduleConfig/externalNotification.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface ExternalNotificationModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const ExternalNotification = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const ExternalNotification = ( + { onFormInit }: ExternalNotificationModuleConfigProps, +) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: ExternalNotificationValidation) => { + if (deepCompareConfig(moduleConfig.externalNotification, data, true)) { + removeWorkingModuleConfig("externalNotification"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +46,11 @@ export const ExternalNotification = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={ExternalNotificationValidationSchema} formId="ModuleConfig_ExternalNotificationConfig" defaultValues={moduleConfig.externalNotification} + values={getEffectiveModuleConfig("externalNotification")} fieldGroups={[ { label: t("externalNotification.title"), diff --git a/src/components/PageComponents/ModuleConfig/MQTT.tsx b/src/components/PageComponents/ModuleConfig/MQTT.tsx index e9587e89..6b6f4abd 100644 --- a/src/components/PageComponents/ModuleConfig/MQTT.tsx +++ b/src/components/PageComponents/ModuleConfig/MQTT.tsx @@ -4,37 +4,72 @@ import { MqttValidationSchema, } from "@app/validation/moduleConfig/mqtt.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface MqttModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const MQTT = () => { - const { config, moduleConfig, setWorkingModuleConfig } = useDevice(); +export const MQTT = ({ onFormInit }: MqttModuleConfigProps) => { + const { + config, + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: MqttValidation) => { + const payload = { + ...data, + mapReportSettings: create( + Protobuf.ModuleConfig.ModuleConfig_MapReportSettingsSchema, + data.mapReportSettings, + ), + }; + + if (deepCompareConfig(moduleConfig.mqtt, payload, true)) { + removeWorkingModuleConfig("mqtt"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { case: "mqtt", - value: { - ...data, - mapReportSettings: create( - Protobuf.ModuleConfig.ModuleConfig_MapReportSettingsSchema, - data.mapReportSettings, - ), - }, + value: payload, }, }), ); }; + const populateDefaultValues = ( + cfg: Protobuf.ModuleConfig.ModuleConfig_MQTTConfig | undefined, + ) => { + return cfg + ? { + ...cfg, + mapReportSettings: cfg.mapReportSettings ?? + { publishIntervalSecs: 0, positionPrecision: 10 }, + } + : undefined; + }; + return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={MqttValidationSchema} formId="ModuleConfig_MqttConfig" - defaultValues={moduleConfig.mqtt} + defaultValues={populateDefaultValues(moduleConfig.mqtt)} + values={populateDefaultValues(getEffectiveModuleConfig("mqtt"))} fieldGroups={[ { label: t("mqtt.title"), diff --git a/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx b/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx index eabb9207..389c70bc 100644 --- a/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx +++ b/src/components/PageComponents/ModuleConfig/NeighborInfo.tsx @@ -4,15 +4,33 @@ import { NeighborInfoValidationSchema, } from "@app/validation/moduleConfig/neighborInfo.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface NeighborInfoModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const NeighborInfo = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const NeighborInfo = ({ onFormInit }: NeighborInfoModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: NeighborInfoValidation) => { + if (deepCompareConfig(moduleConfig.neighborInfo, data, true)) { + removeWorkingModuleConfig("neighborInfo"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const NeighborInfo = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={NeighborInfoValidationSchema} formId="ModuleConfig_NeighborInfoConfig" defaultValues={moduleConfig.neighborInfo} + values={getEffectiveModuleConfig("neighborInfo")} fieldGroups={[ { label: t("neighborInfo.title"), diff --git a/src/components/PageComponents/ModuleConfig/Paxcounter.tsx b/src/components/PageComponents/ModuleConfig/Paxcounter.tsx index c11840ad..45921d73 100644 --- a/src/components/PageComponents/ModuleConfig/Paxcounter.tsx +++ b/src/components/PageComponents/ModuleConfig/Paxcounter.tsx @@ -3,16 +3,34 @@ import { PaxcounterValidationSchema, } from "@app/validation/moduleConfig/paxcounter.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface PaxcounterModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const Paxcounter = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const Paxcounter = ({ onFormInit }: PaxcounterModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: PaxcounterValidation) => { + if (deepCompareConfig(moduleConfig.paxcounter, data, true)) { + removeWorkingModuleConfig("paxcounter"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const Paxcounter = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={PaxcounterValidationSchema} formId="ModuleConfig_PaxcounterConfig" defaultValues={moduleConfig.paxcounter} + values={getEffectiveModuleConfig("paxcounter")} fieldGroups={[ { label: t("paxcounter.title"), diff --git a/src/components/PageComponents/ModuleConfig/RangeTest.tsx b/src/components/PageComponents/ModuleConfig/RangeTest.tsx index 5960508d..fd18a110 100644 --- a/src/components/PageComponents/ModuleConfig/RangeTest.tsx +++ b/src/components/PageComponents/ModuleConfig/RangeTest.tsx @@ -3,16 +3,34 @@ import { RangeTestValidationSchema, } from "@app/validation/moduleConfig/rangeTest.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface RangeTestModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const RangeTest = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const RangeTest = ({ onFormInit }: RangeTestModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: RangeTestValidation) => { + if (deepCompareConfig(moduleConfig.rangeTest, data, true)) { + removeWorkingModuleConfig("rangeTest"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const RangeTest = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={RangeTestValidationSchema} formId="ModuleConfig_RangeTestConfig" defaultValues={moduleConfig.rangeTest} + values={getEffectiveModuleConfig("rangeTest")} fieldGroups={[ { label: t("rangeTest.title"), diff --git a/src/components/PageComponents/ModuleConfig/Serial.tsx b/src/components/PageComponents/ModuleConfig/Serial.tsx index d98684b5..9adcac16 100644 --- a/src/components/PageComponents/ModuleConfig/Serial.tsx +++ b/src/components/PageComponents/ModuleConfig/Serial.tsx @@ -3,16 +3,34 @@ import { SerialValidationSchema, } from "@app/validation/moduleConfig/serial.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface SerialModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const Serial = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const Serial = ({ onFormInit }: SerialModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: SerialValidation) => { + if (deepCompareConfig(moduleConfig.serial, data, true)) { + removeWorkingModuleConfig("serial"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const Serial = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={SerialValidationSchema} formId="ModuleConfig_SerialConfig" defaultValues={moduleConfig.serial} + values={getEffectiveModuleConfig("serial")} fieldGroups={[ { label: t("serial.title"), diff --git a/src/components/PageComponents/ModuleConfig/StoreForward.tsx b/src/components/PageComponents/ModuleConfig/StoreForward.tsx index 02b5d630..155c235a 100644 --- a/src/components/PageComponents/ModuleConfig/StoreForward.tsx +++ b/src/components/PageComponents/ModuleConfig/StoreForward.tsx @@ -3,16 +3,34 @@ import { StoreForwardValidationSchema, } from "@app/validation/moduleConfig/storeForward.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface StoreForwardModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const StoreForward = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const StoreForward = ({ onFormInit }: StoreForwardModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: StoreForwardValidation) => { + if (deepCompareConfig(moduleConfig.storeForward, data, true)) { + removeWorkingModuleConfig("storeForward"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const StoreForward = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={StoreForwardValidationSchema} formId="ModuleConfig_StoreForwardConfig" defaultValues={moduleConfig.storeForward} + values={getEffectiveModuleConfig("storeForward")} fieldGroups={[ { label: t("storeForward.title"), diff --git a/src/components/PageComponents/ModuleConfig/Telemetry.tsx b/src/components/PageComponents/ModuleConfig/Telemetry.tsx index d296fe71..0bb71134 100644 --- a/src/components/PageComponents/ModuleConfig/Telemetry.tsx +++ b/src/components/PageComponents/ModuleConfig/Telemetry.tsx @@ -3,16 +3,34 @@ import { TelemetryValidationSchema, } from "@app/validation/moduleConfig/telemetry.ts"; import { create } from "@bufbuild/protobuf"; -import { DynamicForm } from "@components/Form/DynamicForm.tsx"; +import { + DynamicForm, + type DynamicFormFormInit, +} from "@components/Form/DynamicForm.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Protobuf } from "@meshtastic/core"; import { useTranslation } from "react-i18next"; +import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts"; + +interface TelemetryModuleConfigProps { + onFormInit: DynamicFormFormInit; +} -export const Telemetry = () => { - const { moduleConfig, setWorkingModuleConfig } = useDevice(); +export const Telemetry = ({ onFormInit }: TelemetryModuleConfigProps) => { + const { + moduleConfig, + setWorkingModuleConfig, + getEffectiveModuleConfig, + removeWorkingModuleConfig, + } = useDevice(); const { t } = useTranslation("moduleConfig"); const onSubmit = (data: TelemetryValidation) => { + if (deepCompareConfig(moduleConfig.telemetry, data, true)) { + removeWorkingModuleConfig("telemetry"); + return; + } + setWorkingModuleConfig( create(Protobuf.ModuleConfig.ModuleConfigSchema, { payloadVariant: { @@ -26,9 +44,11 @@ export const Telemetry = () => { return ( onSubmit={onSubmit} + onFormInit={onFormInit} validationSchema={TelemetryValidationSchema} formId="ModuleConfig_TelemetryConfig" defaultValues={moduleConfig.telemetry} + values={getEffectiveModuleConfig("telemetry")} fieldGroups={[ { label: t("telemetry.title"), diff --git a/src/components/PageLayout.tsx b/src/components/PageLayout.tsx index a08a2afa..534ab71a 100644 --- a/src/components/PageLayout.tsx +++ b/src/components/PageLayout.tsx @@ -8,12 +8,14 @@ import { ErrorPage } from "@components/UI/ErrorPage.tsx"; export interface ActionItem { key: string; - icon: LucideIcon; + icon?: LucideIcon; iconClasses?: string; onClick: () => void; disabled?: boolean; isLoading?: boolean; ariaLabel?: string; + label?: string; + className?: string; } export interface PageLayoutProps { @@ -69,27 +71,39 @@ export const PageLayout = ({ {label} -
- {actions?.map((action) => ( - - ))} + onClick={action.onClick} + aria-label={action.ariaLabel || `Action ${action.key}`} + aria-disabled={action.disabled} + aria-busy={action.isLoading} + > + {action.icon && + (action.isLoading ? : ( + + ))} + {action.label && ( + + {action.label} + + )} + + ); + })}
diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 2cb22b16..f23cf1e3 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -22,7 +22,7 @@ export interface GeneratorProps extends React.BaseHTMLAttributes { devicePSKBitCount?: number; value: string; id: string; - variant: "default" | "invalid"; + variant: "default" | "invalid" | "dirty"; actionButtons: ActionButton[]; bits?: { text: string; value: string; key: string }[]; selectChange: (event: string) => void; diff --git a/src/components/UI/Input.tsx b/src/components/UI/Input.tsx index 81a072e7..faa24544 100644 --- a/src/components/UI/Input.tsx +++ b/src/components/UI/Input.tsx @@ -6,14 +6,17 @@ import { useCopyToClipboard } from "@core/hooks/useCopyToClipboard.ts"; import { usePasswordVisibilityToggle } from "@core/hooks/usePasswordVisibilityToggle.ts"; import { useTranslation } from "react-i18next"; +const cnInvalidBase = "border-2 border-red-500 dark:border-red-500"; +const cnDirtyBase = "border-2 border-sky-500 dark:border-sky-500"; + const inputVariants = cva( "flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-1 focus:ring-slate-400 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-500 dark:bg-transparet dark:text-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-600", { variants: { variant: { default: "border-slate-300 dark:border-slate-500", - invalid: - "border-red-500 dark:border-red-500 focus:ring-red-500 dark:focus:ring-red-500", + invalid: `${cnInvalidBase} focus:ring-red-500 dark:focus:ring-red-500`, + dirty: `${cnDirtyBase} focus:ring-sky-500 dark:focus:ring-sky-500`, }, }, defaultVariants: { @@ -49,6 +52,7 @@ const Input = React.forwardRef( className, containerClassName, variant, + disabled, type = "text", prefix, suffix, @@ -137,6 +141,11 @@ const Input = React.forwardRef( className, ); + const extrasClassName = cn([ + variant === "invalid" && `${cnInvalidBase} border-l-0`, + variant === "dirty" && `${cnDirtyBase} border-l-0`, + ]); + return (
( ref={ref} value={value} onChange={onChange} + disabled={disabled} {...props} /> @@ -161,6 +171,7 @@ const Input = React.forwardRef( @@ -171,7 +182,10 @@ const Input = React.forwardRef( {hasActions && (
( key={action.id} type="button" className={cn( - "inline-flex h-full items-center justify-center px-2.5 text-slate-500 hover:bg-slate-100 hover:text-slate-700 focus:outline-none focus:ring-1 focus:ring-slate-400 focus:ring-offset-0 dark:text-slate-400 dark:hover:bg-slate-700 dark:hover:text-slate-200 dark:focus:ring-slate-500 hover:rounded-md dark:hover:rounded-md", + "inline-flex h-full items-center justify-center px-2.5 text-slate-500 hover:bg-slate-100 hover:text-slate-700 focus:outline-none focus:ring-1 focus:ring-slate-400 focus:ring-offset-0 dark:text-slate-400 dark:hover:bg-slate-700 dark:hover:text-slate-200 dark:focus:ring-slate-500 last:hover:rounded-r-md last:dark:hover:rounded-r-md", + disabled && "text-slate-300 dark:text-slate-600", action.id === "copy-value" && isCopied && "text-green-600 dark:text-green-500", )} diff --git a/src/components/UI/Sidebar/SidebarButton.tsx b/src/components/UI/Sidebar/SidebarButton.tsx index 920fb08c..8dc1aeca 100644 --- a/src/components/UI/Sidebar/SidebarButton.tsx +++ b/src/components/UI/Sidebar/SidebarButton.tsx @@ -13,6 +13,7 @@ export interface SidebarButtonProps { onClick?: () => void; disabled?: boolean; preventCollapse?: boolean; + isDirty?: boolean; } export const SidebarButton = ({ @@ -24,6 +25,7 @@ export const SidebarButton = ({ onClick, disabled = false, preventCollapse = false, + isDirty, }: SidebarButtonProps) => { const { isCollapsed: isSidebarCollapsed } = useSidebar(); const isButtonCollapsed = isSidebarCollapsed && !preventCollapse; @@ -64,13 +66,14 @@ export const SidebarButton = ({ {label} - {!isButtonCollapsed && !active && count && count > 0 && ( + {!isButtonCollapsed && ((!active && count && count > 0) || isDirty) && (
{count} diff --git a/src/core/stores/deviceStore.mock.ts b/src/core/stores/deviceStore.mock.ts index fb97c9d3..43af9a9e 100644 --- a/src/core/stores/deviceStore.mock.ts +++ b/src/core/stores/deviceStore.mock.ts @@ -44,12 +44,19 @@ export const mockDeviceStore: Device = { unsafeRoles: false, refreshKeys: false, deleteMessages: false, + managedMode: false, }, setStatus: vi.fn(), setConfig: vi.fn(), setModuleConfig: vi.fn(), setWorkingConfig: vi.fn(), setWorkingModuleConfig: vi.fn(), + getWorkingConfig: vi.fn(), + getWorkingModuleConfig: vi.fn(), + removeWorkingConfig: vi.fn(), + removeWorkingModuleConfig: vi.fn(), + getEffectiveConfig: vi.fn(), + getEffectiveModuleConfig: vi.fn(), setHardware: vi.fn(), setActiveNode: vi.fn(), setPendingSettingsChanges: vi.fn(), diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index 488a5d5d..5b8d20c0 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -18,6 +18,14 @@ type NodeError = { node: number; error: string; }; +export type ValidConfigType = Exclude< + Protobuf.Config.Config["payloadVariant"]["case"], + "deviceUi" | "sessionkey" | undefined +>; +export type ValidModuleConfigType = Exclude< + Protobuf.ModuleConfig.ModuleConfig["payloadVariant"]["case"], + undefined +>; export interface Device { id: number; @@ -54,6 +62,7 @@ export interface Device { unsafeRoles: boolean; refreshKeys: boolean; deleteMessages: boolean; + managedMode: boolean; }; setStatus: (status: Types.DeviceStatusEnum) => void; @@ -61,6 +70,26 @@ export interface Device { setModuleConfig: (config: Protobuf.ModuleConfig.ModuleConfig) => void; setWorkingConfig: (config: Protobuf.Config.Config) => void; setWorkingModuleConfig: (config: Protobuf.ModuleConfig.ModuleConfig) => void; + getWorkingConfig: ( + payloadVariant: ValidConfigType, + ) => + | Protobuf.LocalOnly.LocalConfig[Exclude] + | undefined; + getWorkingModuleConfig: ( + payloadVariant: ValidModuleConfigType, + ) => + | Protobuf.LocalOnly.LocalModuleConfig[ + Exclude + ] + | undefined; + removeWorkingConfig: (payloadVariant?: ValidConfigType) => void; + removeWorkingModuleConfig: (payloadVariant?: ValidModuleConfigType) => void; + getEffectiveConfig( + payloadVariant: K, + ): Protobuf.LocalOnly.LocalConfig[K] | undefined; + getEffectiveModuleConfig( + payloadVariant: K, + ): Protobuf.LocalOnly.LocalModuleConfig[K] | undefined; setHardware: (hardware: Protobuf.Mesh.MyNodeInfo) => void; setActiveNode: (node: number) => void; setPendingSettingsChanges: (state: boolean) => void; @@ -142,6 +171,7 @@ export const useDeviceStore = createStore((set, get) => ({ refreshKeys: false, rebootOTA: false, deleteMessages: false, + managedMode: false, }, pendingSettingsChanges: false, messageDraft: "", @@ -277,6 +307,7 @@ export const useDeviceStore = createStore((set, get) => ({ const index = device.workingConfig.findIndex( (wc) => wc.payloadVariant.case === config.payloadVariant.case, ); + if (index !== -1) { device.workingConfig[index] = config; } else { @@ -297,6 +328,7 @@ export const useDeviceStore = createStore((set, get) => ({ wmc.payloadVariant.case === moduleConfig.payloadVariant.case, ); + if (index !== -1) { device.workingModuleConfig[index] = moduleConfig; } else { @@ -305,6 +337,106 @@ export const useDeviceStore = createStore((set, get) => ({ }), ); }, + + getWorkingConfig: (payloadVariant: ValidConfigType) => { + const device = get().devices.get(id); + if (!device) return; + + const workingConfig = device.workingConfig.find( + (c) => c.payloadVariant.case === payloadVariant, + ); + + if ( + workingConfig?.payloadVariant.case === "deviceUi" || + workingConfig?.payloadVariant.case === "sessionkey" + ) return; + + return workingConfig?.payloadVariant.value; + }, + getWorkingModuleConfig: (payloadVariant: ValidModuleConfigType) => { + const device = get().devices.get(id); + if (!device) return; + + return device.workingModuleConfig.find( + (c) => c.payloadVariant.case === payloadVariant, + )?.payloadVariant.value; + }, + + removeWorkingConfig: (payloadVariant?: ValidConfigType) => { + set( + produce((draft) => { + const device = draft.devices.get(id); + if (!device) return; + + if (!payloadVariant) { + device.workingConfig = []; + return; + } + + const index = device.workingConfig.findIndex( + (wc: Protobuf.Config.Config) => + wc.payloadVariant.case === payloadVariant, + ); + + if (index !== -1) { + device.workingConfig.splice(index, 1); + } + }), + ); + }, + removeWorkingModuleConfig: ( + payloadVariant?: ValidModuleConfigType, + ) => { + set( + produce((draft) => { + const device = draft.devices.get(id); + if (!device) return; + + if (!payloadVariant) { + device.workingModuleConfig = []; + return; + } + + const index = device.workingModuleConfig.findIndex( + (wc: Protobuf.ModuleConfig.ModuleConfig) => + wc.payloadVariant.case === payloadVariant, + ); + + if (index !== -1) { + device.workingModuleConfig.splice(index, 1); + } + }), + ); + }, + + getEffectiveConfig( + payloadVariant: K, + ): Protobuf.LocalOnly.LocalConfig[K] | undefined { + if (!payloadVariant) return; + const device = get().devices.get(id); + if (!device) return; + + return { + ...device.config[payloadVariant], + ...(device.workingConfig.find( + (c) => c.payloadVariant.case === payloadVariant, + )?.payloadVariant.value), + }; + }, + getEffectiveModuleConfig( + payloadVariant: K, + ): Protobuf.LocalOnly.LocalModuleConfig[K] | undefined { + const device = get().devices.get(id); + if (!device) return; + + return { + ...device.moduleConfig[payloadVariant], + ...(device.workingModuleConfig.find( + (c) => c.payloadVariant.case === payloadVariant, + )?.payloadVariant.value), + }; + }, + setHardware: (hardware: Protobuf.Mesh.MyNodeInfo) => { set( produce((draft) => { diff --git a/src/core/utils/deepCompareConfig.test.ts b/src/core/utils/deepCompareConfig.test.ts new file mode 100644 index 00000000..b504d2b7 --- /dev/null +++ b/src/core/utils/deepCompareConfig.test.ts @@ -0,0 +1,60 @@ +import { describe, expect, it } from "vitest"; +import { deepCompareConfig } from "./deepCompareConfig.ts"; + +describe("deepCompareConfig", () => { + it("returns true for identical primitives", () => { + expect(deepCompareConfig(5, 5)).toBe(true); + expect(deepCompareConfig("foo", "foo")).toBe(true); + expect(deepCompareConfig(true, true)).toBe(true); + }); + + it("returns false for different primitives", () => { + expect(deepCompareConfig(5, 6)).toBe(false); + expect(deepCompareConfig("foo", "bar")).toBe(false); + expect(deepCompareConfig(true, false)).toBe(false); + }); + + it("handles nulls correctly", () => { + expect(deepCompareConfig(null, null)).toBe(true); + expect(deepCompareConfig(null, undefined)).toBe(false); + expect(deepCompareConfig(null, {})).toBe(false); + }); + + it("allows undefined in working when allowUndefined is true", () => { + expect(deepCompareConfig({ a: 1 }, { a: undefined }, true)).toBe(true); + expect(deepCompareConfig([1, 2, 3], [1, undefined, 3], true)).toBe(true); + }); + + it("rejects undefined in working when allowUndefined is false", () => { + expect(deepCompareConfig({ a: 1 }, { a: undefined }, false)).toBe(false); + }); + + it("compares arrays deeply", () => { + expect(deepCompareConfig([1, [2, 3]], [1, [2, 3]])).toBe(true); + expect(deepCompareConfig([1, [2, 3]], [1, [2, 4]])).toBe(false); + }); + + it("compares objects deeply", () => { + const existing = { x: 10, y: { z: 20 } }; + const workingEqual = { x: 10, y: { z: 20 } }; + const workingDiff = { x: 10, y: { z: 21 } }; + + expect(deepCompareConfig(existing, workingEqual)).toBe(true); + expect(deepCompareConfig(existing, workingDiff)).toBe(false); + }); + + it("ignores $typeName key in existing", () => { + const existing = { $typeName: "Test", a: 1 }; + const working = { a: 1 }; + expect(deepCompareConfig(existing, working)).toBe(true); + }); + + it("fails when working has extra keys", () => { + expect(deepCompareConfig({ a: 1 }, { a: 1, b: 2 })).toBe(false); + }); + + it("allows working arrays to be shorter if allowUndefined is true", () => { + expect(deepCompareConfig([1, 2, 3, 4], [1, 2], true)).toBe(true); + expect(deepCompareConfig([1, 2, 3, 4], [1, 2], false)).toBe(false); + }); +}); diff --git a/src/core/utils/deepCompareConfig.ts b/src/core/utils/deepCompareConfig.ts new file mode 100644 index 00000000..aca12452 --- /dev/null +++ b/src/core/utils/deepCompareConfig.ts @@ -0,0 +1,58 @@ +function isObject(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +export function deepCompareConfig( + a: unknown, + b: unknown, + allowUndefined = false, +): boolean { + if (a === b) { + return true; + } + + // If allowUndefined is true, and one is undefined, they are considered equal. // This check is placed early to simplify subsequent logic. + if (allowUndefined && (a === undefined || b === undefined)) { + return true; + } + + if (typeof a !== typeof b || a === null || b === null) { + return false; + } + + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length !== b.length && !allowUndefined) { + return false; + } + + const longestLength = Math.max(a.length, b.length); + for (let i = 0; i < longestLength; i++) { + if (!deepCompareConfig(a[i], b[i], allowUndefined)) { + return false; + } + } + return true; + } + + if (isObject(a) && isObject(b)) { + const aKeys = Object.keys(a); + const bKeys = Object.keys(b); + const allKeys = new Set([...aKeys, ...bKeys]); + + for (const key of allKeys) { + if (key === "$typeName") { + continue; + } + + const aValue = a[key]; + const bValue = b[key]; + + if (!deepCompareConfig(aValue, bValue, allowUndefined)) { + return false; + } + } + return true; + } + + return false; +} diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 5597f53a..0fb0756b 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -72,6 +72,7 @@ "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/en/dialog.json b/src/i18n/locales/en/dialog.json index 28427867..ddf1f352 100644 --- a/src/i18n/locales/en/dialog.json +++ b/src/i18n/locales/en/dialog.json @@ -162,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Are you sure?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Are you sure?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/pages/Config/DeviceConfig.tsx b/src/pages/Config/DeviceConfig.tsx index 8a42d0c4..314d5f26 100644 --- a/src/pages/Config/DeviceConfig.tsx +++ b/src/pages/Config/DeviceConfig.tsx @@ -12,45 +12,77 @@ import { TabsList, TabsTrigger, } from "@components/UI/Tabs.tsx"; +import { Spinner } from "@components/UI/Spinner.tsx"; import { useTranslation } from "react-i18next"; +import { useDevice, type ValidConfigType } from "@core/stores/deviceStore.ts"; +import { useMemo } from "react"; +import { type ComponentType, Suspense } from "react"; +import type { UseFormReturn } from "react-hook-form"; +import { ConfigSuspender } from "@components/PageComponents/Config/ConfigSuspender.tsx"; -export const DeviceConfig = () => { +interface ConfigProps { + // We can get rid of this exception if we import every config schema and pass the union type + // deno-lint-ignore no-explicit-any + onFormInit: (methods: UseFormReturn) => void; +} +type TabItem = { + case: ValidConfigType; + label: string; + element: ComponentType; + count?: number; +}; + +export const DeviceConfig = ({ onFormInit }: ConfigProps) => { + const { getWorkingConfig } = useDevice(); const { t } = useTranslation("deviceConfig"); - const tabs = [ + const tabs: TabItem[] = [ { + case: "device", label: t("page.tabDevice"), element: Device, count: 0, }, { + case: "position", label: t("page.tabPosition"), element: Position, }, { + case: "power", label: t("page.tabPower"), element: Power, }, { + case: "network", label: t("page.tabNetwork"), element: Network, }, { + case: "display", label: t("page.tabDisplay"), element: Display, }, { + case: "lora", label: t("page.tabLora"), element: LoRa, }, { + case: "bluetooth", label: t("page.tabBluetooth"), element: Bluetooth, }, { + case: "security", label: t("page.tabSecurity"), element: Security, }, - ]; + ] as const; + + const flags = useMemo( + () => new Map(tabs.map((tab) => [tab.case, getWorkingConfig(tab.case)])), + [tabs, getWorkingConfig], + ); return ( @@ -59,15 +91,27 @@ export const DeviceConfig = () => { {tab.label} + {flags.get(tab.case) && ( + + + + + + + )} ))} {tabs.map((tab) => ( - + }> + + + + ))} diff --git a/src/pages/Config/ModuleConfig.tsx b/src/pages/Config/ModuleConfig.tsx index 4800cf2b..db0cb106 100644 --- a/src/pages/Config/ModuleConfig.tsx +++ b/src/pages/Config/ModuleConfig.tsx @@ -16,60 +16,96 @@ import { TabsList, TabsTrigger, } from "@components/UI/Tabs.tsx"; +import { Spinner } from "@components/UI/Spinner.tsx"; import { useTranslation } from "react-i18next"; +import { + useDevice, + type ValidModuleConfigType, +} from "@core/stores/deviceStore.ts"; +import { useMemo } from "react"; +import { type ComponentType, Suspense } from "react"; +import type { UseFormReturn } from "react-hook-form"; +import { ConfigSuspender } from "@components/PageComponents/Config/ConfigSuspender.tsx"; + +interface ConfigProps { + // We can get rid of this exception if we import every config schema and pass the union type + // deno-lint-ignore no-explicit-any + onFormInit: (methods: UseFormReturn) => void; +} +type TabItem = { + case: ValidModuleConfigType; + label: string; + element: ComponentType; + count?: number; +}; -export const ModuleConfig = () => { +export const ModuleConfig = ({ onFormInit }: ConfigProps) => { + const { getWorkingModuleConfig } = useDevice(); const { t } = useTranslation("moduleConfig"); - const tabs = [ + const tabs: TabItem[] = [ { + case: "mqtt", label: t("page.tabMqtt"), element: MQTT, }, { + case: "serial", label: t("page.tabSerial"), element: Serial, }, { + case: "externalNotification", label: t("page.tabExternalNotification"), element: ExternalNotification, }, { + case: "storeForward", label: t("page.tabStoreAndForward"), element: StoreForward, }, { + case: "rangeTest", label: t("page.tabRangeTest"), element: RangeTest, }, { + case: "telemetry", label: t("page.tabTelemetry"), element: Telemetry, }, { + case: "cannedMessage", label: t("page.tabCannedMessage"), element: CannedMessage, }, { + case: "audio", label: t("page.tabAudio"), element: Audio, }, { + case: "neighborInfo", label: t("page.tabNeighborInfo"), element: NeighborInfo, }, { + case: "ambientLighting", label: t("page.tabAmbientLighting"), element: AmbientLighting, }, { + case: "detectionSensor", label: t("page.tabDetectionSensor"), element: DetectionSensor, }, - { - label: t("page.tabPaxcounter"), - element: Paxcounter, - }, - ]; + { case: "paxcounter", label: t("page.tabPaxcounter"), element: Paxcounter }, + ] as const; + + const flags = useMemo( + () => + new Map(tabs.map((tab) => [tab.case, getWorkingModuleConfig(tab.case)])), + [tabs, getWorkingModuleConfig], + ); return ( @@ -78,15 +114,27 @@ export const ModuleConfig = () => { {tab.label} + {flags.get(tab.case) && ( + + + + + + + )} ))} {tabs.map((tab) => ( - + }> + + + + ))} diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx index 337c2883..98725b0f 100644 --- a/src/pages/Config/index.tsx +++ b/src/pages/Config/index.tsx @@ -1,27 +1,49 @@ -import { useAppStore } from "../../core/stores/appStore.ts"; +import { useAppStore } from "@core/stores/appStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts"; import { PageLayout } from "@components/PageLayout.tsx"; import { Sidebar } from "@components/Sidebar.tsx"; import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx"; -import { SidebarButton } from "../../components/UI/Sidebar/SidebarButton.tsx"; +import { SidebarButton } from "@components/UI/Sidebar/SidebarButton.tsx"; + import { useToast } from "@core/hooks/useToast.ts"; import { DeviceConfig } from "@pages/Config/DeviceConfig.tsx"; import { ModuleConfig } from "@pages/Config/ModuleConfig.tsx"; -import { BoxesIcon, SaveIcon, SaveOff, SettingsIcon } from "lucide-react"; +import { + BoxesIcon, + RefreshCwIcon, + SaveIcon, + SaveOff, + SettingsIcon, +} from "lucide-react"; import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; +import { cn } from "@core/utils/cn.ts"; +import type { UseFormReturn } from "react-hook-form"; const ConfigPage = () => { - const { workingConfig, workingModuleConfig, connection } = useDevice(); + const { + workingConfig, + workingModuleConfig, + connection, + removeWorkingConfig, + removeWorkingModuleConfig, + setConfig, + setModuleConfig, + } = useDevice(); const { hasErrors } = useAppStore(); + const [activeConfigSection, setActiveConfigSection] = useState< "device" | "module" >("device"); const [isSaving, setIsSaving] = useState(false); + const [formMethods, setFormMethods] = useState(null); const { toast } = useToast(); - const isError = hasErrors(); const { t } = useTranslation("deviceConfig"); + const onFormInit = (methods: UseFormReturn) => { + setFormMethods(methods); + }; + const handleSave = async () => { if (hasErrors()) { return toast({ @@ -31,36 +53,49 @@ const ConfigPage = () => { } setIsSaving(true); + try { - if (activeConfigSection === "device") { - await Promise.all( - workingConfig.map((config) => - connection?.setConfig(config).then(() => - toast({ - title: t("toast.saveSuccess.title"), - description: t("toast.saveSuccess.description", { - case: config.payloadVariant.case, - }), - }) - ) - ), - ); - } else { - await Promise.all( - workingModuleConfig.map((moduleConfig) => - connection?.setModuleConfig(moduleConfig).then(() => - toast({ - title: t("toast.saveSuccess.title"), - description: t("toast.saveSuccess.description", { - case: moduleConfig.payloadVariant.case, - }), - }) - ) - ), + await Promise.all( + workingConfig.map((newConfig) => + connection?.setConfig(newConfig).then(() => { + toast({ + title: t("toast.saveSuccess.title"), + description: t("toast.saveSuccess.description", { + case: newConfig.payloadVariant.case, + }), + }); + }) + ), + ); + + await Promise.all( + workingModuleConfig.map((newModuleConfig) => + connection?.setModuleConfig(newModuleConfig).then(() => + toast({ + title: t("toast.saveSuccess.title"), + description: t("toast.saveSuccess.description", { + case: newModuleConfig.payloadVariant.case, + }), + }) + ) + ), + ); + + await connection?.commitEditSettings().then(() => { + if (formMethods) { + formMethods.reset({}, { + keepValues: true, + }); + } + + workingConfig.map((newConfig) => setConfig(newConfig)); + workingModuleConfig.map((newModuleConfig) => + setModuleConfig(newModuleConfig) ); - setIsSaving(false); - } - await connection?.commitEditSettings(); + + removeWorkingConfig(); + removeWorkingModuleConfig(); + }); } catch (_error) { toast({ title: t("toast.configSaveError.title"), @@ -71,6 +106,15 @@ const ConfigPage = () => { } }; + const handleReset = () => { + if (formMethods) { + formMethods.reset(); + } + + removeWorkingConfig(); + removeWorkingModuleConfig(); + }; + const leftSidebar = useMemo( () => ( @@ -83,19 +127,79 @@ const ConfigPage = () => { active={activeConfigSection === "device"} onClick={() => setActiveConfigSection("device")} Icon={SettingsIcon} + isDirty={workingConfig.length > 0} + count={workingConfig.length} /> setActiveConfigSection("module")} Icon={BoxesIcon} + isDirty={workingModuleConfig.length > 0} + count={workingModuleConfig.length} /> ), - [activeConfigSection], + [activeConfigSection, workingConfig, workingModuleConfig], ); + const buttonOpacity = useMemo( + () => (formMethods?.formState.isDirty && + Object.keys(formMethods?.formState.dirtyFields ?? {}).length > 0 || + workingConfig.length > 0 || workingModuleConfig.length > 0 + ? "opacity-100" + : "opacity-0"), + [ + formMethods?.formState.isDirty, + formMethods?.formState.dirtyFields, + workingConfig, + workingModuleConfig, + ], + ); + + const isValid = useMemo(() => { + return Object.keys(formMethods?.formState.errors ?? {}).length === 0; + }, [formMethods?.formState.errors]); + + const actions = useMemo(() => [ + { + key: "unsavedChanges", + label: t("common:formValidation.unsavedChanges"), + onClick: () => {}, + className: cn([ + "bg-blue-500 hover:bg-blue-500 text-white hover:text-white", + buttonOpacity, + "transition-opacity", + ]), + }, + { + key: "reset", + icon: RefreshCwIcon, + label: t("common:button.reset"), + onClick: handleReset, + className: cn([buttonOpacity, "transition-opacity"]), + }, + { + key: "save", + icon: !isValid ? SaveOff : SaveIcon, + isLoading: isSaving, + disabled: isSaving || + !isValid || + (workingConfig.length === 0 && workingModuleConfig.length === 0), + iconClasses: !isValid ? "text-red-400 cursor-not-allowed" : "", + onClick: handleSave, + label: t("common:button.save"), + }, + ], [ + activeConfigSection, + isSaving, + isValid, + buttonOpacity, + workingConfig, + workingModuleConfig, + ]); + return ( <> { label={activeConfigSection === "device" ? t("navigation.radioConfig") : t("navigation.moduleConfig")} - actions={[ - { - key: "save", - icon: isError ? SaveOff : SaveIcon, - isLoading: isSaving, - disabled: isSaving, - iconClasses: isError ? "text-red-400 cursor-not-allowed" : "", - onClick: handleSave, - }, - ]} + actions={actions} > - {activeConfigSection === "device" ? : } + {activeConfigSection === "device" + ? + : } ); diff --git a/src/validation/config/network.ts b/src/validation/config/network.ts index 26ba9c36..cdb486b0 100644 --- a/src/validation/config/network.ts +++ b/src/validation/config/network.ts @@ -19,7 +19,7 @@ export const NetworkValidationSchema = z.object({ wifiEnabled: z.boolean(), wifiSsid: z.string().max(33), wifiPsk: z.string().max(64), - ntpServer: z.string().min(2).max(33), + ntpServer: z.string().min(0).max(33), ethEnabled: z.boolean(), addressMode: AddressModeEnum, ipv4Config: NetworkValidationIpV4ConfigSchema, diff --git a/src/validation/config/security.test.ts b/src/validation/config/security.test.ts index 08e74cce..428711c3 100644 --- a/src/validation/config/security.test.ts +++ b/src/validation/config/security.test.ts @@ -53,7 +53,7 @@ describe("RawSecuritySchema", () => { if (!result.success) { expect( result.error.issues.some((i) => - i.message === "formValidation.adminKeyRequiredWhenManaged" + i.message === "formValidation.required.managed" ), ).toBe(true); } @@ -103,7 +103,7 @@ describe("ParsedSecuritySchema", () => { if (!result.success) { expect( result.error.issues.some((i) => - i.message === "formValidation.adminKeyRequiredWhenManaged" + i.message === "formValidation.required.managed" ), ).toBe(true); } diff --git a/src/validation/config/security.ts b/src/validation/config/security.ts index 2053b085..4d7bd83a 100644 --- a/src/validation/config/security.ts +++ b/src/validation/config/security.ts @@ -7,7 +7,7 @@ const { isValidKey, } = makePskHelpers([32]); // 256-bit -const isManagedRequiredMsg = "formValidation.adminKeyRequiredWhenManaged"; +const isManagedRequiredMsg = "formValidation.required.managed"; function makeSecuritySchema( keyMaker: (optional: boolean) => ZodType, diff --git a/src/validation/moduleConfig/mqtt.ts b/src/validation/moduleConfig/mqtt.ts index 638f076f..fe47c93d 100644 --- a/src/validation/moduleConfig/mqtt.ts +++ b/src/validation/moduleConfig/mqtt.ts @@ -1,8 +1,8 @@ import { z } from "zod/v4"; export const MqttValidationMapReportSettingsSchema = z.object({ - publishIntervalSecs: z.number().optional(), - positionPrecision: z.number().optional(), + publishIntervalSecs: z.coerce.number().int(), + positionPrecision: z.coerce.number().int(), }); export const MqttValidationSchema = z.object({ From 0e6a4818ea45c16e04cfea7791b1bad068e1786d Mon Sep 17 00:00:00 2001 From: Jeremy Gallant <8975765+philon-@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:48:41 +0200 Subject: [PATCH 18/37] fix: Crowdin upload sources action (#672) * Fix Crowdin upload sources action * Replace biome with deno in vscode extension recommendations --------- Co-authored-by: philon- --- .github/workflows/crowdin-upload-sources.yml | 22 ++++++++++---------- .vscode/extensions.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/crowdin-upload-sources.yml b/.github/workflows/crowdin-upload-sources.yml index 4f77f1b3..882f73c7 100644 --- a/.github/workflows/crowdin-upload-sources.yml +++ b/.github/workflows/crowdin-upload-sources.yml @@ -5,9 +5,9 @@ on: # Monitor all .json files within the /src/i18n/locales/en/ directory. # This ensures the workflow triggers if any the English namespace files are modified on the main branch. paths: - - '/src/i18n/locales/en/**/*.json' - branches: [ main ] - workflow_dispatch: # Allow manual triggering + - "/src/i18n/locales/en/*.json" + branches: [main] + workflow_dispatch: # Allow manual triggering jobs: synchronize-with-crowdin: @@ -20,13 +20,13 @@ jobs: - name: Upload sources with Crowdin uses: crowdin/github-action@v2 with: - base_url: 'https://meshtastic.crowdin.com/api/v2' - config: 'crowdin.yml' - upload_sources: true - upload_translations: false - download_translations: false - crowdin_branch_name: 'main' - + base_url: "https://meshtastic.crowdin.com/api/v2" + config: "crowdin.yml" + upload_sources: true + upload_translations: false + download_translations: false + crowdin_branch_name: "main" + env: CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} \ No newline at end of file + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e11f647b..15b1f6c5 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["bradlc.vscode-tailwindcss", "biomejs.biome"] + "recommendations": ["bradlc.vscode-tailwindcss", "denoland.vscode-deno"] } From ec9b299b37eba06e43773810e0251a68bbd9fee1 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Wed, 18 Jun 2025 16:25:14 -0400 Subject: [PATCH 19/37] fix: add missing i18n strings (#671) * fix: added required i18n labels to UI * added node i18n * updated tests * updated path to match github action --- crowdin.yml | 2 +- src/components/Form/DynamicForm.tsx | 2 +- src/components/Map.tsx | 9 +- .../Messages/MessageInput.test.tsx | 24 ++-- .../PageComponents/Messages/MessageInput.tsx | 4 +- .../PageComponents/Messages/MessageItem.tsx | 16 +-- src/components/UI/Avatar.tsx | 4 +- src/components/UI/Generator.tsx | 34 ++++- src/components/generic/TimeAgo.tsx | 134 +++++++++++++----- src/core/hooks/useFavoriteNode.test.ts | 6 +- src/core/hooks/useFavoriteNode.ts | 14 +- src/core/hooks/useIgnoreNode.ts | 15 +- src/i18n/config.ts | 6 +- src/i18n/locales/en/common.json | 10 +- src/i18n/locales/en/messages.json | 39 +++-- src/i18n/locales/en/nodes.json | 15 +- src/i18n/locales/en/ui.json | 18 +++ src/pages/Messages.tsx | 17 ++- src/pages/Nodes/index.tsx | 9 +- 19 files changed, 267 insertions(+), 111 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index 14d994ec..d32b8047 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -6,5 +6,5 @@ base_url: "https://meshtastic.crowdin.com/api/v2" preserve_hierarchy: true files: - - source: "/src/i18n/locales/en/**/*.json" + - source: "/src/i18n/locales/en/*.json" translation: "/src/i18n/locales/%locale%/%original_file_name%" diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index 3fe802d6..2012b443 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -208,7 +208,7 @@ export function DynamicForm({ variant="outline" disabled={!formState.isValid} > - Submit + {t("button.submit")} )} diff --git a/src/components/Map.tsx b/src/components/Map.tsx index 9a3946f5..a121fb6e 100644 --- a/src/components/Map.tsx +++ b/src/components/Map.tsx @@ -1,6 +1,5 @@ import MapGl, { AttributionControl, - GeolocateControl, type MapRef, NavigationControl, ScaleControl, @@ -45,11 +44,15 @@ export const Map = ({ children, onLoad }: MapProps) => { color: darkMode ? "black" : undefined, }} /> - + /> */ + } {children} diff --git a/src/components/PageComponents/Messages/MessageInput.test.tsx b/src/components/PageComponents/Messages/MessageInput.test.tsx index 2c88c1cc..0ddb8531 100644 --- a/src/components/PageComponents/Messages/MessageInput.test.tsx +++ b/src/components/PageComponents/Messages/MessageInput.test.tsx @@ -86,7 +86,7 @@ describe("MessageInput", () => { it("should render the input field, byte counter, and send button", () => { renderComponent(); - expect(screen.getByPlaceholderText("Enter Message")).toBeInTheDocument(); + expect(screen.getByTestId("message-input-field")).toBeInTheDocument(); expect(screen.getByTestId("byte-counter")).toBeInTheDocument(); expect(screen.getByRole("button")).toBeInTheDocument(); expect(screen.getByTestId("send-icon")).toBeInTheDocument(); @@ -100,10 +100,6 @@ describe("MessageInput", () => { renderComponent(); - const inputElement = screen.getByPlaceholderText( - "Enter Message", - ) as HTMLInputElement; - expect(inputElement.value).toBe(initialDraft); expect(mockGetDraft).toHaveBeenCalledWith(defaultProps.to); const expectedBytes = new Blob([initialDraft]).size; expect(screen.getByTestId("byte-counter")).toHaveTextContent( @@ -113,7 +109,7 @@ describe("MessageInput", () => { it("should update input value, byte counter, and call setDraft on change within limits", () => { renderComponent(); - const inputElement = screen.getByPlaceholderText("Enter Message"); + const inputElement = screen.getByTestId("message-input-field"); const testMessage = "Hello there!"; const expectedBytes = new Blob([testMessage]).size; @@ -130,7 +126,7 @@ describe("MessageInput", () => { it("should NOT update input value or call setDraft if maxBytes is exceeded", () => { const smallMaxBytes = 5; renderComponent({ maxBytes: smallMaxBytes }); - const inputElement = screen.getByPlaceholderText("Enter Message"); + const inputElement = screen.getByTestId("message-input-field"); const initialValue = "12345"; const excessiveValue = "123456"; @@ -150,7 +146,7 @@ describe("MessageInput", () => { it("should call onSend, clear input, reset byte counter, and call clearDraft on valid submit", async () => { renderComponent(); - const inputElement = screen.getByPlaceholderText("Enter Message"); + const inputElement = screen.getByTestId("message-input-field"); const formElement = screen.getByRole("form"); const testMessage = "Send this message"; @@ -171,7 +167,7 @@ describe("MessageInput", () => { it("should trim whitespace before calling onSend", async () => { renderComponent(); - const inputElement = screen.getByPlaceholderText("Enter Message"); + const inputElement = screen.getByTestId("message-input-field"); const formElement = screen.getByRole("form"); const testMessageWithWhitespace = " Trim me! "; const expectedTrimmedMessage = "Trim me!"; @@ -190,7 +186,7 @@ describe("MessageInput", () => { it("should not call onSend or clearDraft if input is empty on submit", async () => { renderComponent(); - const inputElement = screen.getByPlaceholderText("Enter Message"); + const inputElement = screen.getByTestId("message-input-field"); const formElement = screen.getByRole("form"); expect((inputElement as HTMLInputElement).value).toBe(""); @@ -236,10 +232,14 @@ describe("MessageInput", () => { expect(mockGetDraft).toHaveBeenCalledWith(broadcastDest); expect( - (screen.getByPlaceholderText("Enter Message") as HTMLInputElement).value, + (screen.getByTestId( + "message-input-field", + ) as HTMLInputElement).value, ).toBe("Broadcast draft"); - const inputElement = screen.getByPlaceholderText("Enter Message"); + const inputElement = screen.getByTestId( + "message-input-field", + ) as HTMLInputElement; const formElement = screen.getByRole("form"); const newMessage = "New broadcast msg"; diff --git a/src/components/PageComponents/Messages/MessageInput.tsx b/src/components/PageComponents/Messages/MessageInput.tsx index 3488e0a0..fb58bc3e 100644 --- a/src/components/PageComponents/Messages/MessageInput.tsx +++ b/src/components/PageComponents/Messages/MessageInput.tsx @@ -4,6 +4,7 @@ import type { Types } from "@meshtastic/core"; import { SendIcon } from "lucide-react"; import { startTransition, useState } from "react"; import { useMessageStore } from "@core/stores/messageStore/index.ts"; +import { useTranslation } from "react-i18next"; export interface MessageInputProps { onSend: (message: string) => void; @@ -17,6 +18,7 @@ export const MessageInput = ({ maxBytes, }: MessageInputProps) => { const { setDraft, getDraft, clearDraft } = useMessageStore(); + const { t } = useTranslation("messages"); const calculateBytes = (text: string) => new Blob([text]).size; @@ -59,7 +61,7 @@ export const MessageInput = ({ autoFocus minLength={1} name="messageInput" - placeholder="Enter Message" + placeholder={t("sendMessage.placeholder")} autoComplete="off" value={localDraft} onChange={handleInputChange} diff --git a/src/components/PageComponents/Messages/MessageItem.tsx b/src/components/PageComponents/Messages/MessageItem.tsx index ab509741..dbcfd533 100644 --- a/src/components/PageComponents/Messages/MessageItem.tsx +++ b/src/components/PageComponents/Messages/MessageItem.tsx @@ -56,21 +56,21 @@ export const MessageItem = ({ message }: MessageItemProps) => { const MESSAGE_STATUS_MAP = useMemo( (): Record => ({ [MessageState.Ack]: { - displayText: t("deliveryStatus.deliveryStatus."), + displayText: t("deliveryStatus.delivered.displayText"), icon: CheckCircle2, - ariaLabel: t("deliveryStatus.delivered"), + ariaLabel: t("deliveryStatus.delivered.label"), iconClassName: "text-green-500", }, [MessageState.Waiting]: { - displayText: t("deliveryStatus.waiting"), + displayText: t("deliveryStatus.waiting.displayText"), icon: CircleEllipsis, - ariaLabel: t("deliveryStatus.waiting"), + ariaLabel: t("deliveryStatus.waiting.label"), iconClassName: "text-slate-400", }, [MessageState.Failed]: { - displayText: t("deliveryStatus.failed"), + displayText: t("deliveryStatus.failed.displayText"), icon: AlertCircle, - ariaLabel: t("deliveryStatus.failed"), + ariaLabel: t("deliveryStatus.failed.label"), iconClassName: "text-red-500 dark:text-red-400", }, }), @@ -78,9 +78,9 @@ export const MessageItem = ({ message }: MessageItemProps) => { ); const UNKNOWN_STATUS = useMemo((): MessageStatusInfo => ({ - displayText: t("delveryStatus.unknown"), + displayText: t("delveryStatus.unknown.displayText"), icon: AlertCircle, - ariaLabel: t("deliveryStatus.unknown"), + ariaLabel: t("deliveryStatus.unknown.label"), iconClassName: "text-red-500 dark:text-red-400", }), [t]); diff --git a/src/components/UI/Avatar.tsx b/src/components/UI/Avatar.tsx index f9b0054d..f4192d64 100644 --- a/src/components/UI/Avatar.tsx +++ b/src/components/UI/Avatar.tsx @@ -114,7 +114,7 @@ export const Avatar = ({ /> - Favorite + {t("nodeDetail.favorite.label", { ns: "nodes" })} @@ -132,7 +132,7 @@ export const Avatar = ({ /> - Node error + {t("nodeDetail.error.label", { ns: "nodes" })} diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index f23cf1e3..22fa2921 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -8,6 +8,7 @@ import { SelectTrigger, SelectValue, } from "@components/UI/Select.tsx"; +import { useTranslation } from "react-i18next"; export interface ActionButton { text: string; @@ -40,12 +41,7 @@ const Generator = ( variant, value, actionButtons, - bits = [ - { text: "256 bit", value: "32", key: "bit256" }, - { text: "128 bit", value: "16", key: "bit128" }, - { text: "8 bit", value: "1", key: "bit8" }, - { text: "Empty", value: "0", key: "empty" }, - ], + bits, selectChange, inputChange, disabled, @@ -55,6 +51,30 @@ const Generator = ( }: GeneratorProps, ) => { const inputRef = useRef(null); + const { t } = useTranslation(); + + const passwordRequiredBitSize = bits ? bits : [ + { + text: t("security.256bit"), + value: "32", + key: "bit256", + }, + { + text: t("security.128bit"), + value: "16", + key: "bit128", + }, + { + text: t("security.8bit"), + value: "1", + key: "bit8", + }, + { + text: t("security.empty"), + value: "0", + key: "bit0", + }, + ]; // Invokes onChange event on the input element when the value changes from the parent component useEffect(() => { @@ -91,7 +111,7 @@ const Generator = ( - {bits.map(({ text, value, key }) => ( + {passwordRequiredBitSize.map(({ text, value, key }) => ( {text} diff --git a/src/components/generic/TimeAgo.tsx b/src/components/generic/TimeAgo.tsx index 652cd364..f5fae897 100755 --- a/src/components/generic/TimeAgo.tsx +++ b/src/components/generic/TimeAgo.tsx @@ -5,49 +5,115 @@ import { TooltipProvider, TooltipTrigger, } from "@radix-ui/react-tooltip"; +import { useEffect, useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; export interface TimeAgoProps { - timestamp: number; + timestamp: number | Date; + locale?: string; + tooltipOptions?: Intl.DateTimeFormatOptions; + className?: string; } -const getTimeAgo = ( - unixTimestamp: number, - locale: Intl.LocalesArgument = "en", -): string => { - const timestamp = new Date(unixTimestamp); - const diff = (new Date().getTime() - timestamp.getTime()) / 1000; - - const minutes = Math.floor(diff / 60); - const hours = Math.floor(minutes / 60); - const days = Math.floor(hours / 24); - const months = Math.floor(days / 30); - const years = Math.floor(months / 12); - const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" }); - - if (years > 0) { - return rtf.format(0 - years, "year"); - } - if (months > 0) { - return rtf.format(0 - months, "month"); - } - if (days > 0) { - return rtf.format(0 - days, "day"); - } - if (hours > 0) { - return rtf.format(0 - hours, "hour"); - } - if (minutes > 0) { - return rtf.format(0 - minutes, "minute"); +const TIME_UNITS: Array<[Intl.RelativeTimeFormatUnit, number]> = [ + ["year", 31536000], + ["month", 2592000], + ["day", 86400], + ["hour", 3600], + ["minute", 60], + ["second", 1], +]; + +const getRelativeTimeParts = ( + date: Date | number, +): { value: number; unit: Intl.RelativeTimeFormatUnit } => { + const diffInSeconds = (new Date(date).getTime() - Date.now()) / 1000; + + for (const [unit, secondsInUnit] of TIME_UNITS) { + if (Math.abs(diffInSeconds) >= secondsInUnit) { + const value = Math.round(diffInSeconds / secondsInUnit); + return { value, unit }; + } } - return rtf.format(Math.floor(0 - diff), "second"); + + return { value: Math.round(diffInSeconds), unit: "second" }; }; -export const TimeAgo = ({ timestamp }: TimeAgoProps) => { +const UPDATE_INTERVALS: Partial> = { + // For long-term units, an hourly update is more than sufficient. + year: 1000 * 60 * 60, + month: 1000 * 60 * 60, + + // When the unit is 'day', check hourly to catch the change to the next day. + day: 1000 * 60 * 60, + + // When the unit is 'hour', check every thiry seconds to catch the change to the next hour. + hour: 1000 * 30, + + // When the unit is 'minute', a 15-second check is a good balance. + minute: 1000 * 15, + + // For 'second', a 3-second check keeps it feeling "live" without being excessive. + second: 1000 * 3, +}; + +export const TimeAgo = ({ + timestamp, + locale: localeProp, + tooltipOptions, + className, +}: TimeAgoProps) => { + const { i18n } = useTranslation(); + const [timeAgo, setTimeAgo] = useState(""); + + const locale = useMemo( + () => + localeProp || + i18n.language || + (typeof navigator !== "undefined" ? navigator.language : "en-US"), + [localeProp, i18n.language], + ); + + const date = useMemo(() => new Date(timestamp), [timestamp]); + + const fullDate = useMemo(() => { + const defaultOptions: Intl.DateTimeFormatOptions = { + dateStyle: "full", + timeStyle: "medium", + }; + const formatter = new Intl.DateTimeFormat(locale, { + ...defaultOptions, + ...tooltipOptions, + }); + return formatter.format(date); + }, [date, locale, tooltipOptions]); + + useEffect(() => { + const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" }); + let timerId: number; + + const update = () => { + const { value, unit } = getRelativeTimeParts(date); + setTimeAgo(rtf.format(value, unit)); + + const interval = UPDATE_INTERVALS[unit] || 60000; + timerId = globalThis.setTimeout(update, interval); + }; + + update(); + + return () => { + clearTimeout(timerId); + }; + }, [date, locale]); + return ( - - {getTimeAgo(timestamp)} + + { align="center" sideOffset={5} > - {new Date(timestamp).toLocaleString()} + {fullDate} diff --git a/src/core/hooks/useFavoriteNode.test.ts b/src/core/hooks/useFavoriteNode.test.ts index 78732ace..19caf04c 100644 --- a/src/core/hooks/useFavoriteNode.test.ts +++ b/src/core/hooks/useFavoriteNode.test.ts @@ -43,7 +43,7 @@ describe("useFavoriteNode hook", () => { expect(mockUpdateFavorite).toHaveBeenCalledWith(1234, true); expect(mockGetNode).toHaveBeenCalledWith(1234); expect(mockToast).toHaveBeenCalledWith({ - title: "Added Test Node to favorites", + title: "Added Test Node to favorites.", }); }); @@ -57,7 +57,7 @@ describe("useFavoriteNode hook", () => { expect(mockUpdateFavorite).toHaveBeenCalledWith(1234, false); expect(mockGetNode).toHaveBeenCalledWith(1234); expect(mockToast).toHaveBeenCalledWith({ - title: "Removed Test Node from favorites", + title: "Removed Test Node from favorites.", }); }); @@ -74,7 +74,7 @@ describe("useFavoriteNode hook", () => { }); expect(mockToast).toHaveBeenCalledWith({ - title: "Added node to favorites", + title: "Added Node to favorites.", }); }); diff --git a/src/core/hooks/useFavoriteNode.ts b/src/core/hooks/useFavoriteNode.ts index 6bf6c808..f93779e4 100644 --- a/src/core/hooks/useFavoriteNode.ts +++ b/src/core/hooks/useFavoriteNode.ts @@ -1,6 +1,7 @@ import { useCallback } from "react"; import { useDevice } from "@core/stores/deviceStore.ts"; import { useToast } from "@core/hooks/useToast.ts"; +import { useTranslation } from "react-i18next"; interface FavoriteNodeOptions { nodeNum: number; @@ -9,6 +10,7 @@ interface FavoriteNodeOptions { export function useFavoriteNode() { const { updateFavorite, getNode } = useDevice(); + const { t } = useTranslation(); const { toast } = useToast(); const updateFavoriteCB = useCallback( @@ -19,9 +21,15 @@ export function useFavoriteNode() { updateFavorite(nodeNum, isFavorite); toast({ - title: `${isFavorite ? "Added" : "Removed"} ${ - node?.user?.longName ?? "node" - } ${isFavorite ? "to" : "from"} favorites`, + title: t("toast.favoriteNode.title", { + action: isFavorite + ? t("toast.favoriteNode.action.added") + : t("toast.favoriteNode.action.removed"), + nodeName: node?.user?.longName ?? t("node"), + direction: isFavorite + ? t("toast.favoriteNode.action.to") + : t("toast.favoriteNode.action.from"), + }), }); }, [updateFavorite, getNode], diff --git a/src/core/hooks/useIgnoreNode.ts b/src/core/hooks/useIgnoreNode.ts index 14b75974..c214bdc2 100644 --- a/src/core/hooks/useIgnoreNode.ts +++ b/src/core/hooks/useIgnoreNode.ts @@ -1,6 +1,7 @@ import { useCallback } from "react"; import { useDevice } from "@core/stores/deviceStore.ts"; import { useToast } from "@core/hooks/useToast.ts"; +import { useTranslation } from "react-i18next"; interface IgnoreNodeOptions { nodeNum: number; @@ -9,6 +10,8 @@ interface IgnoreNodeOptions { export function useIgnoreNode() { const { updateIgnored, getNode } = useDevice(); + const { t } = useTranslation(); + const { toast } = useToast(); const updateIgnoredCB = useCallback( @@ -19,9 +22,15 @@ export function useIgnoreNode() { updateIgnored(nodeNum, isIgnored); toast({ - title: `${isIgnored ? "Added" : "Removed"} ${ - node?.user?.longName ?? "node" - } ${isIgnored ? "to" : "from"} ignore list`, + title: t("toast.ignoreNode.title", { + nodeName: node?.user?.longName ?? "node", + action: isIgnored + ? t("toast.ignoreNode.action.added") + : t("toast.ignoreNode.action.removed"), + direction: isIgnored + ? t("toast.ignoreNode.action.to") + : t("toast.ignoreNode.action.from"), + }), }); }, [updateIgnored, getNode], diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 097e3791..a17a9cd9 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -41,9 +41,9 @@ i18next fallbackLng: { default: [FALLBACK_LANGUAGE_CODE], "en-GB": [FALLBACK_LANGUAGE_CODE], - "fi": ["fi-FI"], - "sv": ["sv-SE"], - "de": ["de-DE"], + "fi": ["fi-FI", FALLBACK_LANGUAGE_CODE], + "sv": ["sv-SE", FALLBACK_LANGUAGE_CODE], + "de": ["de-DE", FALLBACK_LANGUAGE_CODE], }, fallbackNS: ["common", "ui", "dialog"], debug: import.meta.env.MODE === "development", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 0fb0756b..b9ba239e 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -24,7 +24,8 @@ "reset": "Reset", "save": "Save", "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -48,6 +49,7 @@ "raw": "raw", "meter": { "one": "Meter", "plural": "Meters", "suffix": "m" }, "minute": { "one": "Minute", "plural": "Minutes" }, + "hour": { "one": "Hour", "plural": "Hours" }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -55,11 +57,16 @@ }, "second": { "one": "Second", "plural": "Seconds" }, "day": { "one": "Day", "plural": "Days" }, + "month": { "one": "Month", "plural": "Months" }, + "year": { "one": "Year", "plural": "Years" }, "snr": "SNR", "volt": { "one": "Volt", "plural": "Volts", "suffix": "V" }, "record": { "one": "Records", "plural": "Records" } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -71,6 +78,7 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { "unsavedChanges": "Unsaved changes", "tooBig": { diff --git a/src/i18n/locales/en/messages.json b/src/i18n/locales/en/messages.json index 4df0ac92..07d60e57 100644 --- a/src/i18n/locales/en/messages.json +++ b/src/i18n/locales/en/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,7 +11,7 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Send" }, "actionsMenu": { @@ -18,24 +19,22 @@ "replyLabel": "Reply" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/en/nodes.json b/src/i18n/locales/en/nodes.json index 5202f039..b63e90c4 100644 --- a/src/i18n/locales/en/nodes.json +++ b/src/i18n/locales/en/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favorite" + "label": "Favorite", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Error", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,13 @@ "lastHeardStatus": { "never": "Never" } + }, + + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/en/ui.json b/src/i18n/locales/en/ui.json index 0f5aa51f..daab3891 100644 --- a/src/i18n/locales/en/ui.json +++ b/src/i18n/locales/en/ui.json @@ -66,6 +66,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 6a13fb35..96bb7b0e 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -306,13 +306,16 @@ export const MessagesPage = () => { return ( { const { t } = useTranslation("nodes"); + const { currentLanguage } = useLang(); const { getNodes, hardware, connection, hasNodeError, setDialogOpen } = useDevice(); const { setNodeNumDetails } = useAppStore(); @@ -168,7 +170,12 @@ const NodesPage = (): JSX.Element => { {node.lastHeard === 0 ?

{t("nodesTable.lastHeardStatus.never")}

- : } + : ( + + )}
), sortValue: node.lastHeard, From bb91350ef5c6fa45180ffe0a1ecf148fa2fb24cb Mon Sep 17 00:00:00 2001 From: Jeremy Gallant <8975765+philon-@users.noreply.github.com> Date: Wed, 18 Jun 2025 22:39:14 +0200 Subject: [PATCH 20/37] fix: Crash when navigator.serial is undefined (#670) * Fix crash when navigator.serial is undefined * Change value --------- Co-authored-by: philon- --- src/components/Dialog/NewDeviceDialog.tsx | 112 +++++++++++----------- src/i18n/locales/en/dialog.json | 3 +- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/components/Dialog/NewDeviceDialog.tsx b/src/components/Dialog/NewDeviceDialog.tsx index f821c05b..eb25e185 100644 --- a/src/components/Dialog/NewDeviceDialog.tsx +++ b/src/components/Dialog/NewDeviceDialog.tsx @@ -18,9 +18,7 @@ import { TabsList, TabsTrigger, } from "@components/UI/Tabs.tsx"; -import { Subtle } from "@components/UI/Typography/Subtle.tsx"; import { AlertCircle } from "lucide-react"; -import { useMemo } from "react"; import { Trans, useTranslation } from "react-i18next"; import { Link } from "../UI/Typography/Link.tsx"; @@ -29,6 +27,7 @@ export interface TabElementProps { } export interface TabManifest { + id: "HTTP" | "BLE" | "Serial"; label: string; element: React.FC; isDisabled: boolean; @@ -41,29 +40,28 @@ export interface NewDeviceProps { interface FeatureErrorProps { missingFeatures: BrowserFeature[]; + tabId: "HTTP" | "BLE" | "Serial"; } -const links: { [key: string]: string } = { - "Web Bluetooth": - "https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility", - "Web Serial": - "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", - "Secure Context": - "https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts", +const errors: Record = { + "Web Bluetooth": { + href: + "https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility", + i18nKey: "newDeviceDialog.validation.requiresWebBluetooth", + }, + "Web Serial": { + href: + "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", + i18nKey: "newDeviceDialog.validation.requiresWebSerial", + }, + "Secure Context": { + href: + "https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts", + i18nKey: "newDeviceDialog.validation.requiresSecureContext", + }, }; -const ErrorMessage = ({ missingFeatures }: FeatureErrorProps) => { - const { i18n } = useTranslation("dialog"); - - const listFormatter = useMemo( - () => - new Intl.ListFormat(i18n.language, { - style: "long", - type: "disjunction", - }), - [i18n.language], - ); - +const ErrorMessage = ({ missingFeatures, tabId }: FeatureErrorProps) => { if (missingFeatures.length === 0) return null; const browserFeatures = missingFeatures.filter( @@ -71,37 +69,32 @@ const ErrorMessage = ({ missingFeatures }: FeatureErrorProps) => { ); const needsSecureContext = missingFeatures.includes("Secure Context"); - const formatFeatureList = (features: string[]) => { - const parts = listFormatter.formatToParts(features); - return parts.map((part) => { - if (part.type === "element") { - return ( - - {part.value} - - ); - } - return {part.value}; - }); - }; - - const featureNodes = formatFeatureList(browserFeatures); + const needsFeature = + (tabId === "BLE" && browserFeatures.includes("Web Bluetooth")) + ? "Web Bluetooth" + : (tabId === "Serial" && browserFeatures.includes("Web Serial")) + ? "Web Serial" + : undefined; return ( - +
-

- {browserFeatures.length > 0 && ( +

+ {needsFeature && ( {featureNodes}, - }} + i18nKey={errors[needsFeature].i18nKey} + components={[ + , + ]} /> )} - {browserFeatures.length > 0 && needsSecureContext && " "} + {needsFeature && needsSecureContext && " "} {needsSecureContext && ( 0 @@ -110,17 +103,17 @@ const ErrorMessage = ({ missingFeatures }: FeatureErrorProps) => { components={{ "0": ( ), }} /> )} -

+
- +
); }; @@ -133,17 +126,20 @@ export const NewDeviceDialog = ({ const tabs: TabManifest[] = [ { + id: "HTTP", label: t("newDeviceDialog.tabHttp"), element: HTTP, isDisabled: false, }, { + id: "BLE", label: t("newDeviceDialog.tabBluetooth"), element: BLE, isDisabled: unsupported.includes("Web Bluetooth") || unsupported.includes("Secure Context"), }, { + id: "Serial", label: t("newDeviceDialog.tabSerial"), element: Serial, isDisabled: unsupported.includes("Web Serial") || @@ -161,21 +157,27 @@ export const NewDeviceDialog = ({ {tabs.map((tab) => ( - + {tab.label} ))} {tabs.map((tab) => ( - +
- {(tab.label !== "HTTP" && + {(tab.id !== "HTTP" && tab.isDisabled) - ? - : null} - onOpenChange(false)} - /> + ? ( + + ) + : ( + onOpenChange(false)} + /> + )}
))} diff --git a/src/i18n/locales/en/dialog.json b/src/i18n/locales/en/dialog.json index ddf1f352..a6cc54af 100644 --- a/src/i18n/locales/en/dialog.json +++ b/src/i18n/locales/en/dialog.json @@ -64,7 +64,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } From 762aed50b748adfa0dcaa1b9aa83ef595a77c407 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Wed, 18 Jun 2025 21:08:56 -0400 Subject: [PATCH 21/37] Updated button styling on config header (#673) * fix: updated button in config * Update src/pages/Config/index.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/PageLayout.tsx | 3 +-- src/pages/Config/index.tsx | 48 +++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/components/PageLayout.tsx b/src/components/PageLayout.tsx index 534ab71a..7a8c1eee 100644 --- a/src/components/PageLayout.tsx +++ b/src/components/PageLayout.tsx @@ -80,8 +80,7 @@ export const PageLayout = ({ disabled={action.disabled || action.isLoading} className={cn( "flex items-center space-x-2 py-2 px-3 rounded-md", - "text-foreground transition-colors hover:text-accent", - "hover:bg-slate-200 disabled:hover:bg-white", + "text-foreground transition-colors duration-200", "disabled:opacity-50 disabled:cursor-not-allowed", action.className, )} diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx index 98725b0f..c1171739 100644 --- a/src/pages/Config/index.tsx +++ b/src/pages/Config/index.tsx @@ -144,19 +144,23 @@ const ConfigPage = () => { [activeConfigSection, workingConfig, workingModuleConfig], ); - const buttonOpacity = useMemo( - () => (formMethods?.formState.isDirty && - Object.keys(formMethods?.formState.dirtyFields ?? {}).length > 0 || - workingConfig.length > 0 || workingModuleConfig.length > 0 - ? "opacity-100" - : "opacity-0"), - [ - formMethods?.formState.isDirty, - formMethods?.formState.dirtyFields, - workingConfig, - workingModuleConfig, - ], - ); + const buttonOpacity = useMemo(() => { + const isFormDirty = formMethods?.formState.isDirty ?? false; + const hasDirtyFields = + (Object.keys(formMethods?.formState.dirtyFields ?? {}).length ?? 0) > 0; + const hasWorkingConfig = workingConfig.length > 0; + const hasWorkingModuleConfig = workingModuleConfig.length > 0; + + const shouldShowButton = (isFormDirty && hasDirtyFields) || + hasWorkingConfig || hasWorkingModuleConfig; + + return shouldShowButton ? "opacity-100" : "opacity-0"; + }, [ + formMethods?.formState.isDirty, + formMethods?.formState.dirtyFields, + workingConfig, + workingModuleConfig, + ]); const isValid = useMemo(() => { return Object.keys(formMethods?.formState.errors ?? {}).length === 0; @@ -168,7 +172,8 @@ const ConfigPage = () => { label: t("common:formValidation.unsavedChanges"), onClick: () => {}, className: cn([ - "bg-blue-500 hover:bg-blue-500 text-white hover:text-white", + "bg-blue-500 text-slate-900 hover:bg-initial", + "transition-colors duration-200", buttonOpacity, "transition-opacity", ]), @@ -178,7 +183,11 @@ const ConfigPage = () => { icon: RefreshCwIcon, label: t("common:button.reset"), onClick: handleReset, - className: cn([buttonOpacity, "transition-opacity"]), + className: cn([ + buttonOpacity, + "transition-opacity hover:bg-slate-200 disabled:hover:bg-white", + "hover:dark:bg-slate-300 hover:dark:text-black cursor-pointer", + ]), }, { key: "save", @@ -187,7 +196,14 @@ const ConfigPage = () => { disabled: isSaving || !isValid || (workingConfig.length === 0 && workingModuleConfig.length === 0), - iconClasses: !isValid ? "text-red-400 cursor-not-allowed" : "", + iconClasses: !isValid + ? "text-red-400 cursor-not-allowed" + : "cursor-pointer", + className: cn([ + "transition-opacity hover:bg-slate-200 disabled:hover:bg-white", + "hover:dark:bg-slate-300 hover:dark:text-black", + disabled ? "cursor-not-allowed" : "cursor-pointer", + ]), onClick: handleSave, label: t("common:button.save"), }, From c6a564f7e42ac2f1a42253cf88a672d90d448986 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Fri, 20 Jun 2025 12:39:11 -0400 Subject: [PATCH 22/37] fix: style on config page (#674) --- src/pages/Config/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx index c1171739..224dfdb7 100644 --- a/src/pages/Config/index.tsx +++ b/src/pages/Config/index.tsx @@ -202,7 +202,7 @@ const ConfigPage = () => { className: cn([ "transition-opacity hover:bg-slate-200 disabled:hover:bg-white", "hover:dark:bg-slate-300 hover:dark:text-black", - disabled ? "cursor-not-allowed" : "cursor-pointer", + "disabled:hover:cursor-not-allowed cursor-pointer", ]), onClick: handleSave, label: t("common:button.save"), From 43143bfdf6ad636f38275b3addb7ae14cbdcc84b Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 21 Jun 2025 23:08:25 -0400 Subject: [PATCH 23/37] Device Name dialog validation (#676) * fix: style on config page * feat: added device name validation * Update src/i18n/locales/en/dialog.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/components/Dialog/DeviceNameDialog.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/components/Dialog/DeviceNameDialog.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fixed typo --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- deno.lock | 1369 +++++++++-------- package.json | 3 +- public/site.webmanifest | 6 +- src/components/Dialog/DeviceNameDialog.tsx | 58 +- .../UnsafeRolesDialog/UnsafeRolesDialog.tsx | 4 +- src/components/Form/FormInput.tsx | 39 +- src/components/PageComponents/Connect/BLE.tsx | 1 - src/i18n/locales/en/dialog.json | 21 +- 8 files changed, 769 insertions(+), 732 deletions(-) diff --git a/deno.lock b/deno.lock index d63863ec..f58ee462 100644 --- a/deno.lock +++ b/deno.lock @@ -1,103 +1,98 @@ { "version": "5", "specifiers": { - "jsr:@std/path@*": "1.0.6", "jsr:@std/path@^1.1.0": "1.1.0", - "npm:@bufbuild/protobuf@^2.2.5": "2.2.5", - "npm:@jsr/meshtastic__core@2.6.2": "2.6.2", + "npm:@bufbuild/protobuf@^2.2.5": "2.5.2", + "npm:@hookform/resolvers@^5.1.1": "5.1.1_react-hook-form@7.58.1__react@19.1.0_react@19.1.0", "npm:@jsr/meshtastic__core@2.6.4": "2.6.4", "npm:@jsr/meshtastic__js@2.6.0-0": "2.6.0-0", "npm:@jsr/meshtastic__transport-http@*": "0.2.1", - "npm:@jsr/meshtastic__transport-web-bluetooth@*": "0.1.1", + "npm:@jsr/meshtastic__transport-web-bluetooth@*": "0.1.2", "npm:@jsr/meshtastic__transport-web-serial@*": "0.2.1", - "npm:@noble/curves@^1.9.0": "1.9.0", - "npm:@radix-ui/react-accordion@^1.2.8": "1.2.8_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-checkbox@^1.2.3": "1.2.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-dialog@^1.1.11": "1.1.11_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-dropdown-menu@^2.1.12": "2.1.12_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-label@^2.1.4": "2.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-menubar@^1.1.12": "1.1.12_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-popover@^1.1.11": "1.1.11_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-scroll-area@^1.2.6": "1.2.6_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-select@^2.2.2": "2.2.2_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-separator@^1.1.4": "1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-slider@^1.3.2": "1.3.2_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-switch@^1.2.2": "1.2.2_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-tabs@^1.1.9": "1.1.9_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-toast@^1.2.11": "1.2.11_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-toggle-group@^1.1.9": "1.1.10_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-tooltip@^1.2.4": "1.2.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tailwindcss/postcss@^4.1.5": "4.1.5", - "npm:@tanstack/react-router-devtools@^1.120.16": "1.120.16_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_solid-js@1.9.7__seroval@1.3.2", - "npm:@tanstack/react-router@^1.120.15": "1.120.15_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-devtools@^1.120.15": "1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-plugin@^1.120.15": "1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@babel+core@7.27.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.3", + "npm:@noble/curves@^1.9.0": "1.9.2", + "npm:@radix-ui/react-accordion@^1.2.8": "1.2.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-checkbox@^1.2.3": "1.3.2_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-dialog@^1.1.11": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-dropdown-menu@^2.1.12": "2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-label@^2.1.4": "2.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-menubar@^1.1.12": "1.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-popover@^1.1.11": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-scroll-area@^1.2.6": "1.2.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-select@^2.2.2": "2.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-separator@^1.1.4": "1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-slider@^1.3.2": "1.3.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-switch@^1.2.2": "1.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-tabs@^1.1.9": "1.1.12_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-toast@^1.2.11": "1.2.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-toggle-group@^1.1.9": "1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-tooltip@^1.2.4": "1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tailwindcss/postcss@^4.1.5": "4.1.10", + "npm:@tanstack/react-router-devtools@^1.120.16": "1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/react-router@^1.120.15": "1.121.27_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/router-devtools@^1.120.15": "1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/router-plugin@^1.120.15": "1.121.29_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.32", "npm:@testing-library/jest-dom@^6.6.3": "6.6.3", - "npm:@testing-library/react@^16.3.0": "16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@testing-library/react@^16.3.0": "16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:@testing-library/user-event@^14.6.1": "14.6.1_@testing-library+dom@10.4.0", "npm:@turf/turf@^7.2.0": "7.2.0", "npm:@types/chrome@^0.0.318": "0.0.318", "npm:@types/js-cookie@^3.0.6": "3.0.6", - "npm:@types/node@^22.15.3": "22.15.3", - "npm:@types/react-dom@^19.1.3": "19.1.3_@types+react@19.1.2", - "npm:@types/react@^19.1.2": "19.1.2", + "npm:@types/node@^22.15.3": "22.15.32", + "npm:@types/react-dom@^19.1.3": "19.1.6_@types+react@19.1.8", + "npm:@types/react@^19.1.2": "19.1.8", "npm:@types/serviceworker@^0.0.133": "0.0.133", "npm:@types/w3c-web-serial@*": "1.0.8", "npm:@types/w3c-web-serial@^1.0.8": "1.0.8", "npm:@types/web-bluetooth@*": "0.0.21", "npm:@types/web-bluetooth@^0.0.21": "0.0.21", - "npm:@vitejs/plugin-react@^4.4.1": "4.4.1_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@babel+core@7.27.1_@types+node@22.15.3", - "npm:autoprefixer@^10.4.21": "10.4.21_postcss@8.5.3", + "npm:@vitejs/plugin-react@^4.4.1": "4.5.2_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_@types+node@22.15.32", + "npm:autoprefixer@^10.4.21": "10.4.21_postcss@8.5.6", "npm:base64-js@^1.5.1": "1.5.1", "npm:class-variance-authority@~0.7.1": "0.7.1", "npm:clsx@^2.1.1": "2.1.1", - "npm:cmdk@^1.1.1": "1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2", + "npm:cmdk@^1.1.1": "1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8", "npm:crypto-random-string@5": "5.0.0", "npm:gzipper@^8.2.1": "8.2.1", - "npm:happy-dom@^17.4.6": "17.4.6", - "npm:i18next-browser-languagedetector@^8.1.0": "8.1.0", + "npm:happy-dom@^17.4.6": "17.6.3", + "npm:i18next-browser-languagedetector@^8.1.0": "8.2.0", "npm:i18next-http-backend@^3.0.2": "3.0.2", - "npm:i18next@^25.2.0": "25.2.0_typescript@5.8.3", - "npm:idb-keyval@^6.2.1": "6.2.1", + "npm:i18next@^25.2.0": "25.2.1_typescript@5.8.3", + "npm:idb-keyval@^6.2.1": "6.2.2", "npm:immer@^10.1.1": "10.1.1", "npm:js-cookie@^3.0.5": "3.0.5", "npm:lucide-react@0.507": "0.507.0_react@19.1.0", "npm:maplibre-gl@5.4.0": "5.4.0", - "npm:postcss@^8.5.3": "8.5.3", + "npm:postcss@^8.5.3": "8.5.6", "npm:react-dom@^19.1.0": "19.1.0_react@19.1.0", "npm:react-error-boundary@6": "6.0.0_react@19.1.0", - "npm:react-hook-form@^7.56.2": "7.56.2_react@19.1.0", - "npm:react-i18next@^15.5.1": "15.5.1_i18next@25.2.0__typescript@5.8.3_react@19.1.0_typescript@5.8.3", + "npm:react-hook-form@^7.56.2": "7.58.1_react@19.1.0", + "npm:react-i18next@^15.5.1": "15.5.3_i18next@25.2.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3", "npm:react-map-gl@8.0.4": "8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:react-qrcode-logo@3": "3.0.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:react@^19.1.0": "19.1.0", "npm:rfc4648@^1.5.4": "1.5.4", "npm:simple-git-hooks@^2.13.0": "2.13.0", - "npm:tailwind-merge@^3.2.0": "3.2.0", - "npm:tailwindcss-animate@^1.0.7": "1.0.7_tailwindcss@4.1.5", - "npm:tailwindcss@^4.1.5": "4.1.5", + "npm:tailwind-merge@^3.2.0": "3.3.1", + "npm:tailwindcss-animate@^1.0.7": "1.0.7_tailwindcss@4.1.10", + "npm:tailwindcss@^4.1.5": "4.1.10", "npm:tar@^7.4.3": "7.4.3", "npm:testing-library@^0.0.2": "0.0.2_@angular+common@6.1.10__@angular+core@6.1.10___rxjs@6.6.7___zone.js@0.8.29__rxjs@6.6.7_@angular+core@6.1.10__rxjs@6.6.7__zone.js@0.8.29", "npm:typescript@^5.8.3": "5.8.3", - "npm:vite-plugin-pwa@1": "1.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.1__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.3", - "npm:vite-plugin-static-copy@3": "3.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3", - "npm:vite@^6.3.4": "6.3.4_@types+node@22.15.3_picomatch@4.0.2", - "npm:vitest@^3.1.2": "3.1.2_@types+node@22.15.3_happy-dom@17.4.6_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2", - "npm:zod@^3.25.0": "3.25.49", - "npm:zod@^3.25.62": "3.25.62", - "npm:zustand@5.0.5": "5.0.5_@types+react@19.1.2_immer@10.1.1_react@19.1.0" + "npm:vite-plugin-pwa@1": "1.0.0_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.4__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.32", + "npm:vite-plugin-static-copy@3": "3.0.2_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32", + "npm:vite@^6.3.4": "6.3.5_@types+node@22.15.32_picomatch@4.0.2", + "npm:vitest@^3.1.2": "3.2.4_@types+node@22.15.32_happy-dom@17.6.3_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2", + "npm:zod@^3.25.62": "3.25.67", + "npm:zustand@5.0.5": "5.0.5_@types+react@19.1.8_immer@10.1.1_react@19.1.0" }, "jsr": { - "@std/path@1.0.6": { - "integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed" - }, "@std/path@1.1.0": { "integrity": "ddc94f8e3c275627281cbc23341df6b8bcc874d70374f75fec2533521e3d6886" } }, "npm": { - "@adobe/css-tools@4.4.2": { - "integrity": "sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==" + "@adobe/css-tools@4.4.3": { + "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==" }, "@alloc/quick-lru@5.2.0": { "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" @@ -138,15 +133,15 @@ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": [ "@babel/helper-validator-identifier", - "js-tokens", + "js-tokens@4.0.0", "picocolors" ] }, - "@babel/compat-data@7.27.1": { - "integrity": "sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A==" + "@babel/compat-data@7.27.5": { + "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==" }, - "@babel/core@7.27.1": { - "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", + "@babel/core@7.27.4": { + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dependencies": [ "@ampproject/remapping", "@babel/code-frame", @@ -165,8 +160,8 @@ "semver" ] }, - "@babel/generator@7.27.1": { - "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "@babel/generator@7.27.5": { + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", "dependencies": [ "@babel/parser", "@babel/types", @@ -175,14 +170,14 @@ "jsesc@3.1.0" ] }, - "@babel/helper-annotate-as-pure@7.27.1": { - "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", + "@babel/helper-annotate-as-pure@7.27.3": { + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dependencies": [ "@babel/types" ] }, - "@babel/helper-compilation-targets@7.27.1": { - "integrity": "sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g==", + "@babel/helper-compilation-targets@7.27.2": { + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dependencies": [ "@babel/compat-data", "@babel/helper-validator-option", @@ -191,7 +186,7 @@ "semver" ] }, - "@babel/helper-create-class-features-plugin@7.27.1_@babel+core@7.27.1": { + "@babel/helper-create-class-features-plugin@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", "dependencies": [ "@babel/core", @@ -204,7 +199,7 @@ "semver" ] }, - "@babel/helper-create-regexp-features-plugin@7.27.1_@babel+core@7.27.1": { + "@babel/helper-create-regexp-features-plugin@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", "dependencies": [ "@babel/core", @@ -213,7 +208,7 @@ "semver" ] }, - "@babel/helper-define-polyfill-provider@0.6.4_@babel+core@7.27.1": { + "@babel/helper-define-polyfill-provider@0.6.4_@babel+core@7.27.4": { "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", "dependencies": [ "@babel/core", @@ -238,8 +233,8 @@ "@babel/types" ] }, - "@babel/helper-module-transforms@7.27.1_@babel+core@7.27.1": { - "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "@babel/helper-module-transforms@7.27.3_@babel+core@7.27.4": { + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dependencies": [ "@babel/core", "@babel/helper-module-imports", @@ -256,7 +251,7 @@ "@babel/helper-plugin-utils@7.27.1": { "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==" }, - "@babel/helper-remap-async-to-generator@7.27.1_@babel+core@7.27.1": { + "@babel/helper-remap-async-to-generator@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", "dependencies": [ "@babel/core", @@ -265,7 +260,7 @@ "@babel/traverse" ] }, - "@babel/helper-replace-supers@7.27.1_@babel+core@7.27.1": { + "@babel/helper-replace-supers@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", "dependencies": [ "@babel/core", @@ -298,21 +293,21 @@ "@babel/types" ] }, - "@babel/helpers@7.27.1": { - "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "@babel/helpers@7.27.6": { + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dependencies": [ "@babel/template", "@babel/types" ] }, - "@babel/parser@7.27.1": { - "integrity": "sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==", + "@babel/parser@7.27.5": { + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dependencies": [ "@babel/types" ], "bin": true }, - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", "dependencies": [ "@babel/core", @@ -320,21 +315,21 @@ "@babel/traverse" ] }, - "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dependencies": [ "@babel/core", @@ -343,7 +338,7 @@ "@babel/plugin-transform-optional-chaining" ] }, - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", "dependencies": [ "@babel/core", @@ -351,41 +346,41 @@ "@babel/traverse" ] }, - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2_@babel+core@7.27.1": { + "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2_@babel+core@7.27.4": { "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dependencies": [ "@babel/core" ] }, - "@babel/plugin-syntax-import-assertions@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-syntax-import-assertions@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-syntax-import-attributes@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-syntax-import-attributes@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-syntax-typescript@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-syntax-typescript@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-syntax-unicode-sets-regex@7.18.6_@babel+core@7.27.1": { + "@babel/plugin-syntax-unicode-sets-regex@7.18.6_@babel+core@7.27.4": { "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dependencies": [ "@babel/core", @@ -393,14 +388,14 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-arrow-functions@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-arrow-functions@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-async-generator-functions@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-async-generator-functions@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", "dependencies": [ "@babel/core", @@ -409,7 +404,7 @@ "@babel/traverse" ] }, - "@babel/plugin-transform-async-to-generator@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-async-to-generator@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", "dependencies": [ "@babel/core", @@ -418,21 +413,21 @@ "@babel/helper-remap-async-to-generator" ] }, - "@babel/plugin-transform-block-scoped-functions@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-block-scoped-functions@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-block-scoping@7.27.1_@babel+core@7.27.1": { - "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", + "@babel/plugin-transform-block-scoping@7.27.5_@babel+core@7.27.4": { + "integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-class-properties@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-class-properties@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "dependencies": [ "@babel/core", @@ -440,7 +435,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-class-static-block@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-class-static-block@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", "dependencies": [ "@babel/core", @@ -448,7 +443,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-classes@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-classes@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", "dependencies": [ "@babel/core", @@ -460,7 +455,7 @@ "globals" ] }, - "@babel/plugin-transform-computed-properties@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-computed-properties@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", "dependencies": [ "@babel/core", @@ -468,14 +463,14 @@ "@babel/template" ] }, - "@babel/plugin-transform-destructuring@7.27.1_@babel+core@7.27.1": { - "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", + "@babel/plugin-transform-destructuring@7.27.3_@babel+core@7.27.4": { + "integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-dotall-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-dotall-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", "dependencies": [ "@babel/core", @@ -483,14 +478,14 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-duplicate-keys@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-duplicate-keys@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", "dependencies": [ "@babel/core", @@ -498,28 +493,28 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-dynamic-import@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-dynamic-import@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-exponentiation-operator@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-exponentiation-operator@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-export-namespace-from@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-export-namespace-from@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-for-of@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-for-of@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "dependencies": [ "@babel/core", @@ -527,7 +522,7 @@ "@babel/helper-skip-transparent-expression-wrappers" ] }, - "@babel/plugin-transform-function-name@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-function-name@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "dependencies": [ "@babel/core", @@ -536,35 +531,35 @@ "@babel/traverse" ] }, - "@babel/plugin-transform-json-strings@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-json-strings@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-literals@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-literals@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-logical-assignment-operators@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-logical-assignment-operators@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-member-expression-literals@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-member-expression-literals@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-modules-amd@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-modules-amd@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dependencies": [ "@babel/core", @@ -572,7 +567,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-modules-commonjs@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-modules-commonjs@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "dependencies": [ "@babel/core", @@ -580,7 +575,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-modules-systemjs@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-modules-systemjs@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", "dependencies": [ "@babel/core", @@ -590,7 +585,7 @@ "@babel/traverse" ] }, - "@babel/plugin-transform-modules-umd@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-modules-umd@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dependencies": [ "@babel/core", @@ -598,7 +593,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-named-capturing-groups-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-named-capturing-groups-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", "dependencies": [ "@babel/core", @@ -606,37 +601,38 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-new-target@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-new-target@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-nullish-coalescing-operator@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-nullish-coalescing-operator@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-numeric-separator@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-numeric-separator@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-object-rest-spread@7.27.1_@babel+core@7.27.1": { - "integrity": "sha512-/sSliVc9gHE20/7D5qsdGlq7RG5NCDTWsAhyqzGuq174EtWJoGzIu1BQ7G56eDsTcy1jseBZwv50olSdXOlGuA==", + "@babel/plugin-transform-object-rest-spread@7.27.3_@babel+core@7.27.4": { + "integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==", "dependencies": [ "@babel/core", "@babel/helper-compilation-targets", "@babel/helper-plugin-utils", + "@babel/plugin-transform-destructuring", "@babel/plugin-transform-parameters" ] }, - "@babel/plugin-transform-object-super@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-object-super@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dependencies": [ "@babel/core", @@ -644,14 +640,14 @@ "@babel/helper-replace-supers" ] }, - "@babel/plugin-transform-optional-catch-binding@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-optional-catch-binding@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-optional-chaining@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-optional-chaining@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", "dependencies": [ "@babel/core", @@ -659,14 +655,14 @@ "@babel/helper-skip-transparent-expression-wrappers" ] }, - "@babel/plugin-transform-parameters@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-parameters@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-private-methods@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-private-methods@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", "dependencies": [ "@babel/core", @@ -674,7 +670,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-private-property-in-object@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-private-property-in-object@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", "dependencies": [ "@babel/core", @@ -683,35 +679,35 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-property-literals@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-property-literals@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-react-jsx-self@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-react-jsx-self@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-react-jsx-source@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-react-jsx-source@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-regenerator@7.27.1_@babel+core@7.27.1": { - "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "@babel/plugin-transform-regenerator@7.27.5_@babel+core@7.27.4": { + "integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-regexp-modifiers@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-regexp-modifiers@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", "dependencies": [ "@babel/core", @@ -719,21 +715,21 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-reserved-words@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-reserved-words@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-shorthand-properties@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-shorthand-properties@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-spread@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-spread@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", "dependencies": [ "@babel/core", @@ -741,35 +737,46 @@ "@babel/helper-skip-transparent-expression-wrappers" ] }, - "@babel/plugin-transform-sticky-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-sticky-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-template-literals@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-template-literals@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-typeof-symbol@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-typeof-symbol@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-unicode-escapes@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-typescript@7.27.1_@babel+core@7.27.4": { + "integrity": "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-create-class-features-plugin", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers", + "@babel/plugin-syntax-typescript" + ] + }, + "@babel/plugin-transform-unicode-escapes@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-unicode-property-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-unicode-property-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", "dependencies": [ "@babel/core", @@ -777,7 +784,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-unicode-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-unicode-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", "dependencies": [ "@babel/core", @@ -785,7 +792,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-unicode-sets-regex@7.27.1_@babel+core@7.27.1": { + "@babel/plugin-transform-unicode-sets-regex@7.27.1_@babel+core@7.27.4": { "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", "dependencies": [ "@babel/core", @@ -793,8 +800,8 @@ "@babel/helper-plugin-utils" ] }, - "@babel/preset-env@7.27.1_@babel+core@7.27.1": { - "integrity": "sha512-TZ5USxFpLgKDpdEt8YWBR7p6g+bZo6sHaXLqP2BY/U0acaoI8FTVflcYCr/v94twM1C5IWFdZ/hscq9WjUeLXA==", + "@babel/preset-env@7.27.2_@babel+core@7.27.4": { + "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", "dependencies": [ "@babel/compat-data", "@babel/core", @@ -868,7 +875,7 @@ "semver" ] }, - "@babel/preset-modules@0.1.6-no-external-plugins_@babel+core@7.27.1": { + "@babel/preset-modules@0.1.6-no-external-plugins_@babel+core@7.27.4": { "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dependencies": [ "@babel/core", @@ -877,19 +884,30 @@ "esutils" ] }, - "@babel/runtime@7.27.1": { - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==" + "@babel/preset-typescript@7.27.1_@babel+core@7.27.4": { + "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-validator-option", + "@babel/plugin-syntax-jsx", + "@babel/plugin-transform-modules-commonjs", + "@babel/plugin-transform-typescript" + ] + }, + "@babel/runtime@7.27.6": { + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==" }, - "@babel/template@7.27.1": { - "integrity": "sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==", + "@babel/template@7.27.2": { + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dependencies": [ "@babel/code-frame", "@babel/parser", "@babel/types" ] }, - "@babel/traverse@7.27.1": { - "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "@babel/traverse@7.27.4": { + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "dependencies": [ "@babel/code-frame", "@babel/generator", @@ -900,15 +918,15 @@ "globals" ] }, - "@babel/types@7.27.1": { - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "@babel/types@7.27.6": { + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "dependencies": [ "@babel/helper-string-parser", "@babel/helper-validator-identifier" ] }, - "@bufbuild/protobuf@2.2.5": { - "integrity": "sha512-/g5EzJifw5GF8aren8wZ/G5oMuPoGeS6MQD3ca8ddcvdXR5UELUfdTZITCGNhNXynY/AYl3Z4plmxdj/tRl/hQ==" + "@bufbuild/protobuf@2.5.2": { + "integrity": "sha512-foZ7qr0IsUBjzWIq+SuBLfdQCpJ1j8cTuNNT4owngTHoN5KsJb8L9t65fzz7SCeSWzescoOil/0ldqiL041ABg==" }, "@emnapi/core@1.4.3": { "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", @@ -929,146 +947,146 @@ "tslib@2.8.1" ] }, - "@esbuild/aix-ppc64@0.25.3": { - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "@esbuild/aix-ppc64@0.25.5": { + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", "os": ["aix"], "cpu": ["ppc64"] }, - "@esbuild/android-arm64@0.25.3": { - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "@esbuild/android-arm64@0.25.5": { + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", "os": ["android"], "cpu": ["arm64"] }, - "@esbuild/android-arm@0.25.3": { - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "@esbuild/android-arm@0.25.5": { + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", "os": ["android"], "cpu": ["arm"] }, - "@esbuild/android-x64@0.25.3": { - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "@esbuild/android-x64@0.25.5": { + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", "os": ["android"], "cpu": ["x64"] }, - "@esbuild/darwin-arm64@0.25.3": { - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "@esbuild/darwin-arm64@0.25.5": { + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", "os": ["darwin"], "cpu": ["arm64"] }, - "@esbuild/darwin-x64@0.25.3": { - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "@esbuild/darwin-x64@0.25.5": { + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", "os": ["darwin"], "cpu": ["x64"] }, - "@esbuild/freebsd-arm64@0.25.3": { - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "@esbuild/freebsd-arm64@0.25.5": { + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@esbuild/freebsd-x64@0.25.3": { - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "@esbuild/freebsd-x64@0.25.5": { + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", "os": ["freebsd"], "cpu": ["x64"] }, - "@esbuild/linux-arm64@0.25.3": { - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "@esbuild/linux-arm64@0.25.5": { + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", "os": ["linux"], "cpu": ["arm64"] }, - "@esbuild/linux-arm@0.25.3": { - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "@esbuild/linux-arm@0.25.5": { + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", "os": ["linux"], "cpu": ["arm"] }, - "@esbuild/linux-ia32@0.25.3": { - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "@esbuild/linux-ia32@0.25.5": { + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", "os": ["linux"], "cpu": ["ia32"] }, - "@esbuild/linux-loong64@0.25.3": { - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "@esbuild/linux-loong64@0.25.5": { + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", "os": ["linux"], "cpu": ["loong64"] }, - "@esbuild/linux-mips64el@0.25.3": { - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "@esbuild/linux-mips64el@0.25.5": { + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", "os": ["linux"], "cpu": ["mips64el"] }, - "@esbuild/linux-ppc64@0.25.3": { - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "@esbuild/linux-ppc64@0.25.5": { + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", "os": ["linux"], "cpu": ["ppc64"] }, - "@esbuild/linux-riscv64@0.25.3": { - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "@esbuild/linux-riscv64@0.25.5": { + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", "os": ["linux"], "cpu": ["riscv64"] }, - "@esbuild/linux-s390x@0.25.3": { - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "@esbuild/linux-s390x@0.25.5": { + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", "os": ["linux"], "cpu": ["s390x"] }, - "@esbuild/linux-x64@0.25.3": { - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "@esbuild/linux-x64@0.25.5": { + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", "os": ["linux"], "cpu": ["x64"] }, - "@esbuild/netbsd-arm64@0.25.3": { - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "@esbuild/netbsd-arm64@0.25.5": { + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", "os": ["netbsd"], "cpu": ["arm64"] }, - "@esbuild/netbsd-x64@0.25.3": { - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "@esbuild/netbsd-x64@0.25.5": { + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", "os": ["netbsd"], "cpu": ["x64"] }, - "@esbuild/openbsd-arm64@0.25.3": { - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "@esbuild/openbsd-arm64@0.25.5": { + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", "os": ["openbsd"], "cpu": ["arm64"] }, - "@esbuild/openbsd-x64@0.25.3": { - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "@esbuild/openbsd-x64@0.25.5": { + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", "os": ["openbsd"], "cpu": ["x64"] }, - "@esbuild/sunos-x64@0.25.3": { - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "@esbuild/sunos-x64@0.25.5": { + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", "os": ["sunos"], "cpu": ["x64"] }, - "@esbuild/win32-arm64@0.25.3": { - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "@esbuild/win32-arm64@0.25.5": { + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", "os": ["win32"], "cpu": ["arm64"] }, - "@esbuild/win32-ia32@0.25.3": { - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "@esbuild/win32-ia32@0.25.5": { + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", "os": ["win32"], "cpu": ["ia32"] }, - "@esbuild/win32-x64@0.25.3": { - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "@esbuild/win32-x64@0.25.5": { + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", "os": ["win32"], "cpu": ["x64"] }, - "@floating-ui/core@1.7.0": { - "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", + "@floating-ui/core@1.7.1": { + "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", "dependencies": [ "@floating-ui/utils" ] }, - "@floating-ui/dom@1.7.0": { - "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", + "@floating-ui/dom@1.7.1": { + "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", "dependencies": [ "@floating-ui/core", "@floating-ui/utils" ] }, - "@floating-ui/react-dom@2.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "@floating-ui/react-dom@2.1.3_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", "dependencies": [ "@floating-ui/dom", "react", @@ -1084,6 +1102,13 @@ "base64-js" ] }, + "@hookform/resolvers@5.1.1_react-hook-form@7.58.1__react@19.1.0_react@19.1.0": { + "integrity": "sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg==", + "dependencies": [ + "@standard-schema/utils", + "react-hook-form" + ] + }, "@isaacs/fs-minipass@4.0.1": { "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dependencies": [ @@ -1121,17 +1146,6 @@ "@jridgewell/sourcemap-codec" ] }, - "@jsr/meshtastic__core@2.6.2": { - "integrity": "sha512-mzsxs9hQeVimQd/tj15Ojw5FYY8Iko3EbDviFZoEw3bmXgiySG53GvQsNA9wV13lFbDu96SM3uK/LI3EHMFY9w==", - "dependencies": [ - "@bufbuild/protobuf", - "@jsr/meshtastic__protobufs", - "crc", - "ste-simple-events", - "tslog" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__core/2.6.2.tgz" - }, "@jsr/meshtastic__core@2.6.4": { "integrity": "sha512-1Kz5DK6peFxluHOJR38vFwfgeJzMXTz+3p6TvibjILVhSQC2U1nu8aJbn6w5zhRqS+j79OmtrRvdzL6VNsTkkQ==", "dependencies": [ @@ -1164,21 +1178,21 @@ "@jsr/meshtastic__transport-http@0.2.1": { "integrity": "sha512-lmQKr3aIINKvtGROU4HchmSVqbZSbkIHqajowRRC8IAjsnR0zNTyxz210QyY4pFUF9hpcW3GRjwq5h/VO2JuGg==", "dependencies": [ - "@jsr/meshtastic__core@2.6.2" + "@jsr/meshtastic__core" ], "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-http/0.2.1.tgz" }, - "@jsr/meshtastic__transport-web-bluetooth@0.1.1": { - "integrity": "sha512-eAj23n/Pxe8hMjO/uYbI/C+l1s0tLm41EzvcLWQtLQyEKJpPP+/Eqc5lUmDeF7FVPS2IYhllFJvV8Ili7okHtQ==", + "@jsr/meshtastic__transport-web-bluetooth@0.1.2": { + "integrity": "sha512-Z+5pv9RXNgY0/crKExOH3pZ6LT0HIXFmnBL7NX5AO2knOFRn+4lmxQEhhmiTTlkUfqyEfAvbjuY5u4mq9TPTdQ==", "dependencies": [ - "@jsr/meshtastic__core@2.6.2" + "@jsr/meshtastic__core" ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-bluetooth/0.1.1.tgz" + "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-bluetooth/0.1.2.tgz" }, "@jsr/meshtastic__transport-web-serial@0.2.1": { "integrity": "sha512-yumjEGLkAuJYOC3aWKvZzbQqi/LnqaKfNpVCY7Ki7oLtAshNiZrBLiwiFhN7+ZR9FfMdJThyBMqREBDRRWTO1Q==", "dependencies": [ - "@jsr/meshtastic__core@2.6.2" + "@jsr/meshtastic__core" ], "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-serial/0.2.1.tgz" }, @@ -1223,8 +1237,8 @@ ], "bin": true }, - "@maplibre/maplibre-gl-style-spec@23.2.2": { - "integrity": "sha512-kLcVlItPCULc20SM6pSVA7u8nST9xmQA8d7utc9j3KB0Tf/xhM4GgCn/QsZcmlbN/wW0ujyomDrvZ3/LbwvAmw==", + "@maplibre/maplibre-gl-style-spec@23.3.0": { + "integrity": "sha512-IGJtuBbaGzOUgODdBRg66p8stnwj9iDXkgbYKoYcNiiQmaez5WVRfXm4b03MCDwmZyX93csbfHFWEJJYHnn5oA==", "dependencies": [ "@mapbox/jsonlint-lines-primitives", "@mapbox/unitbezier", @@ -1236,16 +1250,16 @@ ], "bin": true }, - "@napi-rs/wasm-runtime@0.2.9": { - "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", + "@napi-rs/wasm-runtime@0.2.11": { + "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", "dependencies": [ "@emnapi/core", "@emnapi/runtime", "@tybys/wasm-util" ] }, - "@noble/curves@1.9.0": { - "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", + "@noble/curves@1.9.2": { + "integrity": "sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==", "dependencies": [ "@noble/hashes" ] @@ -1259,17 +1273,17 @@ "@radix-ui/primitive@1.1.2": { "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==" }, - "@radix-ui/react-accordion@1.2.8_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-c7OKBvO36PfQIUGIjj1Wko0hH937pYFU2tR5zbIJDUsmTzHoZVHHt4bmb7OOJbzTaWJtVELKWojBHa7OcnUHmQ==", + "@radix-ui/react-accordion@1.2.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-collapsible", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-direction", "@radix-ui/react-id", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1281,10 +1295,10 @@ "@types/react-dom" ] }, - "@radix-ui/react-arrow@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw==", + "@radix-ui/react-arrow@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", "dependencies": [ - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@types/react", "@types/react-dom", "react", @@ -1295,14 +1309,14 @@ "@types/react-dom" ] }, - "@radix-ui/react-checkbox@1.2.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-pHVzDYsnaDmBlAuwim45y3soIN8H4R7KbkSVirGhXO+R/kO2OLCe0eucUEbddaTcdMHHdzcIGHtZSMSQlA+apw==", + "@radix-ui/react-checkbox@1.3.2_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@radix-ui/react-use-previous", "@radix-ui/react-use-size", @@ -1316,15 +1330,15 @@ "@types/react-dom" ] }, - "@radix-ui/react-collapsible@1.1.8_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-hxEsLvK9WxIAPyxdDRULL4hcaSjMZCfP7fHB0Z1uUnDoDBat1Zh46hwYfa69DeZAbJrPckjf0AGAtEZyvDyJbw==", + "@radix-ui/react-collapsible@1.1.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-id", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@radix-ui/react-use-layout-effect", "@types/react", @@ -1337,30 +1351,13 @@ "@types/react-dom" ] }, - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-collection@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@radix-ui/react-collection@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", "dependencies": [ "@radix-ui/react-compose-refs", "@radix-ui/react-context", - "@radix-ui/react-primitive@2.1.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.3_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-slot", "@types/react", "@types/react-dom", "react", @@ -1371,7 +1368,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-compose-refs@1.1.2_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-compose-refs@1.1.2_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "dependencies": [ "@types/react", @@ -1381,7 +1378,7 @@ "@types/react" ] }, - "@radix-ui/react-context@1.1.2_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-context@1.1.2_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "dependencies": [ "@types/react", @@ -1391,8 +1388,8 @@ "@types/react" ] }, - "@radix-ui/react-dialog@1.1.11_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-yI7S1ipkP5/+99qhSI6nthfo/tR6bL6Zgxi/+1UO6qPa6UeM6nlafWcQ65vB4rU2XjgjMfMhI3k9Y5MztA62VQ==", + "@radix-ui/react-dialog@1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", @@ -1403,8 +1400,8 @@ "@radix-ui/react-id", "@radix-ui/react-portal", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-slot", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1418,7 +1415,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-direction@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-direction@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", "dependencies": [ "@types/react", @@ -1428,12 +1425,12 @@ "@types/react" ] }, - "@radix-ui/react-dismissable-layer@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-j5+WBUdhccJsmH5/H0K6RncjDtoALSEr6jbkaZu+bjw6hOPOhHycr6vEUujl+HBK8kjUfWcoCJXxP6e4lUlMZw==", + "@radix-ui/react-dismissable-layer@1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-callback-ref", "@radix-ui/react-use-escape-keydown", "@types/react", @@ -1446,15 +1443,15 @@ "@types/react-dom" ] }, - "@radix-ui/react-dropdown-menu@2.1.12_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-VJoMs+BWWE7YhzEQyVwvF9n22Eiyr83HotCVrMQzla/OwRovXCgah7AcaEr4hMNj4gJxSdtIbcHGvmJXOoJVHA==", + "@radix-ui/react-dropdown-menu@2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-id", "@radix-ui/react-menu", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1466,7 +1463,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-focus-guards@1.1.2_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-focus-guards@1.1.2_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", "dependencies": [ "@types/react", @@ -1476,11 +1473,11 @@ "@types/react" ] }, - "@radix-ui/react-focus-scope@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-r2annK27lIW5w9Ho5NyQgqs0MmgZSTIKXWpVCJaLC1q2kZrZkcqnmHkCHMEmv8XLvsLlurKMPT+kbKkRkm/xVA==", + "@radix-ui/react-focus-scope@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", "dependencies": [ "@radix-ui/react-compose-refs", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-callback-ref", "@types/react", "@types/react-dom", @@ -1492,7 +1489,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-id@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-id@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "dependencies": [ "@radix-ui/react-use-layout-effect", @@ -1503,10 +1500,10 @@ "@types/react" ] }, - "@radix-ui/react-label@2.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-wy3dqizZnZVV4ja0FNnUhIWNwWdoldXrneEyUcVtLYDAt8ovGS4ridtMAOGgXBBIfggL4BOveVWsjXDORdGEQg==", + "@radix-ui/react-label@2.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", "dependencies": [ - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@types/react", "@types/react-dom", "react", @@ -1517,11 +1514,11 @@ "@types/react-dom" ] }, - "@radix-ui/react-menu@2.1.12_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-+qYq6LfbiGo97Zz9fioX83HCiIYYFNs8zAsVCMQrIakoNYylIzWuoD/anAD3UzvvR6cnswmfRFJFq/zYYq/k7Q==", + "@radix-ui/react-menu@2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", "dependencies": [ "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-direction", @@ -1532,9 +1529,9 @@ "@radix-ui/react-popper", "@radix-ui/react-portal", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-roving-focus@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-roving-focus", + "@radix-ui/react-slot", "@radix-ui/react-use-callback-ref", "@types/react", "@types/react-dom", @@ -1548,18 +1545,18 @@ "@types/react-dom" ] }, - "@radix-ui/react-menubar@1.1.12_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-bM2vT5nxRqJH/d1vFQ9jLsW4qR70yFQw2ZD1TUPWUNskDsV0eYeMbbNJqxNjGMOVogEkOJaHtu11kzYdTJvVJg==", + "@radix-ui/react-menubar@1.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-Z71C7LGD+YDYo3TV81paUs8f3Zbmkvg6VLRQpKYfzioOE6n7fOhA3ApK/V/2Odolxjoc4ENk8AYCjohCNayd5A==", "dependencies": [ "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-direction", "@radix-ui/react-id", "@radix-ui/react-menu", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-roving-focus@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-roving-focus", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1571,8 +1568,8 @@ "@types/react-dom" ] }, - "@radix-ui/react-popover@1.1.11_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-yFMfZkVA5G3GJnBgb2PxrrcLKm1ZLWXrbYVgdyTl//0TYEIHS9LJbnyz7WWcZ0qCq7hIlJZpRtxeSeIG5T5oJw==", + "@radix-ui/react-popover@1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", @@ -1584,8 +1581,8 @@ "@radix-ui/react-popper", "@radix-ui/react-portal", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-slot", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1599,14 +1596,14 @@ "@types/react-dom" ] }, - "@radix-ui/react-popper@1.2.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-3p2Rgm/a1cK0r/UVkx5F/K9v/EplfjAeIFCGOPYPO4lZ0jtg4iSQXt/YGTSLWaf4x7NG6Z4+uKFcylcTZjeqDA==", + "@radix-ui/react-popper@1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", "dependencies": [ "@floating-ui/react-dom", "@radix-ui/react-arrow", "@radix-ui/react-compose-refs", "@radix-ui/react-context", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-callback-ref", "@radix-ui/react-use-layout-effect", "@radix-ui/react-use-rect", @@ -1622,10 +1619,10 @@ "@types/react-dom" ] }, - "@radix-ui/react-portal@1.1.6_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw==", + "@radix-ui/react-portal@1.1.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", "dependencies": [ - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-layout-effect", "@types/react", "@types/react-dom", @@ -1637,7 +1634,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-presence@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@radix-ui/react-presence@1.1.4_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", "dependencies": [ "@radix-ui/react-compose-refs", @@ -1652,24 +1649,10 @@ "@types/react-dom" ] }, - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==", - "dependencies": [ - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-primitive@2.1.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@radix-ui/react-primitive@2.1.3_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "dependencies": [ - "@radix-ui/react-slot@1.2.3_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-slot", "@types/react", "@types/react-dom", "react", @@ -1680,38 +1663,16 @@ "@types/react-dom" ] }, - "@radix-ui/react-roving-focus@1.1.10_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@radix-ui/react-roving-focus@1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", "dependencies": [ "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-id", - "@radix-ui/react-primitive@2.1.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-roving-focus@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-C6oAg451/fQT3EGbWHbCQjYTtbyjNO1uzQgMzwyivcHT3GKNEmu1q3UuREhN+HzHAVtv3ivMVK08QlC+PkYw9Q==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-direction", "@radix-ui/react-id", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-callback-ref", "@radix-ui/react-use-controllable-state", "@types/react", @@ -1724,8 +1685,8 @@ "@types/react-dom" ] }, - "@radix-ui/react-scroll-area@1.2.6_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-lj8OMlpPERXrQIHlEQdlXHJoRT52AMpBrgyPYylOhXYq5e/glsEdtOc/kCQlsTdtgN5U0iDbrrolDadvektJGQ==", + "@radix-ui/react-scroll-area@1.2.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==", "dependencies": [ "@radix-ui/number", "@radix-ui/primitive", @@ -1733,7 +1694,7 @@ "@radix-ui/react-context", "@radix-ui/react-direction", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-callback-ref", "@radix-ui/react-use-layout-effect", "@types/react", @@ -1746,12 +1707,12 @@ "@types/react-dom" ] }, - "@radix-ui/react-select@2.2.2_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-HjkVHtBkuq+r3zUAZ/CvNWUGKPfuicGDbgtZgiQuFmNcV5F+Tgy24ep2nsAW2nFgvhGPJVqeBZa6KyVN0EyrBA==", + "@radix-ui/react-select@2.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", "dependencies": [ "@radix-ui/number", "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-direction", @@ -1761,8 +1722,8 @@ "@radix-ui/react-id", "@radix-ui/react-popper", "@radix-ui/react-portal", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-slot", "@radix-ui/react-use-callback-ref", "@radix-ui/react-use-controllable-state", "@radix-ui/react-use-layout-effect", @@ -1780,10 +1741,10 @@ "@types/react-dom" ] }, - "@radix-ui/react-separator@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-2fTm6PSiUm8YPq9W0E4reYuv01EE3aFSzt8edBiXqPHshF8N9+Kymt/k0/R+F3dkY5lQyB/zPtrP82phskLi7w==", + "@radix-ui/react-separator@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", "dependencies": [ - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@types/react", "@types/react-dom", "react", @@ -1794,16 +1755,16 @@ "@types/react-dom" ] }, - "@radix-ui/react-slider@1.3.2_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-oQnqfgSiYkxZ1MrF6672jw2/zZvpB+PJsrIc3Zm1zof1JHf/kj7WhmROw7JahLfOwYQ5/+Ip0rFORgF1tjSiaQ==", + "@radix-ui/react-slider@1.3.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==", "dependencies": [ "@radix-ui/number", "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-direction", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@radix-ui/react-use-layout-effect", "@radix-ui/react-use-previous", @@ -1818,18 +1779,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0": { - "integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-slot@1.2.3_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-slot@1.2.3_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "dependencies": [ "@radix-ui/react-compose-refs", @@ -1840,13 +1790,13 @@ "@types/react" ] }, - "@radix-ui/react-switch@1.2.2_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-7Z8n6L+ifMIIYZ83f28qWSceUpkXuslI2FJ34+kDMTiyj91ENdpdQ7VCidrzj5JfwfZTeano/BnGBbu/jqa5rQ==", + "@radix-ui/react-switch@1.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", "@radix-ui/react-context", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@radix-ui/react-use-previous", "@radix-ui/react-use-size", @@ -1860,16 +1810,16 @@ "@types/react-dom" ] }, - "@radix-ui/react-tabs@1.1.9_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-KIjtwciYvquiW/wAFkELZCVnaNLBsYNhTNcvl+zfMAbMhRkcvNuCLXDDd22L0j7tagpzVh/QwbFpwAATg7ILPw==", + "@radix-ui/react-tabs@1.1.12_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-context", "@radix-ui/react-direction", "@radix-ui/react-id", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-roving-focus@1.1.7_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-roving-focus", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1881,17 +1831,17 @@ "@types/react-dom" ] }, - "@radix-ui/react-toast@1.2.11_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-Ed2mlOmT+tktOsu2NZBK1bCSHh/uqULu1vWOkpQTVq53EoOuZUZw7FInQoDB3uil5wZc2oe0XN9a7uVZB7/6AQ==", + "@radix-ui/react-toast@1.2.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg==", "dependencies": [ "@radix-ui/primitive", - "@radix-ui/react-collection@1.1.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-collection", "@radix-ui/react-compose-refs", "@radix-ui/react-context", "@radix-ui/react-dismissable-layer", "@radix-ui/react-portal", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-callback-ref", "@radix-ui/react-use-controllable-state", "@radix-ui/react-use-layout-effect", @@ -1906,14 +1856,14 @@ "@types/react-dom" ] }, - "@radix-ui/react-toggle-group@1.1.10_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@radix-ui/react-toggle-group@1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-kiU694Km3WFLTC75DdqgM/3Jauf3rD9wxeS9XtyWFKsBUeZA337lC+6uUazT7I1DhanZ5gyD5Stf8uf2dbQxOQ==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-context", "@radix-ui/react-direction", - "@radix-ui/react-primitive@2.1.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-roving-focus@1.1.10_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-roving-focus", "@radix-ui/react-toggle", "@radix-ui/react-use-controllable-state", "@types/react", @@ -1926,11 +1876,11 @@ "@types/react-dom" ] }, - "@radix-ui/react-toggle@1.1.9_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@radix-ui/react-toggle@1.1.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-ZoFkBBz9zv9GWer7wIjvdRxmh2wyc2oKWw6C6CseWd6/yq1DK/l5lJ+wnsmFwJZbBYqr02mrf8A2q/CVCuM3ZA==", "dependencies": [ "@radix-ui/primitive", - "@radix-ui/react-primitive@2.1.3_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@radix-ui/react-use-controllable-state", "@types/react", "@types/react-dom", @@ -1942,8 +1892,8 @@ "@types/react-dom" ] }, - "@radix-ui/react-tooltip@1.2.4_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-DyW8VVeeMSSLFvAmnVnCwvI3H+1tpJFHT50r+tdOoMse9XqYDBCcyux8u3G2y+LOpt7fPQ6KKH0mhs+ce1+Z5w==", + "@radix-ui/react-tooltip@1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", "dependencies": [ "@radix-ui/primitive", "@radix-ui/react-compose-refs", @@ -1953,8 +1903,8 @@ "@radix-ui/react-popper", "@radix-ui/react-portal", "@radix-ui/react-presence", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "@radix-ui/react-slot@1.2.0_@types+react@19.1.2_react@19.1.0", + "@radix-ui/react-primitive", + "@radix-ui/react-slot", "@radix-ui/react-use-controllable-state", "@radix-ui/react-visually-hidden", "@types/react", @@ -1967,7 +1917,7 @@ "@types/react-dom" ] }, - "@radix-ui/react-use-callback-ref@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-callback-ref@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", "dependencies": [ "@types/react", @@ -1977,7 +1927,7 @@ "@types/react" ] }, - "@radix-ui/react-use-controllable-state@1.2.2_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-controllable-state@1.2.2_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "dependencies": [ "@radix-ui/react-use-effect-event", @@ -1989,7 +1939,7 @@ "@types/react" ] }, - "@radix-ui/react-use-effect-event@0.0.2_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-effect-event@0.0.2_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", "dependencies": [ "@radix-ui/react-use-layout-effect", @@ -2000,7 +1950,7 @@ "@types/react" ] }, - "@radix-ui/react-use-escape-keydown@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-escape-keydown@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", "dependencies": [ "@radix-ui/react-use-callback-ref", @@ -2011,7 +1961,7 @@ "@types/react" ] }, - "@radix-ui/react-use-layout-effect@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-layout-effect@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "dependencies": [ "@types/react", @@ -2021,7 +1971,7 @@ "@types/react" ] }, - "@radix-ui/react-use-previous@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-previous@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", "dependencies": [ "@types/react", @@ -2031,7 +1981,7 @@ "@types/react" ] }, - "@radix-ui/react-use-rect@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-rect@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", "dependencies": [ "@radix-ui/rect", @@ -2042,7 +1992,7 @@ "@types/react" ] }, - "@radix-ui/react-use-size@1.1.1_@types+react@19.1.2_react@19.1.0": { + "@radix-ui/react-use-size@1.1.1_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", "dependencies": [ "@radix-ui/react-use-layout-effect", @@ -2053,10 +2003,10 @@ "@types/react" ] }, - "@radix-ui/react-visually-hidden@1.2.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-rQj0aAWOpCdCMRbI6pLQm8r7S2BM3YhTa0SzOYD55k+hJA8oo9J+H+9wLM9oMlZWOX/wJWPTzfDfmZkf7LvCfg==", + "@radix-ui/react-visually-hidden@1.2.3_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", "dependencies": [ - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "@types/react", "@types/react-dom", "react", @@ -2070,7 +2020,10 @@ "@radix-ui/rect@1.1.1": { "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==" }, - "@rollup/plugin-babel@5.3.1_@babel+core@7.27.1_rollup@2.79.2": { + "@rolldown/pluginutils@1.0.0-beta.11": { + "integrity": "sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==" + }, + "@rollup/plugin-babel@5.3.1_@babel+core@7.27.4_rollup@2.79.2": { "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", "dependencies": [ "@babel/core", @@ -2082,7 +2035,7 @@ "@rollup/plugin-node-resolve@15.3.1_rollup@2.79.2": { "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", "dependencies": [ - "@rollup/pluginutils@5.1.4_rollup@2.79.2", + "@rollup/pluginutils@5.2.0_rollup@2.79.2", "@types/resolve", "deepmerge", "is-module", @@ -2122,10 +2075,10 @@ "rollup@2.79.2" ] }, - "@rollup/pluginutils@5.1.4_rollup@2.79.2": { - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "@rollup/pluginutils@5.2.0_rollup@2.79.2": { + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", "dependencies": [ - "@types/estree@1.0.7", + "@types/estree@1.0.8", "estree-walker@2.0.2", "picomatch@4.0.2", "rollup@2.79.2" @@ -2134,106 +2087,109 @@ "rollup@2.79.2" ] }, - "@rollup/rollup-android-arm-eabi@4.40.1": { - "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", + "@rollup/rollup-android-arm-eabi@4.44.0": { + "integrity": "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==", "os": ["android"], "cpu": ["arm"] }, - "@rollup/rollup-android-arm64@4.40.1": { - "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", + "@rollup/rollup-android-arm64@4.44.0": { + "integrity": "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==", "os": ["android"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-arm64@4.40.1": { - "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", + "@rollup/rollup-darwin-arm64@4.44.0": { + "integrity": "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==", "os": ["darwin"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-x64@4.40.1": { - "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", + "@rollup/rollup-darwin-x64@4.44.0": { + "integrity": "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==", "os": ["darwin"], "cpu": ["x64"] }, - "@rollup/rollup-freebsd-arm64@4.40.1": { - "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", + "@rollup/rollup-freebsd-arm64@4.44.0": { + "integrity": "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@rollup/rollup-freebsd-x64@4.40.1": { - "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", + "@rollup/rollup-freebsd-x64@4.44.0": { + "integrity": "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==", "os": ["freebsd"], "cpu": ["x64"] }, - "@rollup/rollup-linux-arm-gnueabihf@4.40.1": { - "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", + "@rollup/rollup-linux-arm-gnueabihf@4.44.0": { + "integrity": "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm-musleabihf@4.40.1": { - "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", + "@rollup/rollup-linux-arm-musleabihf@4.44.0": { + "integrity": "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm64-gnu@4.40.1": { - "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", + "@rollup/rollup-linux-arm64-gnu@4.44.0": { + "integrity": "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-arm64-musl@4.40.1": { - "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", + "@rollup/rollup-linux-arm64-musl@4.44.0": { + "integrity": "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-loongarch64-gnu@4.40.1": { - "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", + "@rollup/rollup-linux-loongarch64-gnu@4.44.0": { + "integrity": "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==", "os": ["linux"], "cpu": ["loong64"] }, - "@rollup/rollup-linux-powerpc64le-gnu@4.40.1": { - "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", + "@rollup/rollup-linux-powerpc64le-gnu@4.44.0": { + "integrity": "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==", "os": ["linux"], "cpu": ["ppc64"] }, - "@rollup/rollup-linux-riscv64-gnu@4.40.1": { - "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", + "@rollup/rollup-linux-riscv64-gnu@4.44.0": { + "integrity": "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-riscv64-musl@4.40.1": { - "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", + "@rollup/rollup-linux-riscv64-musl@4.44.0": { + "integrity": "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-s390x-gnu@4.40.1": { - "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", + "@rollup/rollup-linux-s390x-gnu@4.44.0": { + "integrity": "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==", "os": ["linux"], "cpu": ["s390x"] }, - "@rollup/rollup-linux-x64-gnu@4.40.1": { - "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", + "@rollup/rollup-linux-x64-gnu@4.44.0": { + "integrity": "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-linux-x64-musl@4.40.1": { - "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", + "@rollup/rollup-linux-x64-musl@4.44.0": { + "integrity": "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-win32-arm64-msvc@4.40.1": { - "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", + "@rollup/rollup-win32-arm64-msvc@4.44.0": { + "integrity": "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==", "os": ["win32"], "cpu": ["arm64"] }, - "@rollup/rollup-win32-ia32-msvc@4.40.1": { - "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", + "@rollup/rollup-win32-ia32-msvc@4.44.0": { + "integrity": "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==", "os": ["win32"], "cpu": ["ia32"] }, - "@rollup/rollup-win32-x64-msvc@4.40.1": { - "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", + "@rollup/rollup-win32-x64-msvc@4.44.0": { + "integrity": "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==", "os": ["win32"], "cpu": ["x64"] }, + "@standard-schema/utils@0.3.0": { + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==" + }, "@surma/rollup-plugin-off-main-thread@2.2.3": { "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", "dependencies": [ @@ -2243,62 +2199,65 @@ "string.prototype.matchall" ] }, - "@tailwindcss/node@4.1.5": { - "integrity": "sha512-CBhSWo0vLnWhXIvpD0qsPephiaUYfHUX3U9anwDaHZAeuGpTiB3XmsxPAN6qX7bFhipyGBqOa1QYQVVhkOUGxg==", + "@tailwindcss/node@4.1.10": { + "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", "dependencies": [ + "@ampproject/remapping", "enhanced-resolve", "jiti", "lightningcss", + "magic-string@0.30.17", + "source-map-js", "tailwindcss" ] }, - "@tailwindcss/oxide-android-arm64@4.1.5": { - "integrity": "sha512-LVvM0GirXHED02j7hSECm8l9GGJ1RfgpWCW+DRn5TvSaxVsv28gRtoL4aWKGnXqwvI3zu1GABeDNDVZeDPOQrw==", + "@tailwindcss/oxide-android-arm64@4.1.10": { + "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", "os": ["android"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-darwin-arm64@4.1.5": { - "integrity": "sha512-//TfCA3pNrgnw4rRJOqavW7XUk8gsg9ddi8cwcsWXp99tzdBAZW0WXrD8wDyNbqjW316Pk2hiN/NJx/KWHl8oA==", + "@tailwindcss/oxide-darwin-arm64@4.1.10": { + "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", "os": ["darwin"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-darwin-x64@4.1.5": { - "integrity": "sha512-XQorp3Q6/WzRd9OalgHgaqgEbjP3qjHrlSUb5k1EuS1Z9NE9+BbzSORraO+ecW432cbCN7RVGGL/lSnHxcd+7Q==", + "@tailwindcss/oxide-darwin-x64@4.1.10": { + "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", "os": ["darwin"], "cpu": ["x64"] }, - "@tailwindcss/oxide-freebsd-x64@4.1.5": { - "integrity": "sha512-bPrLWbxo8gAo97ZmrCbOdtlz/Dkuy8NK97aFbVpkJ2nJ2Jo/rsCbu0TlGx8joCuA3q6vMWTSn01JY46iwG+clg==", + "@tailwindcss/oxide-freebsd-x64@4.1.10": { + "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", "os": ["freebsd"], "cpu": ["x64"] }, - "@tailwindcss/oxide-linux-arm-gnueabihf@4.1.5": { - "integrity": "sha512-1gtQJY9JzMAhgAfvd/ZaVOjh/Ju/nCoAsvOVJenWZfs05wb8zq+GOTnZALWGqKIYEtyNpCzvMk+ocGpxwdvaVg==", + "@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10": { + "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", "os": ["linux"], "cpu": ["arm"] }, - "@tailwindcss/oxide-linux-arm64-gnu@4.1.5": { - "integrity": "sha512-dtlaHU2v7MtdxBXoqhxwsWjav7oim7Whc6S9wq/i/uUMTWAzq/gijq1InSgn2yTnh43kR+SFvcSyEF0GCNu1PQ==", + "@tailwindcss/oxide-linux-arm64-gnu@4.1.10": { + "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", "os": ["linux"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-linux-arm64-musl@4.1.5": { - "integrity": "sha512-fg0F6nAeYcJ3CriqDT1iVrqALMwD37+sLzXs8Rjy8Z1ZHshJoYceodfyUwGJEsQoTyWbliFNRs2wMQNXtT7MVA==", + "@tailwindcss/oxide-linux-arm64-musl@4.1.10": { + "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-linux-x64-gnu@4.1.5": { - "integrity": "sha512-SO+F2YEIAHa1AITwc8oPwMOWhgorPzzcbhWEb+4oLi953h45FklDmM8dPSZ7hNHpIk9p/SCZKUYn35t5fjGtHA==", + "@tailwindcss/oxide-linux-x64-gnu@4.1.10": { + "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", "os": ["linux"], "cpu": ["x64"] }, - "@tailwindcss/oxide-linux-x64-musl@4.1.5": { - "integrity": "sha512-6UbBBplywkk/R+PqqioskUeXfKcBht3KU7juTi1UszJLx0KPXUo10v2Ok04iBJIaDPkIFkUOVboXms5Yxvaz+g==", + "@tailwindcss/oxide-linux-x64-musl@4.1.10": { + "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", "os": ["linux"], "cpu": ["x64"] }, - "@tailwindcss/oxide-wasm32-wasi@4.1.5": { - "integrity": "sha512-hwALf2K9FHuiXTPqmo1KeOb83fTRNbe9r/Ixv9ZNQ/R24yw8Ge1HOWDDgTdtzntIaIUJG5dfXCf4g9AD4RiyhQ==", + "@tailwindcss/oxide-wasm32-wasi@4.1.10": { + "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", "dependencies": [ "@emnapi/core", "@emnapi/runtime", @@ -2309,18 +2268,22 @@ ], "cpu": ["wasm32"] }, - "@tailwindcss/oxide-win32-arm64-msvc@4.1.5": { - "integrity": "sha512-oDKncffWzaovJbkuR7/OTNFRJQVdiw/n8HnzaCItrNQUeQgjy7oUiYpsm9HUBgpmvmDpSSbGaCa2Evzvk3eFmA==", + "@tailwindcss/oxide-win32-arm64-msvc@4.1.10": { + "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", "os": ["win32"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-win32-x64-msvc@4.1.5": { - "integrity": "sha512-WiR4dtyrFdbb+ov0LK+7XsFOsG+0xs0PKZKkt41KDn9jYpO7baE3bXiudPVkTqUEwNfiglCygQHl2jklvSBi7Q==", + "@tailwindcss/oxide-win32-x64-msvc@4.1.10": { + "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", "os": ["win32"], "cpu": ["x64"] }, - "@tailwindcss/oxide@4.1.5": { - "integrity": "sha512-1n4br1znquEvyW/QuqMKQZlBen+jxAbvyduU87RS8R3tUSvByAkcaMTkJepNIrTlYhD+U25K4iiCIxE6BGdRYA==", + "@tailwindcss/oxide@4.1.10": { + "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", + "dependencies": [ + "detect-libc", + "tar" + ], "optionalDependencies": [ "@tailwindcss/oxide-android-arm64", "@tailwindcss/oxide-darwin-arm64", @@ -2334,10 +2297,11 @@ "@tailwindcss/oxide-wasm32-wasi", "@tailwindcss/oxide-win32-arm64-msvc", "@tailwindcss/oxide-win32-x64-msvc" - ] + ], + "scripts": true }, - "@tailwindcss/postcss@4.1.5": { - "integrity": "sha512-5lAC2/pzuyfhsFgk6I58HcNy6vPK3dV/PoPxSDuOTVbDvCddYHzHiJZZInGIY0venvzzfrTEUAXJFULAfFmObg==", + "@tailwindcss/postcss@4.1.10": { + "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==", "dependencies": [ "@alloc/quick-lru", "@tailwindcss/node", @@ -2346,31 +2310,20 @@ "tailwindcss" ] }, - "@tanstack/history@1.115.0": { - "integrity": "sha512-K7JJNrRVvyjAVnbXOH2XLRhFXDkeP54Kt2P4FR1Kl2KDGlIbkua5VqZQD2rot3qaDrpufyUa63nuLai1kOLTsQ==" + "@tanstack/history@1.121.21": { + "integrity": "sha512-8BFGA7fpElicM1aEfZRDoEiWgMrNb/fVuJjSKv+nYtbp7jdtqt57fROi/uDGf6PLlgJbMoT3GWxqveZisOUEKA==" }, - "@tanstack/react-router-devtools@1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_solid-js@1.9.7__seroval@1.3.2": { - "integrity": "sha512-5KcUXc3fkiLo/6Y56gOM3JqmYXG1ElIH2iyUWuG5IlcegLrpXhu4OBQ+8Q4+62CD0OKy0ifUDyemrCOAEOfCvw==", + "@tanstack/react-router-devtools@1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-hPOI1FGVWSf9U70eW7NevF/i68Id44KLTM7YjKtDcQi+MWEoxqvXiyXrl/HUAm1IBqLNwO5ktnEdcDuAG/efDg==", "dependencies": [ "@tanstack/react-router", "@tanstack/router-devtools-core", "react", - "react-dom", - "solid-js" - ] - }, - "@tanstack/react-router-devtools@1.120.16_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_solid-js@1.9.7__seroval@1.3.2": { - "integrity": "sha512-DWXmMLknVJJMGP2k5yeUWBDhJOHbV2jVfnZKxtGzA64xXhwDFgU9qpodcmYSq3+kHWsKrd7iX0wc7d27rGwGDA==", - "dependencies": [ - "@tanstack/react-router", - "@tanstack/router-devtools-core", - "react", - "react-dom", - "solid-js" + "react-dom" ] }, - "@tanstack/react-router@1.120.15_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-apzBmXh4pHwqUGU3kD8y2FJMi7rVoUbRxh5oV7v8kEb6Aq5Xpdo+OcpThw8h/M2zv7v4Ef8IoY6WFCKKu3HBjQ==", + "@tanstack/react-router@1.121.27_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-zuLy8IC5fF52fzTTG61nMW2pMoK8LW4kSpeW21deb4gx/kMFKDOaYTe/soT63CO9/x0X6TYcbfjRj67038J0pQ==", "dependencies": [ "@tanstack/history", "@tanstack/react-store", @@ -2391,16 +2344,16 @@ "use-sync-external-store" ] }, - "@tanstack/router-core@1.120.15": { - "integrity": "sha512-soLj+mEuvSxAVFK/3b85IowkkvmSuQL6J0RSIyKJFGFgy0CmUzpcBGEO99+JNWvvvzHgIoY4F4KtLIN+rvFSFA==", + "@tanstack/router-core@1.121.27": { + "integrity": "sha512-6lCQ3p7KhJ8Qy33TPRM6wIkQ1XKaikD5qqx3K2fPr3YtyDNefKQValbSAkb2CBB+hlDodfHNyxemE9alnQr55A==", "dependencies": [ "@tanstack/history", "@tanstack/store", "tiny-invariant" ] }, - "@tanstack/router-devtools-core@1.120.15_@tanstack+router-core@1.120.15_solid-js@1.9.7__seroval@1.3.2_tiny-invariant@1.3.3": { - "integrity": "sha512-AT9obPHKpJqnHMbwshozSy6sApg5LchiAll3blpS3MMDybUCidYHrdhe9MZJLmlC99IQiEGmuZERP3VRcuPNHg==", + "@tanstack/router-devtools-core@1.121.27_@tanstack+router-core@1.121.27_solid-js@1.9.7__seroval@1.3.2_tiny-invariant@1.3.3": { + "integrity": "sha512-taeINd8CSIg+0916myI52HbQxjqfgxqHp68Ha6uxjXAHhHQKg/hBFCWpDs4Dwxi290mhT8j2oeXNyDaGMvVumQ==", "dependencies": [ "@tanstack/router-core", "clsx", @@ -2409,32 +2362,32 @@ "tiny-invariant" ] }, - "@tanstack/router-devtools@1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-u7KbvupWSppoEUYuhCBzmWkd1hcODzHhvGIuWZKoQO9q/qeNY5XptbzGqBSUooXyoF4T/pAdCRILF5zFIqexJw==", + "@tanstack/router-devtools@1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-hQ+8CwMYXCk+FmDPSG5YavWNmY2WuHvEGsbmu1KkwyZ8pwj0RUYCArzGpKx8c0GT7Y29eWmU+U0DNzmEKQILpA==", "dependencies": [ "@tanstack/react-router", - "@tanstack/react-router-devtools@1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_solid-js@1.9.7__seroval@1.3.2", + "@tanstack/react-router-devtools", "clsx", "goober", "react", "react-dom" ] }, - "@tanstack/router-generator@1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-QwZ0rNXxzgOEUDRRAEWVjofKxuxSMIYEdYC3z20k6a7jkLC6pnlCORFx41Vf4xVCO6eElqlrUKXWLTleYSsvQw==", + "@tanstack/router-generator@1.121.27": { + "integrity": "sha512-tIb2w8cno85BPu+7v9IK6eki9LIAWJIEaZJvqOwbdhX+X7LgL8K1xMgIRZfcd4a+7VwJaf66cR/0GzIYlWOggg==", "dependencies": [ - "@tanstack/react-router", + "@tanstack/router-core", + "@tanstack/router-utils", "@tanstack/virtual-file-routes", "prettier", + "recast", + "source-map@0.7.4", "tsx", - "zod@3.25.49" - ], - "optionalPeers": [ - "@tanstack/react-router" + "zod" ] }, - "@tanstack/router-plugin@1.120.15_@tanstack+react-router@1.120.15__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@babel+core@7.27.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.3": { - "integrity": "sha512-ARuuPRKO5HzN3V0LzmkIGm0e447t5VCy2ijbUnzd08KjcJm3lG221ViC2qI+vTom1zp6yeNZHfJW1LBh1yLrTw==", + "@tanstack/router-plugin@1.121.29_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.32": { + "integrity": "sha512-MFVuYQY89Qilu+OIcKpfgOwXFUbCm5eidwYv1V/JG8HuiOIUcC6kcIm9t2OPyCBeroA3ywJSTvoOWMiHe2ybOw==", "dependencies": [ "@babel/core", "@babel/plugin-syntax-jsx", @@ -2447,25 +2400,24 @@ "@tanstack/router-generator", "@tanstack/router-utils", "@tanstack/virtual-file-routes", - "@types/babel__core", - "@types/babel__template", - "@types/babel__traverse", "babel-dead-code-elimination", "chokidar", "unplugin", "vite", - "zod@3.25.49" + "zod" ], "optionalPeers": [ "@tanstack/react-router", "vite" ] }, - "@tanstack/router-utils@1.115.0": { - "integrity": "sha512-Dng4y+uLR9b5zPGg7dHReHOTHQa6x+G6nCoZshsDtWrYsrdCcJEtLyhwZ5wG8OyYS6dVr/Cn+E5Bd2b6BhJ89w==", + "@tanstack/router-utils@1.121.21_@babel+core@7.27.4": { + "integrity": "sha512-u7ubq1xPBtNiU7Fm+EOWlVWdgFLzuKOa1thhqdscVn8R4dNMUd1VoOjZ6AKmLw201VaUhFtlX+u0pjzI6szX7A==", "dependencies": [ + "@babel/core", "@babel/generator", "@babel/parser", + "@babel/preset-typescript", "ansis", "diff" ] @@ -2473,8 +2425,8 @@ "@tanstack/store@0.7.1": { "integrity": "sha512-PjUQKXEXhLYj2X5/6c1Xn/0/qKY0IVFxTJweopRfF26xfjVyb14yALydJrHupDh3/d+1WKmfEgZPBVCmDkzzwg==" }, - "@tanstack/virtual-file-routes@1.115.0": { - "integrity": "sha512-XLUh1Py3AftcERrxkxC5Y5m5mfllRH3YR6YVlyjFgI2Tc2Ssy2NKmQFQIafoxfW459UJ8Dn81nWKETEIJifE4g==" + "@tanstack/virtual-file-routes@1.121.21": { + "integrity": "sha512-3nuYsTyaq6ZN7jRZ9z6Gj3GXZqBOqOT0yzd/WZ33ZFfv4yVNIvsa5Lw+M1j3sgyEAxKMqGu/FaNi7FCjr3yOdw==" }, "@testing-library/dom@10.4.0": { "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", @@ -2501,7 +2453,7 @@ "redent" ] }, - "@testing-library/react@16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@testing-library/react@16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", "dependencies": [ "@babel/runtime", @@ -3900,6 +3852,12 @@ "@babel/types" ] }, + "@types/chai@5.2.2": { + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dependencies": [ + "@types/deep-eql" + ] + }, "@types/chrome@0.0.318": { "integrity": "sha512-rrtyYQ1t+g7EyG0FejE+UXQBjSGUHGh0RIdXwUT/laPo9T724NOIgXA94ns6ewmNauwijYa5ck3+dBxWnHcynQ==", "dependencies": [ @@ -3910,11 +3868,14 @@ "@types/d3-voronoi@1.1.12": { "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==" }, + "@types/deep-eql@4.0.2": { + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==" + }, "@types/estree@0.0.39": { "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" }, - "@types/estree@1.0.7": { - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" + "@types/estree@1.0.8": { + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" }, "@types/filesystem@0.0.36": { "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==", @@ -3951,8 +3912,8 @@ "@types/pbf" ] }, - "@types/node@22.15.3": { - "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "@types/node@22.15.32": { + "integrity": "sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==", "dependencies": [ "undici-types" ] @@ -3960,14 +3921,14 @@ "@types/pbf@3.0.5": { "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" }, - "@types/react-dom@19.1.3_@types+react@19.1.2": { - "integrity": "sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==", + "@types/react-dom@19.1.6_@types+react@19.1.8": { + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", "dependencies": [ "@types/react" ] }, - "@types/react@19.1.2": { - "integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==", + "@types/react@19.1.8": { + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", "dependencies": [ "csstype" ] @@ -4012,28 +3973,30 @@ "maplibre-gl" ] }, - "@vitejs/plugin-react@4.4.1_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@babel+core@7.27.1_@types+node@22.15.3": { - "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", + "@vitejs/plugin-react@4.5.2_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_@types+node@22.15.32": { + "integrity": "sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q==", "dependencies": [ "@babel/core", "@babel/plugin-transform-react-jsx-self", "@babel/plugin-transform-react-jsx-source", + "@rolldown/pluginutils", "@types/babel__core", "react-refresh", "vite" ] }, - "@vitest/expect@3.1.2": { - "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", + "@vitest/expect@3.2.4": { + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dependencies": [ + "@types/chai", "@vitest/spy", "@vitest/utils", "chai", "tinyrainbow" ] }, - "@vitest/mocker@3.1.2_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3": { - "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", + "@vitest/mocker@3.2.4_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32": { + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dependencies": [ "@vitest/spy", "estree-walker@3.0.3", @@ -4044,43 +4007,44 @@ "vite" ] }, - "@vitest/pretty-format@3.1.2": { - "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", + "@vitest/pretty-format@3.2.4": { + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dependencies": [ "tinyrainbow" ] }, - "@vitest/runner@3.1.2": { - "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", + "@vitest/runner@3.2.4": { + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dependencies": [ "@vitest/utils", - "pathe" + "pathe", + "strip-literal" ] }, - "@vitest/snapshot@3.1.2": { - "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", + "@vitest/snapshot@3.2.4": { + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dependencies": [ "@vitest/pretty-format", "magic-string@0.30.17", "pathe" ] }, - "@vitest/spy@3.1.2": { - "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", + "@vitest/spy@3.2.4": { + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dependencies": [ "tinyspy" ] }, - "@vitest/utils@3.1.2": { - "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", + "@vitest/utils@3.2.4": { + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dependencies": [ "@vitest/pretty-format", "loupe", "tinyrainbow" ] }, - "acorn@8.14.1": { - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "acorn@8.15.0": { + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "bin": true }, "ajv@8.17.1": { @@ -4104,8 +4068,8 @@ "ansi-styles@5.2.0": { "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" }, - "ansis@3.17.0": { - "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==" + "ansis@4.1.0": { + "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==" }, "anymatch@3.1.3": { "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", @@ -4114,8 +4078,8 @@ "picomatch@2.3.1" ] }, - "aria-hidden@1.2.4": { - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "aria-hidden@1.2.6": { + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "dependencies": [ "tslib@2.8.1" ] @@ -4157,6 +4121,12 @@ "assign-symbols@1.0.0": { "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" }, + "ast-types@0.16.1": { + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dependencies": [ + "tslib@2.8.1" + ] + }, "async-function@1.0.0": { "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==" }, @@ -4166,7 +4136,7 @@ "at-least-node@1.0.0": { "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" }, - "autoprefixer@10.4.21_postcss@8.5.3": { + "autoprefixer@10.4.21_postcss@8.5.6": { "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "dependencies": [ "browserslist", @@ -4194,7 +4164,7 @@ "@babel/types" ] }, - "babel-plugin-polyfill-corejs2@0.4.13_@babel+core@7.27.1": { + "babel-plugin-polyfill-corejs2@0.4.13_@babel+core@7.27.4": { "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", "dependencies": [ "@babel/compat-data", @@ -4203,7 +4173,7 @@ "semver" ] }, - "babel-plugin-polyfill-corejs3@0.11.1_@babel+core@7.27.1": { + "babel-plugin-polyfill-corejs3@0.11.1_@babel+core@7.27.4": { "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", "dependencies": [ "@babel/core", @@ -4211,7 +4181,7 @@ "core-js-compat" ] }, - "babel-plugin-polyfill-regenerator@0.6.4_@babel+core@7.27.1": { + "babel-plugin-polyfill-regenerator@0.6.4_@babel+core@7.27.4": { "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", "dependencies": [ "@babel/core", @@ -4230,15 +4200,15 @@ "binary-extensions@2.3.0": { "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==" }, - "brace-expansion@1.1.11": { - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "brace-expansion@1.1.12": { + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dependencies": [ "balanced-match", "concat-map" ] }, - "brace-expansion@2.0.1": { - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "brace-expansion@2.0.2": { + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dependencies": [ "balanced-match" ] @@ -4249,8 +4219,8 @@ "fill-range" ] }, - "browserslist@4.24.5": { - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "browserslist@4.25.0": { + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "dependencies": [ "caniuse-lite", "electron-to-chromium", @@ -4301,8 +4271,8 @@ "get-intrinsic" ] }, - "caniuse-lite@1.0.30001716": { - "integrity": "sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw==" + "caniuse-lite@1.0.30001724": { + "integrity": "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==" }, "chai@5.2.0": { "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", @@ -4358,13 +4328,13 @@ "clsx@2.1.1": { "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" }, - "cmdk@1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2": { + "cmdk@1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8": { "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", "dependencies": [ "@radix-ui/react-compose-refs", "@radix-ui/react-dialog", "@radix-ui/react-id", - "@radix-ui/react-primitive@2.1.0_@types+react@19.1.2_@types+react-dom@19.1.3__@types+react@19.1.2_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "@radix-ui/react-primitive", "react", "react-dom" ] @@ -4402,8 +4372,8 @@ "convert-source-map@2.0.0": { "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, - "core-js-compat@3.42.0": { - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "core-js-compat@3.43.0": { + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dependencies": [ "browserslist" ] @@ -4471,8 +4441,8 @@ "is-data-view" ] }, - "debug@4.4.0": { - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "debug@4.4.1": { + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dependencies": [ "ms" ] @@ -4508,8 +4478,8 @@ "detect-node-es@1.1.0": { "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, - "diff@7.0.0": { - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==" + "diff@8.0.2": { + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==" }, "dom-accessibility-api@0.5.16": { "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" @@ -4550,11 +4520,11 @@ ], "bin": true }, - "electron-to-chromium@1.5.149": { - "integrity": "sha512-UyiO82eb9dVOx8YO3ajDf9jz2kKyt98DEITRdeLPstOEuTlLzDA4Gyq5K9he71TQziU5jUVu2OAu5N48HmQiyQ==" + "electron-to-chromium@1.5.171": { + "integrity": "sha512-scWpzXEJEMrGJa4Y6m/tVotb0WuvNmasv3wWVzUAeCgKU0ToFOhUW6Z+xWnRQANMYGxN4ngJXIThgBJOqzVPCQ==" }, - "end-of-stream@1.4.4": { - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "end-of-stream@1.4.5": { + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dependencies": [ "once" ] @@ -4566,8 +4536,8 @@ "tapable" ] }, - "es-abstract@1.23.9": { - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "es-abstract@1.24.0": { + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dependencies": [ "array-buffer-byte-length", "arraybuffer.prototype.slice", @@ -4596,7 +4566,9 @@ "is-array-buffer", "is-callable", "is-data-view", + "is-negative-zero", "is-regex", + "is-set", "is-shared-array-buffer", "is-string", "is-typed-array", @@ -4611,6 +4583,7 @@ "safe-push-apply", "safe-regex-test", "set-proto", + "stop-iteration-iterator", "string.prototype.trim", "string.prototype.trimend", "string.prototype.trimstart", @@ -4654,8 +4627,8 @@ "is-symbol" ] }, - "esbuild@0.25.3": { - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "esbuild@0.25.5": { + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", "optionalDependencies": [ "@esbuild/aix-ppc64", "@esbuild/android-arm", @@ -4689,6 +4662,10 @@ "escalade@3.2.0": { "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, + "esprima@4.0.1": { + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": true + }, "estree-walker@1.0.1": { "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" }, @@ -4698,7 +4675,7 @@ "estree-walker@3.0.3": { "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dependencies": [ - "@types/estree@1.0.7" + "@types/estree@1.0.8" ] }, "esutils@2.0.3": { @@ -4729,8 +4706,8 @@ "fast-uri@3.0.6": { "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==" }, - "fdir@6.4.4_picomatch@4.0.2": { - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "fdir@6.4.6_picomatch@4.0.2": { + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dependencies": [ "picomatch@4.0.2" ], @@ -4927,8 +4904,8 @@ ], "bin": true }, - "happy-dom@17.4.6": { - "integrity": "sha512-OEV1hDe9i2rFr66+WZNiwy1S8rAJy6bRXmXql68YJDjdfHBRbN76om+qVh68vQACf6y5Bcr90e/oK53RQxsDdg==", + "happy-dom@17.6.3": { + "integrity": "sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==", "dependencies": [ "webidl-conversions@7.0.0", "whatwg-mimetype" @@ -4973,8 +4950,8 @@ "void-elements" ] }, - "i18next-browser-languagedetector@8.1.0": { - "integrity": "sha512-mHZxNx1Lq09xt5kCauZ/4bsXOEA2pfpwSoU11/QTJB+pD94iONFwp+ohqi///PwiFvjFOxe1akYCdHyFo1ng5Q==", + "i18next-browser-languagedetector@8.2.0": { + "integrity": "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==", "dependencies": [ "@babel/runtime" ] @@ -4985,8 +4962,8 @@ "cross-fetch" ] }, - "i18next@25.2.0_typescript@5.8.3": { - "integrity": "sha512-ERhJICsxkw1vE7G0lhCUYv4ZxdBEs03qblt1myJs94rYRK9loJF3xDj8mgQz3LmCyp0yYrNjbN/1/GWZTZDGCA==", + "i18next@25.2.1_typescript@5.8.3": { + "integrity": "sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==", "dependencies": [ "@babel/runtime", "typescript" @@ -4995,8 +4972,8 @@ "typescript" ] }, - "idb-keyval@6.2.1": { - "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" + "idb-keyval@6.2.2": { + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==" }, "idb@7.1.1": { "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" @@ -5132,6 +5109,9 @@ "is-module@1.0.0": { "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" }, + "is-negative-zero@2.0.3": { + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" + }, "is-number-object@1.1.1": { "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dependencies": [ @@ -5247,6 +5227,9 @@ "js-tokens@4.0.0": { "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "js-tokens@9.0.1": { + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==" + }, "jsesc@3.0.2": { "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "bin": true @@ -5295,58 +5278,58 @@ "leven@3.1.0": { "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, - "lightningcss-darwin-arm64@1.29.2": { - "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "lightningcss-darwin-arm64@1.30.1": { + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", "os": ["darwin"], "cpu": ["arm64"] }, - "lightningcss-darwin-x64@1.29.2": { - "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "lightningcss-darwin-x64@1.30.1": { + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", "os": ["darwin"], "cpu": ["x64"] }, - "lightningcss-freebsd-x64@1.29.2": { - "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "lightningcss-freebsd-x64@1.30.1": { + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", "os": ["freebsd"], "cpu": ["x64"] }, - "lightningcss-linux-arm-gnueabihf@1.29.2": { - "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "lightningcss-linux-arm-gnueabihf@1.30.1": { + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", "os": ["linux"], "cpu": ["arm"] }, - "lightningcss-linux-arm64-gnu@1.29.2": { - "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "lightningcss-linux-arm64-gnu@1.30.1": { + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", "os": ["linux"], "cpu": ["arm64"] }, - "lightningcss-linux-arm64-musl@1.29.2": { - "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "lightningcss-linux-arm64-musl@1.30.1": { + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", "os": ["linux"], "cpu": ["arm64"] }, - "lightningcss-linux-x64-gnu@1.29.2": { - "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "lightningcss-linux-x64-gnu@1.30.1": { + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", "os": ["linux"], "cpu": ["x64"] }, - "lightningcss-linux-x64-musl@1.29.2": { - "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "lightningcss-linux-x64-musl@1.30.1": { + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", "os": ["linux"], "cpu": ["x64"] }, - "lightningcss-win32-arm64-msvc@1.29.2": { - "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "lightningcss-win32-arm64-msvc@1.30.1": { + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", "os": ["win32"], "cpu": ["arm64"] }, - "lightningcss-win32-x64-msvc@1.29.2": { - "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "lightningcss-win32-x64-msvc@1.30.1": { + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", "os": ["win32"], "cpu": ["x64"] }, - "lightningcss@1.29.2": { - "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "lightningcss@1.30.1": { + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", "dependencies": [ "detect-libc" ], @@ -5376,8 +5359,8 @@ "lodash@4.17.21": { "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "loupe@3.1.3": { - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==" + "loupe@3.1.4": { + "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==" }, "lru-cache@5.1.1": { "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", @@ -5417,7 +5400,7 @@ "@mapbox/unitbezier", "@mapbox/vector-tile", "@mapbox/whoots-js", - "@maplibre/maplibre-gl-style-spec@23.2.2", + "@maplibre/maplibre-gl-style-spec@23.3.0", "@types/geojson", "@types/geojson-vt", "@types/mapbox__point-geometry", @@ -5450,13 +5433,13 @@ "minimatch@3.1.2": { "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": [ - "brace-expansion@1.1.11" + "brace-expansion@1.1.12" ] }, "minimatch@5.1.6": { "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dependencies": [ - "brace-expansion@2.0.1" + "brace-expansion@2.0.2" ] }, "minimist@1.2.8": { @@ -5593,8 +5576,8 @@ "postcss-value-parser@4.2.0": { "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, - "postcss@8.5.3": { - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "postcss@8.5.6": { + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dependencies": [ "nanoid", "picocolors", @@ -5637,8 +5620,8 @@ "punycode@2.3.1": { "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, - "qrcode-generator@1.4.4": { - "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + "qrcode-generator@1.5.0": { + "integrity": "sha512-sqo7otiDq5rA4djRkFI7IjLQqxRrLpIou0d3rqr03JJLUGf5raPh91xCio+lFFbQf0SlcVckStz0EmDEX3EeZA==" }, "quickselect@1.1.1": { "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" @@ -5681,14 +5664,14 @@ "react" ] }, - "react-hook-form@7.56.2_react@19.1.0": { - "integrity": "sha512-vpfuHuQMF/L6GpuQ4c3ZDo+pRYxIi40gQqsCmmfUBwm+oqvBhKhwghCuj2o00YCgSfU6bR9KC/xnQGWm3Gr08A==", + "react-hook-form@7.58.1_react@19.1.0": { + "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==", "dependencies": [ "react" ] }, - "react-i18next@15.5.1_i18next@25.2.0__typescript@5.8.3_react@19.1.0_typescript@5.8.3": { - "integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==", + "react-i18next@15.5.3_i18next@25.2.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3": { + "integrity": "sha512-ypYmOKOnjqPEJZO4m1BI0kS8kWqkBNsKYyhVUfij0gvjy9xJNoG/VcGkxq5dRlVwzmrmY1BQMAmpbbUBLwC4Kw==", "dependencies": [ "@babel/runtime", "html-parse-stringify", @@ -5728,7 +5711,7 @@ "react-refresh@0.17.0": { "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==" }, - "react-remove-scroll-bar@2.3.8_@types+react@19.1.2_react@19.1.0": { + "react-remove-scroll-bar@2.3.8_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", "dependencies": [ "@types/react", @@ -5740,8 +5723,8 @@ "@types/react" ] }, - "react-remove-scroll@2.6.3_@types+react@19.1.2_react@19.1.0": { - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "react-remove-scroll@2.7.1_@types+react@19.1.8_react@19.1.0": { + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", "dependencies": [ "@types/react", "react", @@ -5755,7 +5738,7 @@ "@types/react" ] }, - "react-style-singleton@2.2.3_@types+react@19.1.2_react@19.1.0": { + "react-style-singleton@2.2.3_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", "dependencies": [ "@types/react", @@ -5796,6 +5779,16 @@ "picomatch@2.3.1" ] }, + "recast@0.23.11": { + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dependencies": [ + "ast-types", + "esprima", + "source-map@0.6.1", + "tiny-invariant", + "tslib@2.8.1" + ] + }, "redent@3.0.0": { "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dependencies": [ @@ -5894,10 +5887,10 @@ ], "bin": true }, - "rollup@4.40.1": { - "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", + "rollup@4.44.0": { + "integrity": "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==", "dependencies": [ - "@types/estree@1.0.7" + "@types/estree@1.0.8" ], "optionalDependencies": [ "@rollup/rollup-android-arm-eabi", @@ -6120,6 +6113,9 @@ "source-map@0.6.1": { "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "source-map@0.7.4": { + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + }, "source-map@0.8.0-beta.0": { "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", "dependencies": [ @@ -6154,6 +6150,13 @@ "ste-core" ] }, + "stop-iteration-iterator@1.1.0": { + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dependencies": [ + "es-errors", + "internal-slot" + ] + }, "stream-shift@1.0.3": { "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, @@ -6233,6 +6236,12 @@ "min-indent" ] }, + "strip-literal@3.0.0": { + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dependencies": [ + "js-tokens@9.0.1" + ] + }, "supercluster@8.0.1": { "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", "dependencies": [ @@ -6254,20 +6263,20 @@ "tinyqueue@2.0.3" ] }, - "tailwind-merge@3.2.0": { - "integrity": "sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA==" + "tailwind-merge@3.3.1": { + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==" }, - "tailwindcss-animate@1.0.7_tailwindcss@4.1.5": { + "tailwindcss-animate@1.0.7_tailwindcss@4.1.10": { "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", "dependencies": [ "tailwindcss" ] }, - "tailwindcss@4.1.5": { - "integrity": "sha512-nYtSPfWGDiWgCkwQG/m+aX83XCwf62sBgg3bIlNiiOcggnS1x3uVRDAuyelBFL+vJdOPPCGElxv9DjHJjRHiVA==" + "tailwindcss@4.1.10": { + "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==" }, - "tapable@2.2.1": { - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + "tapable@2.2.2": { + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==" }, "tar@7.4.3": { "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", @@ -6292,8 +6301,8 @@ "unique-string" ] }, - "terser@5.39.0": { - "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "terser@5.43.1": { + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dependencies": [ "@jridgewell/source-map", "acorn", @@ -6335,15 +6344,15 @@ "tinyexec@0.3.2": { "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==" }, - "tinyglobby@0.2.13_picomatch@4.0.2": { - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "tinyglobby@0.2.14_picomatch@4.0.2": { + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dependencies": [ "fdir", "picomatch@4.0.2" ] }, - "tinypool@1.0.2": { - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==" + "tinypool@1.1.1": { + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==" }, "tinyqueue@2.0.3": { "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" @@ -6354,8 +6363,8 @@ "tinyrainbow@2.0.0": { "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==" }, - "tinyspy@3.0.2": { - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==" + "tinyspy@4.0.3": { + "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==" }, "to-regex-range@5.0.1": { "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", @@ -6395,8 +6404,8 @@ "tslog@4.9.3": { "integrity": "sha512-oDWuGVONxhVEBtschLf2cs/Jy8i7h1T+CpdkTNWQgdAF7DhRo2G8vMCgILKe7ojdEkLhICWgI1LYSSKaJsRgcw==" }, - "tsx@4.19.4": { - "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", + "tsx@4.20.3": { + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", "dependencies": [ "esbuild", "get-tsconfig" @@ -6523,7 +6532,7 @@ "upath@1.2.0": { "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, - "update-browserslist-db@1.1.3_browserslist@4.24.5": { + "update-browserslist-db@1.1.3_browserslist@4.25.0": { "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dependencies": [ "browserslist", @@ -6532,7 +6541,7 @@ ], "bin": true }, - "use-callback-ref@1.3.3_@types+react@19.1.2_react@19.1.0": { + "use-callback-ref@1.3.3_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "dependencies": [ "@types/react", @@ -6543,7 +6552,7 @@ "@types/react" ] }, - "use-sidecar@1.1.3_@types+react@19.1.2_react@19.1.0": { + "use-sidecar@1.1.3_@types+react@19.1.8_react@19.1.0": { "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", "dependencies": [ "@types/react", @@ -6564,8 +6573,8 @@ "util-deprecate@1.0.2": { "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "vite-node@3.1.2_@types+node@22.15.3": { - "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", + "vite-node@3.2.4_@types+node@22.15.32": { + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dependencies": [ "cac", "debug", @@ -6575,7 +6584,7 @@ ], "bin": true }, - "vite-plugin-pwa@1.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.1__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.3": { + "vite-plugin-pwa@1.0.0_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.4__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.32": { "integrity": "sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==", "dependencies": [ "debug", @@ -6586,8 +6595,8 @@ "workbox-window" ] }, - "vite-plugin-static-copy@3.0.0_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2_@types+node@22.15.3": { - "integrity": "sha512-Uki9pPUQ4ZnoMEdIFabvoh9h6Bh9Q1m3iF7BrZvoiF30reREpJh2gZb4jOnW1/uYFzyRiLCmFSkM+8hwiq1vWQ==", + "vite-plugin-static-copy@3.0.2_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32": { + "integrity": "sha512-/seLvhUg44s1oU9RhjTZZy/0NPbfNctozdysKcvPovxxXZdI5l19mGq6Ri3IaTf1Dy/qChS4BSR7ayxeu8o9aQ==", "dependencies": [ "chokidar", "fs-extra@11.3.0", @@ -6597,15 +6606,15 @@ "vite" ] }, - "vite@6.3.4_@types+node@22.15.3_picomatch@4.0.2": { - "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==", + "vite@6.3.5_@types+node@22.15.32_picomatch@4.0.2": { + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dependencies": [ "@types/node", "esbuild", "fdir", "picomatch@4.0.2", "postcss", - "rollup@4.40.1", + "rollup@4.44.0", "tinyglobby" ], "optionalDependencies": [ @@ -6616,9 +6625,10 @@ ], "bin": true }, - "vitest@3.1.2_@types+node@22.15.3_happy-dom@17.4.6_vite@6.3.4__@types+node@22.15.3__picomatch@4.0.2": { - "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", + "vitest@3.2.4_@types+node@22.15.32_happy-dom@17.6.3_vite@6.3.5__@types+node@22.15.32__picomatch@4.0.2": { + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dependencies": [ + "@types/chai", "@types/node", "@vitest/expect", "@vitest/mocker", @@ -6633,6 +6643,7 @@ "happy-dom", "magic-string@0.30.17", "pathe", + "picomatch@4.0.2", "std-env", "tinybench", "tinyexec", @@ -6767,7 +6778,7 @@ "workbox-core" ] }, - "workbox-build@7.3.0_ajv@8.17.1_@babel+core@7.27.1_rollup@2.79.2": { + "workbox-build@7.3.0_ajv@8.17.1_@babel+core@7.27.4_rollup@2.79.2": { "integrity": "sha512-JGL6vZTPlxnlqZRhR/K/msqg3wKP+m0wfEUVosK7gsYzSgeIxvZLi1ViJJzVL7CEeI8r7rGFV973RiEqkP3lWQ==", "dependencies": [ "@apideck/better-ajv-errors", @@ -6906,16 +6917,13 @@ "yallist@5.0.0": { "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" }, - "zod@3.25.49": { - "integrity": "sha512-JMMPMy9ZBk3XFEdbM3iL1brx4NUSejd6xr3ELrrGEfGb355gjhiAWtG3K5o+AViV/3ZfkIrCzXsZn6SbLwTR8Q==" - }, - "zod@3.25.62": { - "integrity": "sha512-YCxsr4DmhPcrKPC9R1oBHQNlQzlJEyPAId//qTau/vBee9uO8K6prmRq4eMkOyxvBfH4wDPIPdLx9HVMWIY3xA==" + "zod@3.25.67": { + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==" }, "zone.js@0.8.29": { "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" }, - "zustand@5.0.5_@types+react@19.1.2_immer@10.1.1_react@19.1.0": { + "zustand@5.0.5_@types+react@19.1.8_immer@10.1.1_react@19.1.0": { "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==", "dependencies": [ "@types/react", @@ -6938,6 +6946,7 @@ "packageJson": { "dependencies": [ "npm:@bufbuild/protobuf@^2.2.5", + "npm:@hookform/resolvers@^5.1.1", "npm:@jsr/meshtastic__core@2.6.4", "npm:@jsr/meshtastic__js@2.6.0-0", "npm:@jsr/meshtastic__transport-http@*", @@ -7014,7 +7023,7 @@ "npm:vite-plugin-static-copy@3", "npm:vite@^6.3.4", "npm:vitest@^3.1.2", - "npm:zod@^3.25.62", + "npm:zod@^3.25.67", "npm:zustand@5.0.5" ] } diff --git a/package.json b/package.json index f3577bc3..6235e641 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "homepage": "https://meshtastic.org", "dependencies": { "@bufbuild/protobuf": "^2.2.5", + "@hookform/resolvers": "^5.1.1", "@meshtastic/core": "npm:@jsr/meshtastic__core@2.6.4", "@meshtastic/js": "npm:@jsr/meshtastic__js@2.6.0-0", "@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http", @@ -84,7 +85,7 @@ "react-map-gl": "8.0.4", "react-qrcode-logo": "^3.0.0", "rfc4648": "^1.5.4", - "zod": "^3.25.62", + "zod": "^3.25.67", "zustand": "5.0.5" }, "devDependencies": { diff --git a/public/site.webmanifest b/public/site.webmanifest index 6135ea5c..a5f2d0ca 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1,11 +1,11 @@ { "name": "Meshtastic", - "short_name": "Meshtastic", + "short_name": "Web Client", "start_url": ".", - "description": "Meshtastic web app", + "description": "Meshtastic Web App", "icons": [ { - "src": "/icon.svg", + "src": "/Logo.svg", "sizes": "any", "type": "image/svg+xml" } diff --git a/src/components/Dialog/DeviceNameDialog.tsx b/src/components/Dialog/DeviceNameDialog.tsx index b3dd94aa..9944a2b3 100644 --- a/src/components/Dialog/DeviceNameDialog.tsx +++ b/src/components/Dialog/DeviceNameDialog.tsx @@ -14,8 +14,9 @@ import { Protobuf } from "@meshtastic/core"; import { useForm } from "react-hook-form"; import { GenericInput } from "@components/Form/FormInput.tsx"; import { useTranslation } from "react-i18next"; -import { validateMaxByteLength } from "@core/utils/string.ts"; import { Label } from "../UI/Label.tsx"; +import z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; export interface User { longName: string; @@ -26,8 +27,6 @@ export interface DeviceNameDialogProps { open: boolean; onOpenChange: (open: boolean) => void; } -const MAX_LONG_NAME_BYTE_LENGTH = 40; -const MAX_SHORT_NAME_BYTE_LENGTH = 4; export const DeviceNameDialog = ({ open, @@ -38,27 +37,25 @@ export const DeviceNameDialog = ({ const myNode = getNode(hardware.myNodeNum); const defaultValues = { - longName: myNode?.user?.longName ?? t("unknown.longName"), - shortName: myNode?.user?.shortName ?? t("unknown.shortName"), + shortName: myNode?.user?.shortName ?? "", + longName: myNode?.user?.longName ?? "", }; - const { getValues, setValue, reset, control, handleSubmit } = useForm({ - values: defaultValues, + const deviceNameSchema = z.object({ + longName: z + .string() + .min(1, t("deviceName.validation.longNameMin")) + .max(40, t("deviceName.validation.longNameMax")), + shortName: z + .string() + .min(2, t("deviceName.validation.shortNameMin")) + .max(4, t("deviceName.validation.shortNameMax")), }); - const { currentLength: currentLongNameLength } = validateMaxByteLength( - getValues("longName"), - MAX_LONG_NAME_BYTE_LENGTH, - ); - const { currentLength: currentShortNameLength } = validateMaxByteLength( - getValues("shortName"), - MAX_SHORT_NAME_BYTE_LENGTH, - ); - - if (!myNode?.user) { - console.warn("DeviceNameDialog: No user data available"); - return null; - } + const { getValues, reset, control, handleSubmit } = useForm({ + values: defaultValues, + resolver: zodResolver(deviceNameSchema), + }); const onSubmit = handleSubmit((data) => { connection?.setOwner( @@ -70,9 +67,7 @@ export const DeviceNameDialog = ({ }); const handleReset = () => { - reset({ longName: "", shortName: "" }); - setValue("longName", ""); - setValue("shortName", ""); + reset(defaultValues); }; return ( @@ -99,8 +94,9 @@ export const DeviceNameDialog = ({ properties: { className: "text-slate-900 dark:text-slate-200", fieldLength: { - currentValueLength: currentLongNameLength ?? 0, - max: MAX_LONG_NAME_BYTE_LENGTH, + currentValueLength: getValues("longName").length, + max: 40, + min: 1, showCharacterCount: true, }, }, @@ -119,8 +115,9 @@ export const DeviceNameDialog = ({ type: "text", properties: { fieldLength: { - currentValueLength: currentShortNameLength ?? 0, - max: MAX_SHORT_NAME_BYTE_LENGTH, + currentValueLength: getValues("shortName").length, + max: 4, + min: 1, showCharacterCount: true, }, }, @@ -137,7 +134,12 @@ export const DeviceNameDialog = ({ > {t("button.reset")} - + diff --git a/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx b/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx index 5ce685a1..73a41e07 100644 --- a/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx +++ b/src/components/Dialog/UnsafeRolesDialog/UnsafeRolesDialog.tsx @@ -63,7 +63,9 @@ export const UnsafeRolesDialog = ( onChange={() => setConfirmState(!confirmState)} name="confirmUnderstanding" > - {t("unsafeRoles.confirmUnderstanding")} + + {t("unsafeRoles.confirmUnderstanding")} +
diff --git a/src/components/Form/FormInput.tsx b/src/components/Form/FormInput.tsx index cd7ffea0..9a7d605d 100644 --- a/src/components/Form/FormInput.tsx +++ b/src/components/Form/FormInput.tsx @@ -4,15 +4,14 @@ import type { } from "@components/Form/DynamicForm.tsx"; import { Input } from "@components/UI/Input.tsx"; import type { ChangeEventHandler } from "react"; -import { useState } from "react"; import { type FieldValues, useController } from "react-hook-form"; export interface InputFieldProps extends BaseFormBuilderProps { type: "text" | "number" | "password"; inputChange?: ChangeEventHandler; + prefix?: string; properties?: { - value?: string; - prefix?: string; + id?: string; suffix?: string; step?: number; className?: string; @@ -31,29 +30,33 @@ export function GenericInput({ control, disabled, field, - isDirty, invalid, }: GenericFormElementProps>) { const { fieldLength, ...restProperties } = field.properties || {}; - const [currentLength, setCurrentLength] = useState( - fieldLength?.currentValueLength || 0, - ); - const { field: controllerField } = useController({ + const { + field: controllerField, + fieldState: { error, isDirty }, + } = useController({ name: field.name, control, + rules: { + minLength: field.properties?.fieldLength?.min, + maxLength: field.properties?.fieldLength?.max, + }, }); + const isInvalid = invalid || Boolean(error?.message); + const handleInputChange = (e: React.ChangeEvent) => { const newValue = e.target.value; if ( field.properties?.fieldLength?.max && - newValue.length > field.properties?.fieldLength?.max + newValue.length > field.properties.fieldLength.max ) { return; } - setCurrentLength(newValue.length); if (field.inputChange) field.inputChange(e); @@ -64,6 +67,10 @@ export function GenericInput({ ); }; + const currentLength = controllerField.value + ? String(controllerField.value).length + : 0; + return (
({ className={field.properties?.className} {...restProperties} disabled={disabled} - variant={invalid ? "invalid" : isDirty ? "dirty" : "default"} + variant={error ? "invalid" : isDirty ? "dirty" : "default"} /> - {fieldLength?.showCharacterCount && fieldLength?.max && ( + {fieldLength?.showCharacterCount && fieldLength.max && (
- {currentLength ?? fieldLength?.currentValueLength}/{fieldLength?.max} + {currentLength}/{fieldLength.max} +
+ )} + + {isInvalid && ( +
+

{error?.message ?? ""}

)}
diff --git a/src/components/PageComponents/Connect/BLE.tsx b/src/components/PageComponents/Connect/BLE.tsx index 28aec612..ca1dd326 100644 --- a/src/components/PageComponents/Connect/BLE.tsx +++ b/src/components/PageComponents/Connect/BLE.tsx @@ -7,7 +7,6 @@ import { subscribeAll } from "@core/subscriptions.ts"; import { randId } from "@core/utils/randId.ts"; import { TransportWebBluetooth } from "@meshtastic/transport-web-bluetooth"; import { MeshDevice } from "@meshtastic/core"; -import type { BluetoothDevice } from "web-bluetooth"; import { useCallback, useEffect, useState } from "react"; import { useMessageStore } from "@core/stores/messageStore/index.ts"; import { useTranslation } from "react-i18next"; diff --git a/src/i18n/locales/en/dialog.json b/src/i18n/locales/en/dialog.json index a6cc54af..9b06b33a 100644 --- a/src/i18n/locales/en/dialog.json +++ b/src/i18n/locales/en/dialog.json @@ -7,7 +7,13 @@ "description": "The Device will restart once the config is saved.", "longName": "Long Name", "shortName": "Short Name", - "title": "Change Device Name" + "title": "Change Device Name", + "validation": { + "longNameMax": "Long name must not be more than 40 characters", + "shortNameMax": "Short name must not be more than 4 characters", + "longNameMin": "Long name must have at least 1 character", + "shortNameMin": "Short name must have at least 1 character" + } }, "import": { "description": "The current LoRa configuration will be overridden.", @@ -21,9 +27,10 @@ "title": "Import Channel Set" }, "locationResponse": { + "title": "Location: {{identifier}}", "altitude": "Altitude: ", "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" + "noCoordinates": "No Coordinates" }, "pkiRegenerateDialog": { "title": "Regenerate Pre-Shared Key?", @@ -61,11 +68,15 @@ }, "bluetoothConnection": { "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" + "newDeviceButton": "New device", + "connectionFailed": "Connection failed", + "deviceDisconnected": "Device disconnected", + "unknownDevice": "Unknown Device", + "errorLoadingDevices": "Error loading devices", + "unknownErrorLoadingDevices": "Unknown error loading devices" }, "validation": { - "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", - "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", + "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } From 183b3ae8cc5668db67f87fd6f604b9d3a0c3b18a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 22 Jun 2025 13:57:29 -0400 Subject: [PATCH 24/37] chore(i18n): New Crowdin Translations by GitHub Action (#677) Co-authored-by: Crowdin Bot --- src/i18n/locales/bg-BG/channels.json | 10 +- src/i18n/locales/bg-BG/commandPalette.json | 30 +- src/i18n/locales/bg-BG/common.json | 86 ++-- src/i18n/locales/bg-BG/dashboard.json | 12 +- src/i18n/locales/bg-BG/deviceConfig.json | 118 +++--- src/i18n/locales/bg-BG/dialog.json | 134 +++--- src/i18n/locales/bg-BG/messages.json | 47 ++- src/i18n/locales/bg-BG/moduleConfig.json | 90 ++--- src/i18n/locales/bg-BG/nodes.json | 36 +- src/i18n/locales/bg-BG/ui.json | 133 +++--- src/i18n/locales/cs-CZ/common.json | 24 +- src/i18n/locales/cs-CZ/dialog.json | 16 +- src/i18n/locales/cs-CZ/messages.json | 39 +- src/i18n/locales/cs-CZ/nodes.json | 14 +- src/i18n/locales/cs-CZ/ui.json | 27 ++ src/i18n/locales/de-DE/common.json | 24 +- src/i18n/locales/de-DE/dialog.json | 16 +- src/i18n/locales/de-DE/messages.json | 39 +- src/i18n/locales/de-DE/nodes.json | 14 +- src/i18n/locales/de-DE/ui.json | 27 ++ src/i18n/locales/es-ES/common.json | 24 +- src/i18n/locales/es-ES/dialog.json | 16 +- src/i18n/locales/es-ES/messages.json | 39 +- src/i18n/locales/es-ES/nodes.json | 14 +- src/i18n/locales/es-ES/ui.json | 27 ++ src/i18n/locales/fi-FI/common.json | 24 +- src/i18n/locales/fi-FI/dialog.json | 16 +- src/i18n/locales/fi-FI/messages.json | 37 +- src/i18n/locales/fi-FI/nodes.json | 14 +- src/i18n/locales/fi-FI/ui.json | 33 +- src/i18n/locales/fr-FR/common.json | 24 +- src/i18n/locales/fr-FR/dialog.json | 16 +- src/i18n/locales/fr-FR/messages.json | 39 +- src/i18n/locales/fr-FR/nodes.json | 14 +- src/i18n/locales/fr-FR/ui.json | 27 ++ src/i18n/locales/it-IT/channels.json | 78 ++-- src/i18n/locales/it-IT/commandPalette.json | 40 +- src/i18n/locales/it-IT/common.json | 120 +++--- src/i18n/locales/it-IT/dashboard.json | 10 +- src/i18n/locales/it-IT/deviceConfig.json | 372 ++++++++--------- src/i18n/locales/it-IT/dialog.json | 194 ++++----- src/i18n/locales/it-IT/messages.json | 47 ++- src/i18n/locales/it-IT/moduleConfig.json | 402 +++++++++--------- src/i18n/locales/it-IT/nodes.json | 48 ++- src/i18n/locales/it-IT/ui.json | 171 ++++---- src/i18n/locales/ja-JP/common.json | 24 +- src/i18n/locales/ja-JP/dialog.json | 16 +- src/i18n/locales/ja-JP/messages.json | 39 +- src/i18n/locales/ja-JP/nodes.json | 14 +- src/i18n/locales/ja-JP/ui.json | 27 ++ src/i18n/locales/ko-KR/channels.json | 69 ++++ src/i18n/locales/ko-KR/commandPalette.json | 50 +++ src/i18n/locales/ko-KR/common.json | 141 +++++++ src/i18n/locales/ko-KR/dashboard.json | 12 + src/i18n/locales/ko-KR/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/ko-KR/dialog.json | 171 ++++++++ src/i18n/locales/ko-KR/messages.json | 39 ++ src/i18n/locales/ko-KR/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/ko-KR/nodes.json | 63 +++ src/i18n/locales/ko-KR/ui.json | 228 +++++++++++ src/i18n/locales/nl-NL/common.json | 24 +- src/i18n/locales/nl-NL/dialog.json | 16 +- src/i18n/locales/nl-NL/messages.json | 39 +- src/i18n/locales/nl-NL/nodes.json | 14 +- src/i18n/locales/nl-NL/ui.json | 27 ++ src/i18n/locales/pl-PL/channels.json | 69 ++++ src/i18n/locales/pl-PL/commandPalette.json | 50 +++ src/i18n/locales/pl-PL/common.json | 141 +++++++ src/i18n/locales/pl-PL/dashboard.json | 12 + src/i18n/locales/pl-PL/deviceConfig.json | 428 ++++++++++++++++++++ src/i18n/locales/pl-PL/dialog.json | 171 ++++++++ src/i18n/locales/pl-PL/messages.json | 39 ++ src/i18n/locales/pl-PL/moduleConfig.json | 448 +++++++++++++++++++++ src/i18n/locales/pl-PL/nodes.json | 63 +++ src/i18n/locales/pl-PL/ui.json | 228 +++++++++++ src/i18n/locales/pt-PT/common.json | 24 +- src/i18n/locales/pt-PT/dialog.json | 16 +- src/i18n/locales/pt-PT/messages.json | 39 +- src/i18n/locales/pt-PT/nodes.json | 14 +- src/i18n/locales/pt-PT/ui.json | 27 ++ src/i18n/locales/sv-SE/common.json | 24 +- src/i18n/locales/sv-SE/dashboard.json | 2 +- src/i18n/locales/sv-SE/dialog.json | 16 +- src/i18n/locales/sv-SE/messages.json | 39 +- src/i18n/locales/sv-SE/nodes.json | 14 +- src/i18n/locales/sv-SE/ui.json | 29 +- src/i18n/locales/tr-TR/common.json | 24 +- src/i18n/locales/tr-TR/dialog.json | 16 +- src/i18n/locales/tr-TR/messages.json | 39 +- src/i18n/locales/tr-TR/nodes.json | 14 +- src/i18n/locales/tr-TR/ui.json | 27 ++ src/i18n/locales/uk-UA/channels.json | 58 +-- src/i18n/locales/uk-UA/commandPalette.json | 12 +- src/i18n/locales/uk-UA/common.json | 56 ++- src/i18n/locales/uk-UA/dashboard.json | 4 +- src/i18n/locales/uk-UA/deviceConfig.json | 54 +-- src/i18n/locales/uk-UA/dialog.json | 52 ++- src/i18n/locales/uk-UA/messages.json | 49 ++- src/i18n/locales/uk-UA/moduleConfig.json | 18 +- src/i18n/locales/uk-UA/nodes.json | 24 +- src/i18n/locales/uk-UA/ui.json | 71 +++- src/i18n/locales/zh-CN/common.json | 24 +- src/i18n/locales/zh-CN/dialog.json | 16 +- src/i18n/locales/zh-CN/messages.json | 39 +- src/i18n/locales/zh-CN/nodes.json | 14 +- src/i18n/locales/zh-CN/ui.json | 27 ++ 106 files changed, 5754 insertions(+), 1448 deletions(-) create mode 100644 src/i18n/locales/ko-KR/channels.json create mode 100644 src/i18n/locales/ko-KR/commandPalette.json create mode 100644 src/i18n/locales/ko-KR/common.json create mode 100644 src/i18n/locales/ko-KR/dashboard.json create mode 100644 src/i18n/locales/ko-KR/deviceConfig.json create mode 100644 src/i18n/locales/ko-KR/dialog.json create mode 100644 src/i18n/locales/ko-KR/messages.json create mode 100644 src/i18n/locales/ko-KR/moduleConfig.json create mode 100644 src/i18n/locales/ko-KR/nodes.json create mode 100644 src/i18n/locales/ko-KR/ui.json create mode 100644 src/i18n/locales/pl-PL/channels.json create mode 100644 src/i18n/locales/pl-PL/commandPalette.json create mode 100644 src/i18n/locales/pl-PL/common.json create mode 100644 src/i18n/locales/pl-PL/dashboard.json create mode 100644 src/i18n/locales/pl-PL/deviceConfig.json create mode 100644 src/i18n/locales/pl-PL/dialog.json create mode 100644 src/i18n/locales/pl-PL/messages.json create mode 100644 src/i18n/locales/pl-PL/moduleConfig.json create mode 100644 src/i18n/locales/pl-PL/nodes.json create mode 100644 src/i18n/locales/pl-PL/ui.json diff --git a/src/i18n/locales/bg-BG/channels.json b/src/i18n/locales/bg-BG/channels.json index 10379e7b..55eb07d9 100644 --- a/src/i18n/locales/bg-BG/channels.json +++ b/src/i18n/locales/bg-BG/channels.json @@ -1,7 +1,7 @@ { "page": { "sectionLabel": "Канали", - "channelName": "Channel: {{channelName}}", + "channelName": "Канал: {{channelName}}", "broadcastLabel": "Primary", "channelIndex": "Ch {{index}}" }, @@ -24,7 +24,7 @@ "psk": { "label": "Pre-Shared Key", "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" + "generate": "Генериране" }, "name": { "label": "Име", @@ -39,11 +39,11 @@ "description": "Send messages from MQTT to the local mesh" }, "positionPrecision": { - "label": "Location", + "label": "Местоположение", "description": "The precision of the location to share with the channel. Can be disabled.", "options": { - "none": "Do not share location", - "precise": "Precise Location", + "none": "Да не се споделя местоположението", + "precise": "Точно местоположение", "metric_km23": "Within 23 kilometers", "metric_km12": "Within 12 kilometers", "metric_km5_8": "Within 5.8 kilometers", diff --git a/src/i18n/locales/bg-BG/commandPalette.json b/src/i18n/locales/bg-BG/commandPalette.json index 83140af2..a37dbd60 100644 --- a/src/i18n/locales/bg-BG/commandPalette.json +++ b/src/i18n/locales/bg-BG/commandPalette.json @@ -1,5 +1,5 @@ { - "emptyState": "No results found.", + "emptyState": "Няма намерени резултати.", "page": { "title": "Command Menu" }, @@ -14,37 +14,37 @@ "command": { "messages": "Съобщения", "map": "Карта", - "config": "Config", + "config": "Конфигурация", "channels": "Канали", "nodes": "Възли" } }, "manage": { - "label": "Manage", + "label": "Управление", "command": { "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" + "connectNewNode": "Свързване на нов възел" } }, "contextual": { "label": "Contextual", "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", + "qrCode": "QR код", + "qrGenerator": "Генератор", "qrImport": "Импортиране", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" + "scheduleShutdown": "Планирано изключване", + "scheduleReboot": "Планирано рестартиране", + "rebootToOtaMode": "Рестартиране в режим OTA", + "resetNodeDb": "Нулиране на базата данни с възли", + "factoryResetDevice": "Фабрично нулиране на устройството", + "factoryResetConfig": "Фабрично нулиране на конфигурацията" } }, "debug": { - "label": "Debug", + "label": "Отстраняване на грешки", "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" + "reconfigure": "Преконфигуриране", + "clearAllStoredMessages": "Изчистване на всички съхранени съобщения" } } } diff --git a/src/i18n/locales/bg-BG/common.json b/src/i18n/locales/bg-BG/common.json index 3f874ddb..da05c539 100644 --- a/src/i18n/locales/bg-BG/common.json +++ b/src/i18n/locales/bg-BG/common.json @@ -3,20 +3,20 @@ "apply": "Приложи", "backupKey": "Backup Key", "cancel": "Отказ", - "clearMessages": "Clear Messages", + "clearMessages": "Изчистване на съобщенията", "close": "Затвори", - "confirm": "Confirm", + "confirm": "Потвърждаване", "delete": "Изтриване", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", + "dismiss": "Отхвърляне", + "download": "Изтегляне", + "export": "Експортиране", + "generate": "Генериране", + "regenerate": "Регенериране", "import": "Импортиране", "message": "Съобщение", - "now": "Now", + "now": "Сега", "ok": "Добре", - "print": "Print", + "print": "Отпечатване", "rebootOtaNow": "Reboot to OTA Mode Now", "remove": "Изтрий", "requestNewKeys": "Request New Keys", @@ -24,13 +24,14 @@ "reset": "Нулиране", "save": "Запис", "scanQr": "Сканиране на QR кода", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", - "fullTitle": "Meshtastic Web Client" + "fullTitle": "Meshtastic Web клиент" }, - "loading": "Loading...", + "loading": "Зареждане...", "unit": { "cps": "CPS", "dbm": "dBm", @@ -47,47 +48,68 @@ "megahertz": "MHz", "raw": "raw", "meter": { - "one": "Meter", - "plural": "Meters", + "one": "Метър", + "plural": "Метри", "suffix": "m" }, "minute": { - "one": "Minute", - "plural": "Minutes" + "one": "Минута", + "plural": "Минути" + }, + "hour": { + "one": "Час", + "plural": "Часа" }, "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", + "one": "Милисекунда", + "plural": "Милисекунди", "suffix": "ms" }, "second": { - "one": "Second", - "plural": "Seconds" + "one": "Секунда", + "plural": "Секунди" + }, + "day": { + "one": "Ден", + "plural": "Дни" + }, + "month": { + "one": "Месец", + "plural": "Месеца" + }, + "year": { + "one": "Година", + "plural": "Години" }, "snr": "SNR", "volt": { - "one": "Volt", - "plural": "Volts", + "one": "Волт", + "plural": "Волта", "suffix": "V" }, "record": { - "one": "Records", - "plural": "Records" + "one": "Записи", + "plural": "Записи" } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { - "longName": "Unknown", - "shortName": "UNK", + "longName": "Неизвестно", + "shortName": "НЕИЗВ.", "notAvailable": "N/A", "num": "??" }, "nodeUnknownPrefix": "!", - "unset": "UNSET", + "unset": "НЕЗАДАДЕН", "fallbackName": "Meshtastic {{last4}}", + "node": "Възел", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", @@ -98,22 +120,22 @@ "number": "Too small, expected a number larger than or equal to {{minimum}}." }, "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", + "ipv4": "Невалиден формат, очаква се IPv4 адрес.", "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." }, "invalidType": { - "number": "Invalid type, expected a number." + "number": "Невалиден тип, очаква се число." }, "pskLength": { - "0bit": "Key is required to be empty.", + "0bit": "Ключът трябва да е празен.", "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." }, "required": { - "generic": "This field is required.", + "generic": "Това поле е задължително.", "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." + "key": "Ключът е задължителен." } } } diff --git a/src/i18n/locales/bg-BG/dashboard.json b/src/i18n/locales/bg-BG/dashboard.json index e2b64fed..4f1c9d39 100644 --- a/src/i18n/locales/bg-BG/dashboard.json +++ b/src/i18n/locales/bg-BG/dashboard.json @@ -1,12 +1,12 @@ { "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", + "title": "Свързани устройства", + "description": "Управлявайте свързаните си устройства Meshtastic.", "connectionType_ble": "BLE", - "connectionType_serial": "Serial", + "connectionType_serial": "Серийна", "connectionType_network": "Мрежа", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" + "noDevicesTitle": "Няма свързани устройства", + "noDevicesDescription": "Свържете ново устройство, за да започнете.", + "button_newConnection": "Нова връзка" } } diff --git a/src/i18n/locales/bg-BG/deviceConfig.json b/src/i18n/locales/bg-BG/deviceConfig.json index b44b77ee..f7e707a7 100644 --- a/src/i18n/locales/bg-BG/deviceConfig.json +++ b/src/i18n/locales/bg-BG/deviceConfig.json @@ -1,6 +1,6 @@ { "page": { - "title": "Configuration", + "title": "Конфигурация", "tabBluetooth": "Bluetooth", "tabDevice": "Устройство", "tabDisplay": "Дисплей", @@ -11,11 +11,11 @@ "tabSecurity": "Сигурност" }, "sidebar": { - "label": "Modules" + "label": "Модули" }, "device": { - "title": "Device Settings", - "description": "Settings for the device", + "title": "Настройки на устройството", + "description": "Настройки за устройството", "buttonPin": { "description": "Button pin override", "label": "Button Pin" @@ -54,31 +54,31 @@ } }, "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "title": "Настройки за Bluetooth", + "description": "Настройки за Bluetooth модула", + "note": "Забележка: Някои устройства (ESP32) не могат да използват едновременно Bluetooth и WiFi.", "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" + "description": "Активиране или дезактивиране на Bluetooth", + "label": "Активиран" }, "pairingMode": { - "description": "Pin selection behaviour.", + "description": "Поведение при избор на ПИН.", "label": "Режим на сдвояване" }, "pin": { "description": "Pin to use when pairing", - "label": "Pin" + "label": "ПИН" } }, "display": { - "description": "Settings for the device display", - "title": "Display Settings", + "description": "Настройки за дисплея на устройството", + "title": "Настройки на дисплея", "headingBold": { "description": "Bolden the heading text", "label": "Bold Heading" }, "carouselDelay": { - "description": "How fast to cycle through windows", + "description": "Колко бързо да се превключва между прозорците", "label": "Carousel Delay" }, "compassNorthTop": { @@ -90,7 +90,7 @@ "label": "Display Mode" }, "displayUnits": { - "description": "Display metric or imperial units", + "description": "Показване на метрични или имперски мерни единици", "label": "Display Units" }, "flipScreen": { @@ -110,8 +110,8 @@ "label": "Screen Timeout" }, "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" + "description": "Използване на 12-часов формат на часовника", + "label": "12-часов часовник" }, "wakeOnTapOrMotion": { "description": "Wake the device on tap or motion", @@ -119,10 +119,10 @@ } }, "lora": { - "title": "Mesh Settings", + "title": "Настройки на Mesh", "description": "Settings for the LoRa mesh", "bandwidth": { - "description": "Channel bandwidth in MHz", + "description": "Широчина на канала в MHz", "label": "Широчина на честотната лента" }, "boostedRxGain": { @@ -135,11 +135,11 @@ }, "frequencyOffset": { "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" + "label": "Отместване на честотата" }, "frequencySlot": { "description": "LoRa frequency channel number", - "label": "Frequency Slot" + "label": "Честотен слот" }, "hopLimit": { "description": "Maximum number of hops", @@ -150,8 +150,8 @@ "label": "Ignore MQTT" }, "modemPreset": { - "description": "Modem preset to use", - "label": "Modem Preset" + "description": "Използване на предварително настроен модем", + "label": "Предварително настроен модем" }, "okToMqtt": { "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", @@ -174,60 +174,60 @@ "label": "Spreading Factor" }, "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" + "description": "Активиране/дезактивиране на предаването (TX) от LoRa радиото", + "label": "Предаването е активирано" }, "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" + "description": "Максимална мощност на предаване", + "label": "Мощност на предаване" }, "usePreset": { "description": "Use one of the predefined modem presets", - "label": "Use Preset" + "label": "Използване на предварително зададени настройки" }, "meshSettings": { "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" + "label": "Настройки на Mesh" }, "waveformSettings": { "description": "Settings for the LoRa waveform", "label": "Waveform Settings" }, "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" + "label": "Настройки на радиото", + "description": "Настройки за LoRa радиото" } }, "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "title": "Конфигурация на WiFi", + "description": "Конфигурация на WiFi радиото", + "note": "Забележка: Някои устройства (ESP32) не могат да използват едновременно Bluetooth и WiFi.", "addressMode": { "description": "Address assignment selection", "label": "Address Mode" }, "dns": { - "description": "DNS Server", + "description": "DNS сървър", "label": "DNS" }, "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" + "description": "Активиране или дезактивиране на Ethernet порта", + "label": "Активиран" }, "gateway": { - "description": "Default Gateway", + "description": "Шлюз по подразбиране", "label": "Шлюз" }, "ip": { - "description": "IP Address", + "description": "IP адрес", "label": "IP" }, "psk": { - "description": "Network password", + "description": "Парола за мрежата", "label": "PSK" }, "ssid": { - "description": "Network name", + "description": "Име на мрежата", "label": "SSID" }, "subnet": { @@ -235,29 +235,29 @@ "label": "Subnet" }, "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" + "description": "Активиране или дезактивиране на WiFi радиото", + "label": "Активиран" }, "meshViaUdp": { "label": "Mesh via UDP" }, "ntpServer": { - "label": "NTP Server" + "label": "NTP сървър" }, "rsyslogServer": { "label": "Rsyslog Server" }, "ethernetConfigSettings": { "description": "Ethernet port configuration", - "label": "Ethernet Config" + "label": "Конфигурация на Ethernet " }, "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" + "description": "Конфигуриране на IP", + "label": "Конфигурация на IP" }, "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" + "description": "Конфигуриране на NTP", + "label": "Конфигурация на NTP" }, "rsyslogConfigSettings": { "description": "Rsyslog configuration", @@ -269,8 +269,8 @@ } }, "position": { - "title": "Position Settings", - "description": "Settings for the position module", + "title": "Настройки на позицията", + "description": "Настройки за модула за позиция", "broadcastInterval": { "description": "How often your position is sent out over the mesh", "label": "Broadcast Interval" @@ -281,15 +281,15 @@ }, "fixedPosition": { "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" + "label": "Фиксирана позиция" }, "gpsMode": { "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" + "label": "Режим на GPS" }, "gpsUpdateInterval": { "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" + "label": "Интервал на актуализиране на GPS" }, "positionFlags": { "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", @@ -317,11 +317,11 @@ }, "intervalsSettings": { "description": "How often to send position updates", - "label": "Intervals" + "label": "Интервали" }, "flags": { "placeholder": "Select position flags...", - "altitude": "Altitude", + "altitude": "Надморска височина", "altitudeGeoidalSeparation": "Altitude Geoidal Separation", "altitudeMsl": "Altitude is Mean Sea Level", "dop": "Dilution of precision (DOP) PDOP used by default", @@ -331,7 +331,7 @@ "timestamp": "Времево клеймо", "unset": "Отказ", "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" + "vehicleSpeed": "Скорост на превозното средство" } }, "power": { @@ -378,7 +378,7 @@ }, "security": { "description": "Settings for the Security configuration", - "title": "Security Settings", + "title": "Насртойки на сигурността", "button_backupKey": "Backup Key", "adminChannelEnabled": { "description": "Allow incoming device control over the insecure legacy admin channel", @@ -417,7 +417,7 @@ "label": "Tertiary Admin Key" }, "adminSettings": { - "description": "Settings for Admin", + "description": "Настройки за Admin", "label": "Admin Settings" }, "loggingSettings": { diff --git a/src/i18n/locales/bg-BG/dialog.json b/src/i18n/locales/bg-BG/dialog.json index 8d8e484a..1d9ea3f0 100644 --- a/src/i18n/locales/bg-BG/dialog.json +++ b/src/i18n/locales/bg-BG/dialog.json @@ -1,69 +1,70 @@ { "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" + "description": "Това действие ще изчисти цялата история на съобщенията. Това не може да бъде отменено. Сигурни ли сте, че искате да продължите?", + "title": "Изчистване на всички съобщения" }, "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" + "description": "Устройството ще се рестартира, след като конфигурацията бъде запазена.", + "longName": "Дълго име", + "shortName": "Кратко име", + "title": "Промяна на името на устройството" }, "import": { "description": "The current LoRa configuration will be overridden.", "error": { - "invalidUrl": "Invalid Meshtastic URL" + "invalidUrl": "Невалиден Meshtastic URL" }, - "channelPrefix": "Channel: ", + "channelPrefix": "Канал: ", "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", + "channels": "Канали:", "usePreset": "Use Preset?", "title": "Import Channel Set" }, "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" + "altitude": "Надморска височина: ", + "coordinates": "Координати:", + "title": "Местоположение: {{identifier}}" }, "pkiRegenerateDialog": { "title": "Regenerate Pre-Shared Key?", "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" + "regenerate": "Регенериране" }, "newDeviceDialog": { - "title": "Connect New Device", + "title": "Свързване на ново устройство", "https": "https", "http": "http", "tabHttp": "HTTP", "tabBluetooth": "Bluetooth", "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", + "useHttps": "Използване на HTTPS", + "connecting": "Свързване...", "connect": "Свързване", "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" + "title": "Връзката е неуспешна", + "descriptionPrefix": "Не може да се свърже с устройството.", + "httpsHint": "Ако използвате HTTPS, може да се наложи първо да приемете самоподписан сертификат. ", + "openLinkPrefix": "Моля, отворете", + "openLinkSuffix": "в нов раздел", + "acceptTlsWarningSuffix": "", + "learnMoreLink": "Научете повече" }, "httpConnection": { - "label": "IP Address/Hostname", + "label": "IP адрес/Име на хост", "placeholder": "000.000.000.000 / meshtastic.local" }, "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", + "noDevicesPaired": "Все още няма сдвоени устройства.", + "newDeviceButton": "Ново устройство", "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" }, "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" + "noDevicesPaired": "Все още няма сдвоени устройства.", + "newDeviceButton": "Ново устройство" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -74,17 +75,17 @@ "traceRoute": "Trace Route", "airTxUtilization": "Air TX utilization", "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", + "batteryLevel": "Ниво на батерията", + "channelUtilization": "Използване на канала", + "details": "Подробности:", "deviceMetrics": "Device Metrics:", - "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", + "hardware": "Хардуер: ", + "lastHeard": "Последно чут: ", "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", + "nodeNumber": "Номер на възела: ", + "position": "Позиция:", + "role": "Роля: ", + "uptime": "Време на работа: ", "voltage": "Напрежение", "title": "Node Details for {{identifier}}", "ignoreNode": "Ignore node", @@ -92,36 +93,42 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", - "footer": "=== END OF KEYS ===", - "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", + "loseKeysWarning": "Ако загубите ключовете си, ще трябва да нулирате устройството си.", + "secureBackup": "Важно е да направите резервно копие на публичните и частните си ключове и да съхранявате резервното си копие сигурно!", + "footer": "=== КРАЙ НА КЛЮЧОВЕТЕ ===", + "header": "=== MESHTASTIC КЛЮЧОВЕ ЗА {{longName}} ({{shortName}}) ===", + "privateKey": "Частен ключ:", + "publicKey": "Публичен ключ:", "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" + "description": "Сигурни ли сте, че искате да регенерирате двойката ключове?", + "title": "Регенериране на двойката ключове" }, "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", + "addChannels": "Добавяне на канали", + "replaceChannels": "Замяна на канали", + "description": "Текущата конфигурация на LoRa също ще бъде споделена.", "sharableUrl": "Sharable URL", - "title": "Generate QR Code" + "title": "Генериране на QR код" }, "rebootOta": { - "title": "Schedule Reboot", + "title": "Планирано рестартиране", "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" + "enterDelay": "Въведете забавяне (сек)", + "scheduled": "Насрочено е рестартиране" }, "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." + "title": "Планирано рестартиране", + "description": "Рестартиране на свързания възел след x минути." }, "refreshKeys": { "description": { @@ -133,12 +140,12 @@ "title": "Keys Mismatch - {{identifier}}" }, "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" + "description": "Сигурни ли сте, че искате да премахнете този възел?", + "title": "Премахване на възела?" }, "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." + "title": "Планирано изключване", + "description": "Изключване на свързания възел след x минути." }, "traceRoute": { "routeToDestination": "Route to destination:", @@ -148,12 +155,17 @@ "title": "Traceroute: {{identifier}}" }, "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", + "confirmUnderstanding": "Да, знам какво правя", "conjunction": " and the blog post about ", "postamble": " and understand the implications of changing the role.", "preamble": "I have read the ", "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Сигурни ли сте?" + }, + "managedMode": { + "confirmUnderstanding": "Да, знам какво правя", + "title": "Сигурни ли сте?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/bg-BG/messages.json b/src/i18n/locales/bg-BG/messages.json index 56f346cd..edad2226 100644 --- a/src/i18n/locales/bg-BG/messages.json +++ b/src/i18n/locales/bg-BG/messages.json @@ -1,40 +1,39 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Съобщения: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." + "title": "Изберете чат", + "text": "Все още няма съобщения." }, "selectChatPrompt": { "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Въведете Вашето съобщение тук...", "sendButton": "Изпрати" }, "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" + "addReactionLabel": "Добавяне на реакция", + "replyLabel": "Отговор" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Съобщението е доставено", + "displayText": "Съобщението е доставено" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Статусът на съобщението е неизвестен", + "displayText": "Неизвестно състояние" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/bg-BG/moduleConfig.json b/src/i18n/locales/bg-BG/moduleConfig.json index 32633d61..1b3eb924 100644 --- a/src/i18n/locales/bg-BG/moduleConfig.json +++ b/src/i18n/locales/bg-BG/moduleConfig.json @@ -1,7 +1,7 @@ { "page": { "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", + "tabAudio": "Аудио", "tabCannedMessage": "Canned", "tabDetectionSensor": "Detection Sensor", "tabExternalNotification": "Ext Notif", @@ -38,10 +38,10 @@ } }, "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", + "title": "Настройки на аудиото", + "description": "Настройки за аудио модула", "codec2Enabled": { - "label": "Codec 2 Enabled", + "label": "Codec 2 е активиран", "description": "Enable Codec 2 audio encoding" }, "pttPin": { @@ -73,12 +73,12 @@ "title": "Canned Message Settings", "description": "Settings for the Canned Message module", "moduleEnabled": { - "label": "Module Enabled", + "label": "Модулът е активиран", "description": "Enable Canned Message" }, "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" + "label": "Ротационен енкодер #1 е активиран", + "description": "Активиране на ротационния енкодер" }, "inputbrokerPinA": { "label": "Encoder Pin A", @@ -110,7 +110,7 @@ }, "allowInputSource": { "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + "description": "Изберете от: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" }, "sendBell": { "label": "Send Bell", @@ -121,7 +121,7 @@ "title": "Detection Sensor Settings", "description": "Settings for the Detection Sensor module", "enabled": { - "label": "Enabled", + "label": "Активиран", "description": "Enable or disable Detection Sensor Module" }, "minimumBroadcastSecs": { @@ -137,8 +137,8 @@ "description": "Send ASCII bell with alert message" }, "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" + "label": "Приятелско име", + "description": "Използва се за форматиране на съобщението, изпратено до mesh, максимум 20 знака" }, "monitorPin": { "label": "Monitor Pin", @@ -157,7 +157,7 @@ "title": "External Notification Settings", "description": "Configure the external notification module", "enabled": { - "label": "Module Enabled", + "label": "Модулът е активиран", "description": "Enable External Notification" }, "outputMs": { @@ -181,8 +181,8 @@ "description": "Active" }, "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" + "label": "Предупредително съобщение", + "description": "Предупредително съобщение" }, "alertMessageVibra": { "label": "Alert Message Vibrate", @@ -218,35 +218,35 @@ } }, "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", + "title": "Настройки на MQTT", + "description": "Настройки за MQTT модула", "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" + "label": "Активиран", + "description": "Активиране или дезактивиране на MQTT" }, "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" + "label": "Адрес на MQTT сървъра", + "description": "Адрес на MQTT сървъра, който да се използва за сървъри по подразбиране/персонализирани сървъри" }, "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" + "label": "Потребителско име за MQTT", + "description": "Потребителско име за MQTT, което да се използва за сървъри по подразбиране/персонализирани сървъри" }, "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" + "label": "Парола за MQTT", + "description": "Парола за MQTT, която да се използва за сървъри по подразбиране/персонализирани сървъри" }, "encryptionEnabled": { - "label": "Encryption Enabled", + "label": "Криптирането е активирано", "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." }, "jsonEnabled": { - "label": "JSON Enabled", + "label": "JSON е активиран", "description": "Whether to send/consume JSON packets on MQTT" }, "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" + "label": "TLS е активиран", + "description": "Активиране или дезактивиране на TLS" }, "root": { "label": "Root topic", @@ -266,7 +266,7 @@ "description": "Interval in seconds to publish map reports" }, "positionPrecision": { - "label": "Approximate Location", + "label": "Приблизително местоположение", "description": "Position shared will be accurate within this distance", "options": { "metric_km23": "Within 23 km", @@ -297,7 +297,7 @@ "title": "Neighbor Info Settings", "description": "Settings for the Neighbor Info module", "enabled": { - "label": "Enabled", + "label": "Активиран", "description": "Enable or disable Neighbor Info Module" }, "updateInterval": { @@ -307,10 +307,10 @@ }, "paxcounter": { "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", + "description": "Настройки за модула Paxcounter", "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" + "label": "Модулът е активиран", + "description": "Активиране на Paxcounter" }, "paxcounterUpdateInterval": { "label": "Update Interval (seconds)", @@ -338,14 +338,14 @@ }, "save": { "label": "Save CSV to storage", - "description": "ESP32 Only" + "description": "Само ESP32" } }, "serial": { "title": "Serial Settings", "description": "Settings for the Serial module", "enabled": { - "label": "Module Enabled", + "label": "Модулът е активиран", "description": "Enable Serial output" }, "echo": { @@ -369,8 +369,8 @@ "description": "Seconds to wait before we consider your packet as 'done'" }, "mode": { - "label": "Mode", - "description": "Select Mode" + "label": "Режим", + "description": "Избор на режим" }, "overrideConsoleSerialPort": { "label": "Override Console Serial Port", @@ -381,7 +381,7 @@ "title": "Store & Forward Settings", "description": "Settings for the Store & Forward module", "enabled": { - "label": "Module Enabled", + "label": "Модулът е активиран", "description": "Enable Store & Forward" }, "heartbeat": { @@ -402,8 +402,8 @@ } }, "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", + "title": "Настройки на телеметрията", + "description": "Настройки за модула за телеметрия", "deviceUpdateInterval": { "label": "Device Metrics", "description": "Device metrics update interval (seconds)" @@ -413,7 +413,7 @@ "description": "" }, "environmentMeasurementEnabled": { - "label": "Module Enabled", + "label": "Модулът е активиран", "description": "Enable the Environment Telemetry" }, "environmentScreenEnabled": { @@ -421,12 +421,12 @@ "description": "Show the Telemetry Module on the OLED" }, "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" + "label": "Показване на Фаренхайт", + "description": "Показване на температурата във Фаренхайт" }, "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" + "label": "Качество на въздуха е активирано", + "description": "Активиране на телеметрията за качеството на въздуха" }, "airQualityInterval": { "label": "Air Quality Update Interval", diff --git a/src/i18n/locales/bg-BG/nodes.json b/src/i18n/locales/bg-BG/nodes.json index 5202f039..760c708d 100644 --- a/src/i18n/locales/bg-BG/nodes.json +++ b/src/i18n/locales/bg-BG/nodes.json @@ -1,19 +1,24 @@ { "nodeDetail": { "publicKeyEnabled": { - "label": "Public Key Enabled" + "label": "Публичният ключ е активиран" }, "noPublicKey": { - "label": "No Public Key" + "label": "Няма публичен ключ" }, "directMessage": { - "label": "Direct Message {{shortName}}" + "label": "Директно съобщение {{shortName}}" }, "favorite": { - "label": "Favorite" + "label": "Любим", + "tooltip": "Добавяне или премахване на този възел от любимите ви" }, "notFavorite": { - "label": "Not a Favorite" + "label": "Не е любим" + }, + "error": { + "label": "Грешка", + "text": "Възникна грешка при извличането на подробности за възела. Моля, опитайте отново по-късно." }, "status": { "heard": "Heard", @@ -31,21 +36,28 @@ }, "nodesTable": { "headings": { - "longName": "Long Name", + "longName": "Дълго име", "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" + "lastHeard": "Последно чут", + "encryption": "Криптиране", + "model": "Модел", + "macAddress": "MAC адрес" }, "connectionStatus": { "direct": "Direct", "away": "away", "unknown": "-", - "viaMqtt": ", via MQTT" + "viaMqtt": ", чрез MQTT" }, "lastHeardStatus": { - "never": "Never" + "never": "Никога" } + }, + "actions": { + "added": "Добавен", + "removed": "Премахнат", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/bg-BG/ui.json b/src/i18n/locales/bg-BG/ui.json index bab99b20..e635ba10 100644 --- a/src/i18n/locales/bg-BG/ui.json +++ b/src/i18n/locales/bg-BG/ui.json @@ -1,49 +1,49 @@ { "navigation": { - "title": "Navigation", + "title": "Навигация", "messages": "Съобщения", "map": "Карта", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", + "config": "Конфигурация", + "radioConfig": "Конфигурация на радиото", + "moduleConfig": "Конфигурация на модула", "channels": "Канали", "nodes": "Възли" }, "app": { "title": "Meshtastic", - "logo": "Meshtastic Logo" + "logo": "Лого на Meshtastic" }, "sidebar": { "collapseToggle": { "button": { - "open": "Open sidebar", - "close": "Close sidebar" + "open": "Отваряне на страничната лента", + "close": "Затваряне на страничната лента" } }, "deviceInfo": { - "volts": "{{voltage}} volts", + "volts": "{{voltage}} волта", "firmware": { "title": "Фърмуер", "version": "v{{version}}", - "buildDate": "Build date: {{date}}" + "buildDate": "Дата на компилация: {{date}}" }, "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" + "title": "Име на устройството", + "changeName": "Промяна на името на устройството", + "placeholder": "Въвеждане на име на устройството" }, - "editDeviceName": "Edit device name" + "editDeviceName": "Редактиране на името на устройство" } }, "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", + "charging": "{{level}}% зареждане", + "pluggedIn": "Включен в ел. мрежа", "title": "Батерия" }, "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." + "nodes": "Търсене на възли...", + "channels": "Търсене на канали...", + "commandPalette": "Търсене на команди..." }, "toast": { "positionRequestSent": { @@ -59,35 +59,53 @@ "title": "Traceroute sent." }, "savedChannel": { - "title": "Saved Channel: {{channelName}}" + "title": "Запазен канал: {{channelName}}" }, "messages": { "pkiEncryption": { - "title": "Chat is using PKI encryption." + "title": "Чатът използва PKI криптиране." }, "pskEncryption": { - "title": "Chat is using PSK encryption." + "title": "Чатът използва PSK криптиране." } }, "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." + "title": "Грешка при запазване на конфигурацията", + "description": "Възникна грешка при запазване на конфигурацията." }, "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." + "title": "Съществуват грешки в конфигурацията", + "description": "Моля, коригирайте грешките в конфигурацията, преди да я запазите." }, "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." + "title": "Запазване на конфигурацията", + "description": "Промяната в конфигурацията {{case}} е запазена." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { "copied": { - "label": "Copied!" + "label": "Копирано!" }, "copyToClipboard": { - "label": "Copy to clipboard" + "label": "Копиране в клипборда" }, "hidePassword": { "label": "Скриване на паролата" @@ -98,7 +116,7 @@ "deliveryStatus": { "delivered": "Delivered", "failed": "Delivery Failed", - "waiting": "Waiting", + "waiting": "Изчакване", "unknown": "Unknown" } }, @@ -117,29 +135,32 @@ "filter": { "label": "Филтър" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, "resetFilters": { - "label": "Reset Filters" + "label": "Нулиране на филтрите" }, "nodeName": { - "label": "Node name/number", + "label": "Име/номер на възел", "placeholder": "Meshtastic 1234" }, "airtimeUtilization": { "label": "Airtime Utilization (%)" }, "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" + "label": "Ниво на батерията (%)", + "labelText": "Ниво на батерията (%): {{value}}" }, "batteryVoltage": { - "label": "Battery voltage (V)", + "label": "Напрежение на батерията (V)", "title": "Напрежение" }, "channelUtilization": { - "label": "Channel Utilization (%)" + "label": "Използване на канала (%)" }, "hops": { "direct": "Direct", @@ -149,13 +170,13 @@ "lastHeard": { "label": "Последно чут", "labelText": "Last heard: {{value}}", - "nowLabel": "Now" + "nowLabel": "Сега" }, "snr": { "label": "SNR (db)" }, "favorites": { - "label": "Favorites" + "label": "Любими" }, "hide": { "label": "Hide" @@ -164,38 +185,44 @@ "label": "Show Only" }, "viaMqtt": { - "label": "Connected via MQTT" + "label": "Свързан чрез MQTT" + }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" }, "language": { "label": "Език", - "changeLanguage": "Change Language" + "changeLanguage": "Промяна на езика" }, "theme": { "dark": "Тъмна", "light": "Светла", - "system": "Automatic", - "changeTheme": "Change Color Scheme" + "system": "Автоматично", + "changeTheme": "Промяна на цветовата схема" }, "errorPage": { "title": "This is a little embarrassing...", "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", + "reportInstructions": "Моля, включете следната информация в доклада си:", "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", + "step1": "Какво правехте, когато възникна грешката", + "step2": "Какво очаквахте да се случи", + "step3": "Какво всъщност се случи", + "step4": "Всяка друга подходяща информация" + }, + "reportLink": "Можете да съобщите за проблема в нашия <0>GitHub", + "dashboardLink": "Връщане към <0>таблото", + "detailsSummary": "Подробности за грешката", + "errorMessageLabel": "Съобщение за грешка:", "stackTraceLabel": "Stack trace:", "fallbackError": "{{error}}" }, "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "text": "Задвижвано от <0>▲ Vercel | Meshtastic® е регистрирана търговска марка на Meshtastic LLC. | <1>Правна информация", "commitSha": "Commit SHA: {{sha}}" } } diff --git a/src/i18n/locales/cs-CZ/common.json b/src/i18n/locales/cs-CZ/common.json index dd918f3b..0d4f47ca 100644 --- a/src/i18n/locales/cs-CZ/common.json +++ b/src/i18n/locales/cs-CZ/common.json @@ -24,7 +24,8 @@ "reset": "Reset", "save": "Uložit", "scanQr": "Naskenovat QR kód", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/cs-CZ/dialog.json b/src/i18n/locales/cs-CZ/dialog.json index cf2c0735..dbe2aab6 100644 --- a/src/i18n/locales/cs-CZ/dialog.json +++ b/src/i18n/locales/cs-CZ/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Jste si jistý?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Jste si jistý?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/cs-CZ/messages.json b/src/i18n/locales/cs-CZ/messages.json index 12f340e9..e4ddb17d 100644 --- a/src/i18n/locales/cs-CZ/messages.json +++ b/src/i18n/locales/cs-CZ/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Odeslat" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "Reply" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/cs-CZ/nodes.json b/src/i18n/locales/cs-CZ/nodes.json index 4f0694de..df4b4c6a 100644 --- a/src/i18n/locales/cs-CZ/nodes.json +++ b/src/i18n/locales/cs-CZ/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Oblíbené" + "label": "Oblíbené", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Chyba", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/cs-CZ/ui.json b/src/i18n/locales/cs-CZ/ui.json index f173ed53..550b2af2 100644 --- a/src/i18n/locales/cs-CZ/ui.json +++ b/src/i18n/locales/cs-CZ/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filtr" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Jazyk", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/de-DE/common.json b/src/i18n/locales/de-DE/common.json index 3a8af3a5..b02e09d6 100644 --- a/src/i18n/locales/de-DE/common.json +++ b/src/i18n/locales/de-DE/common.json @@ -24,7 +24,8 @@ "reset": "Zurücksetzen", "save": "Speichern", "scanQr": "QR Code scannen", - "traceRoute": "Route verfolgen" + "traceRoute": "Route verfolgen", + "submit": "Absenden" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minuten" }, + "hour": { + "one": "Stunde", + "plural": "Stunden" + }, "millisecond": { "one": "Millisekunde", "plural": "Millisekunden", @@ -64,6 +69,18 @@ "one": "Sekunde", "plural": "Sekunden" }, + "day": { + "one": "Tag", + "plural": "Tage" + }, + "month": { + "one": "Monat", + "plural": "Monate" + }, + "year": { + "one": "Jahr", + "plural": "Jahre" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Leer", + "8bit": "8 Bit", + "128bit": "128 Bit", "256bit": "256 Bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "NICHT GESETZT", "fallbackName": "Meshtastic {{last4}}", + "node": "Knoten", "formValidation": { + "unsavedChanges": "Ungespeicherte Änderungen", "tooBig": { "string": "Zu lang, erwarte maximal {{maximum}} Zeichen.", "number": "Zu groß, erwartete eine Zahl kleiner oder gleich {{maximum}}.", diff --git a/src/i18n/locales/de-DE/dialog.json b/src/i18n/locales/de-DE/dialog.json index b385e70b..1c8e966d 100644 --- a/src/i18n/locales/de-DE/dialog.json +++ b/src/i18n/locales/de-DE/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "Neues Gerät" }, "validation": { - "requiresFeatures": "Dieser Verbindungstyp erfordert <0>. Bitte verwenden Sie einen unterstützten Browser, wie Chrome oder Edge.", + "requiresWebBluetooth": "Dieser Verbindungstyp erfordert <0>Bluetooth im Browser. Bitte verwenden Sie einen unterstützten Browser, wie Chrome oder Edge.", + "requiresWebSerial": "Dieser Verbindungstyp erfordert <0>Serielle Schnittstelle im Browser. Bitte verwenden Sie einen unterstützten Browser, wie Chrome oder Edge.", "requiresSecureContext": "Diese Anwendung erfordert einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost.", "additionallyRequiresSecureContext": "Zusätzlich erfordert es einen <0>sicheren Kontext. Bitte verbinden Sie sich über HTTPS oder localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Knoten akzeptieren" }, "pkiBackup": { - "description": "Wir empfehlen die regelmäßige Sicherung Ihrer Schlüsseldaten. Möchten Sie jetzt sicheren?", "loseKeysWarning": "Wenn Sie Ihre Schlüssel verlieren, müssen Sie Ihr Gerät zurücksetzen.", "secureBackup": "Es ist wichtig, dass Sie Ihre öffentlichen und privaten Schlüssel sichern und diese sicher speichern!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Schlüssel sichern" }, + "pkiBackupReminder": { + "description": "Wir empfehlen die regelmäßige Sicherung Ihrer Schlüsseldaten. Möchten Sie jetzt sicheren?", + "title": "Erinnerungen für Sicherungen", + "remindLaterPrefix": "Erinnerung in:", + "remindNever": "Nie erinnern", + "backupNow": "Jetzt sichern" + }, "pkiRegenerate": { "description": "Sind Sie sicher, dass Sie Schlüsselpaar neu erstellen möchten?", "title": "Schlüsselpaar neu erstellen" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Wahl der richtigen Geräterolle", "deviceRoleDocumentation": "Dokumentation der Geräterolle", "title": "Bist Du sicher?" + }, + "managedMode": { + "confirmUnderstanding": "Ja, ich weiß, was ich tue!", + "title": "Bist Du sicher?", + "description": "Das Aktivieren des verwalteten Modus blockiert das Schreiben der Einstellungen in das Funkgerät durch alle Anwendungen (einschließlich der Webanwendung). Einmal aktiviert, können die Einstellungen nur durch administrative Nachrichten geändert werden. Diese Einstellung ist für die Fernverwaltung von abgesetzten Knoten nicht erforderlich." } } diff --git a/src/i18n/locales/de-DE/messages.json b/src/i18n/locales/de-DE/messages.json index 401e425b..02f1435c 100644 --- a/src/i18n/locales/de-DE/messages.json +++ b/src/i18n/locales/de-DE/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Nachrichten: {{chatName}}" + "title": "Nachrichten: {{chatName}}", + "placeholder": "Nachricht eingeben" }, "emptyState": { "title": "Einen Chat auswählen", @@ -10,31 +11,29 @@ "text": "Wählen Sie einen Kanal oder Knoten, um Nachrichten zu schreiben." }, "sendMessage": { - "placeholder": "Geben Sie Ihre Nachricht hier ein...", + "placeholder": "Geben Sie hier Ihre Nachricht ein...", "sendButton": "Senden" }, "actionsMenu": { "addReactionLabel": "Reaktion hinzufügen", "replyLabel": "Antworten" }, - "item": { - "status": { - "delivered": { - "label": "Nachricht zugestellt", - "displayText": "Nachricht zugestellt" - }, - "failed": { - "label": "Nachrichtenübermittlung fehlgeschlagen", - "displayText": "Zustellung fehlgeschlagen" - }, - "unknown": { - "label": "Nachrichtenstatus unbekannt", - "displayText": "Unbekannter Status" - }, - "waiting": { - "ariaLabel": "Nachricht wird gesendet", - "displayText": "Warte auf Zustellung" - } + "deliveryStatus": { + "delivered": { + "label": "Nachricht zugestellt", + "displayText": "Nachricht zugestellt" + }, + "failed": { + "label": "Nachrichtenübermittlung fehlgeschlagen", + "displayText": "Zustellung fehlgeschlagen" + }, + "unknown": { + "label": "Nachrichtenstatus unbekannt", + "displayText": "Unbekannter Status" + }, + "waiting": { + "label": "Nachricht wird gesendet", + "displayText": "Warte auf Zustellung" } } } diff --git a/src/i18n/locales/de-DE/nodes.json b/src/i18n/locales/de-DE/nodes.json index af9df668..de1e038d 100644 --- a/src/i18n/locales/de-DE/nodes.json +++ b/src/i18n/locales/de-DE/nodes.json @@ -10,11 +10,16 @@ "label": "Direktnachricht {{shortName}}" }, "favorite": { - "label": "Favorit" + "label": "Favorit", + "tooltip": "Diesen Knoten zu Favoriten hinzufügen oder entfernen" }, "notFavorite": { "label": "Kein Favorit" }, + "error": { + "label": "Fehler", + "text": "Beim Abrufen der Knotendetails ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut." + }, "status": { "heard": "Gehört", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Nie" } + }, + "actions": { + "added": "Hinzugefügt", + "removed": "Entfernt", + "ignoreNode": "Knoten ignorieren", + "unignoreNode": "Knoten akzeptieren", + "requestPosition": "Standort anfordern" } } diff --git a/src/i18n/locales/de-DE/ui.json b/src/i18n/locales/de-DE/ui.json index 23e4f9d0..bc7c1853 100644 --- a/src/i18n/locales/de-DE/ui.json +++ b/src/i18n/locales/de-DE/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Einstellungen speichern", "description": "Die Einstellungsänderung {{case}} wurde gespeichert." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} Favoriten.", + "action": { + "added": "Hinzugefügt", + "removed": "Entfernt", + "to": "bis", + "from": "von" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} Ignorierliste", + "action": { + "added": "Hinzugefügt", + "removed": "Entfernt", + "to": "bis", + "from": "von" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filter" }, + "advanced": { + "label": "Fortgeschritten" + }, "clearInput": { "label": "Eingabe löschen" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Über MQTT verbunden" }, + "hopsUnknown": { + "label": "Unbekannte Sprungweite" + }, + "showUnheard": { + "label": "Nie gehört" + }, "language": { "label": "Sprache", "changeLanguage": "Sprache ändern" diff --git a/src/i18n/locales/es-ES/common.json b/src/i18n/locales/es-ES/common.json index e5da6d9f..c566496b 100644 --- a/src/i18n/locales/es-ES/common.json +++ b/src/i18n/locales/es-ES/common.json @@ -24,7 +24,8 @@ "reset": "Reiniciar", "save": "Guardar", "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/es-ES/dialog.json b/src/i18n/locales/es-ES/dialog.json index 97f12d8f..149e317f 100644 --- a/src/i18n/locales/es-ES/dialog.json +++ b/src/i18n/locales/es-ES/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "¿Estás seguro?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "¿Estás seguro?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/es-ES/messages.json b/src/i18n/locales/es-ES/messages.json index 09c10917..fb7d1fcb 100644 --- a/src/i18n/locales/es-ES/messages.json +++ b/src/i18n/locales/es-ES/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Enviar" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "Reply" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/es-ES/nodes.json b/src/i18n/locales/es-ES/nodes.json index 366eee1d..6d5dec63 100644 --- a/src/i18n/locales/es-ES/nodes.json +++ b/src/i18n/locales/es-ES/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favorito" + "label": "Favorito", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Error", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/es-ES/ui.json b/src/i18n/locales/es-ES/ui.json index efa3a1f6..4d4bef7c 100644 --- a/src/i18n/locales/es-ES/ui.json +++ b/src/i18n/locales/es-ES/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filtro" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Idioma", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/fi-FI/common.json b/src/i18n/locales/fi-FI/common.json index beb5a9d4..01ef9ed8 100644 --- a/src/i18n/locales/fi-FI/common.json +++ b/src/i18n/locales/fi-FI/common.json @@ -24,7 +24,8 @@ "reset": "Palauta", "save": "Tallenna", "scanQr": "Skannaa QR-koodi", - "traceRoute": "Reitinselvitys" + "traceRoute": "Reitinselvitys", + "submit": "Lähetä" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minuutti", "plural": "Minuuttia" }, + "hour": { + "one": "Tunti", + "plural": "Tuntia" + }, "millisecond": { "one": "Millisekunti", "plural": "Millisekuntia", @@ -64,6 +69,18 @@ "one": "Sekunti", "plural": "Sekuntia" }, + "day": { + "one": "Päivä", + "plural": "Päivää" + }, + "month": { + "one": "Kuukausi", + "plural": "Kuukautta" + }, + "year": { + "one": "Vuosi", + "plural": "Vuotta" + }, "snr": "SNR", "volt": { "one": "Voltti", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Tyhjä", + "8bit": "8-bittiä", + "128bit": "128-bittiä", "256bit": "256 bittiä" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "EI ASETETTU", "fallbackName": "Meshtastic {{last4}}", + "node": "Laite", "formValidation": { + "unsavedChanges": "Tallentamattomat muutokset", "tooBig": { "string": "Teksti on liian pitkä – sallittu enimmäispituus on {{maximum}} merkkiä.", "number": "Arvo on liian suuri – sallittu enimmäisarvo on {{maximum}}.", diff --git a/src/i18n/locales/fi-FI/dialog.json b/src/i18n/locales/fi-FI/dialog.json index 04c35775..579dacb8 100644 --- a/src/i18n/locales/fi-FI/dialog.json +++ b/src/i18n/locales/fi-FI/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "Uusi laite" }, "validation": { - "requiresFeatures": "Tämä yhteystyyppi vaatii <0>. Käytä tuettua selainta, kuten Chromea tai Edgeä.", + "requiresWebBluetooth": "Tämä yhteystyyppi vaatii <0>Web-sarjaportti bluetooth -tuen. Käytä tuettua selainta, kuten Chromea tai Edgeä.", + "requiresWebSerial": "Tämä yhteystyyppi vaatii <0>Web-sarjaportti -tuen. Käytä tuettua selainta, kuten Chromea tai Edgeä.", "requiresSecureContext": "Tämä sovellus vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia.", "additionallyRequiresSecureContext": "Lisäksi se vaatii <0>suojatun yhteyden. Yhdistä käyttämällä HTTPS:ää tai localhostia." } @@ -92,7 +93,6 @@ "unignoreNode": "Poista laitteen ohitus käytöstä" }, "pkiBackup": { - "description": "Suosittelemme avaintietojen säännöllistä varmuuskopiointia. Haluatko varmuuskopioida nyt?", "loseKeysWarning": "Jos menetät avaimesi, sinun täytyy palauttaa laite tehdasasetuksiin.", "secureBackup": "On tärkeää varmuuskopioida julkiset ja yksityiset avaimet ja säilyttää niiden varmuuskopioita turvallisesti!", "footer": "=== AVAIMIEN LOPPU ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_avaimet_{{longName}}_{{shortName}}.txt", "title": "Varmuuskopioi avaimet" }, + "pkiBackupReminder": { + "description": "Suosittelemme avaintietojen säännöllistä varmuuskopiointia. Haluatko varmuuskopioida nyt?", + "title": "Varmuuskopion Muistutus", + "remindLaterPrefix": "Muistuta minua", + "remindNever": "Älä muistuta minua koskaan", + "backupNow": "Varmuuskopioi nyt" + }, "pkiRegenerate": { "description": "Haluatko varmasti luoda avainparin uudelleen?", "title": "Luo avainpari uudelleen" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Valitse laitteelle oikea rooli", "deviceRoleDocumentation": "Roolien dokumentaatio laitteelle", "title": "Oletko varma?" + }, + "managedMode": { + "confirmUnderstanding": "Kyllä, tiedän mitä teen", + "title": "Oletko varma?", + "description": "Hallintatilan käyttöönotto estää asiakassovelluksia (mukaan lukien verkkosovellus) kirjoittamasta asetuksia radioon. Kun tila on otettu käyttöön, radion asetuksia voidaan muuttaa vain etähallintaviestien kautta. Tämä asetus ei ole pakollinen etähallittavien laitteiden hallintaan." } } diff --git a/src/i18n/locales/fi-FI/messages.json b/src/i18n/locales/fi-FI/messages.json index b37421ef..7fc4247f 100644 --- a/src/i18n/locales/fi-FI/messages.json +++ b/src/i18n/locales/fi-FI/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Viestit: {{chatName}}" + "title": "Viestit: {{chatName}}", + "placeholder": "Kirjoita viesti" }, "emptyState": { "title": "Valitse keskustelu", @@ -17,24 +18,22 @@ "addReactionLabel": "Lisää reaktio", "replyLabel": "Vastaa" }, - "item": { - "status": { - "delivered": { - "label": "Viesti toimitettu", - "displayText": "Viesti toimitettu" - }, - "failed": { - "label": "Viestin toimitus epäonnistui", - "displayText": "Toimitus epäonnistui" - }, - "unknown": { - "label": "Viestin tila tuntematon", - "displayText": "Tuntematon tila" - }, - "waiting": { - "ariaLabel": "Lähetetään viestiä", - "displayText": "Odottaa toimitusta" - } + "deliveryStatus": { + "delivered": { + "label": "Viesti toimitettu", + "displayText": "Viesti toimitettu" + }, + "failed": { + "label": "Viestin toimitus epäonnistui", + "displayText": "Toimitus epäonnistui" + }, + "unknown": { + "label": "Viestin tila tuntematon", + "displayText": "Tuntematon tila" + }, + "waiting": { + "label": "Lähetetään viestiä", + "displayText": "Odottaa toimitusta" } } } diff --git a/src/i18n/locales/fi-FI/nodes.json b/src/i18n/locales/fi-FI/nodes.json index 8c2b7401..40acfbb4 100644 --- a/src/i18n/locales/fi-FI/nodes.json +++ b/src/i18n/locales/fi-FI/nodes.json @@ -10,11 +10,16 @@ "label": "Suora Viesti {{shortName}}" }, "favorite": { - "label": "Suosikki" + "label": "Suosikki", + "tooltip": "Lisää tai poista tämä laite suosikeistasi" }, "notFavorite": { "label": "Ei suosikki" }, + "error": { + "label": "Virhe", + "text": "Tapahtui virhe haettaessa laitteen tietoja. Yritä uudelleen myöhemmin." + }, "status": { "heard": "Kuultu", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Ei koskaan" } + }, + "actions": { + "added": "Lisätty", + "removed": "Poistettu", + "ignoreNode": "Älä huomioi laitetta", + "unignoreNode": "Huomioi laite uudelleen", + "requestPosition": "Pyydä sijaintia" } } diff --git a/src/i18n/locales/fi-FI/ui.json b/src/i18n/locales/fi-FI/ui.json index f0fb9477..77c15c9d 100644 --- a/src/i18n/locales/fi-FI/ui.json +++ b/src/i18n/locales/fi-FI/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Tallennetaan asetukset", "description": "Asetuksien muutos {{case}} on tallennettu." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} suosikit.", + "action": { + "added": "Lisätty", + "removed": "Poistettu", + "to": "saakka", + "from": "alkaen" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} estolista", + "action": { + "added": "Lisätty", + "removed": "Poistettu", + "to": "saakka", + "from": "alkaen" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Suodatus" }, + "advanced": { + "label": "Lisäasetukset" + }, "clearInput": { "label": "Tyhjennä kenttä" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Yhdistetty MQTT-yhteydellä" }, + "hopsUnknown": { + "label": "Tuntematon määrä hyppyjä" + }, + "showUnheard": { + "label": "Ei koskaan kuultu" + }, "language": { "label": "Kieli", "changeLanguage": "Vaihda kieli" @@ -178,7 +205,7 @@ }, "errorPage": { "title": "Tämä on hieman noloa...", - "description1": "Pahoittelemme, mutta verkkosovelluksessa tapahtui virhe, joka aiheutti kaatumisen.
\nTämän ei pitäisi tapahtua ja me työskentelemme ahkerasti ongelman korjaamiseksi.", + "description1": "Pahoittelemme, mutta verkkosovelluksessa tapahtui virhe, joka aiheutti kaatumisen.
\nTällaista ei pitäisi tapahtua ja me työskentelemme ahkerasti ongelman korjaamiseksi.", "description2": "Paras tapa estää tämän tapahtuminen uudelleen sinulle tai kenellekään muulle, on ilmoittaa meille ongelmasta.", "reportInstructions": "Lisääthän raporttiisi seuraavat tiedot:", "reportSteps": { @@ -188,7 +215,7 @@ "step4": "Muut mahdollisesti oleelliset tiedot" }, "reportLink": "Voit raportoida ongelmasta <0>GitHubissa", - "dashboardLink": "Palaa takaisin <0>dashboard", + "dashboardLink": "Palaa takaisin <0>hallintapaneeliin", "detailsSummary": "Virheen tiedot", "errorMessageLabel": "Virheilmoitus:", "stackTraceLabel": "Virheen jäljityslista:", @@ -196,6 +223,6 @@ }, "footer": { "text": "Powered by <0>▲ Vercel | Meshtastic® on Meshtastic LLC:n rekisteröity tavaramerkki. | <1>Oikeudelliset tiedot", - "commitSha": "Versiokomentoviestin SHA-tunniste: {{sha}}" + "commitSha": "Ohjelmistokehitysversion SHA-tunniste: {{sha}}" } } diff --git a/src/i18n/locales/fr-FR/common.json b/src/i18n/locales/fr-FR/common.json index b3e4bc9b..00196840 100644 --- a/src/i18n/locales/fr-FR/common.json +++ b/src/i18n/locales/fr-FR/common.json @@ -24,7 +24,8 @@ "reset": "Réinitialiser", "save": "Sauvegarder", "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/fr-FR/dialog.json b/src/i18n/locales/fr-FR/dialog.json index b7b9c962..3440a37d 100644 --- a/src/i18n/locales/fr-FR/dialog.json +++ b/src/i18n/locales/fr-FR/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Êtes-vous sûr ?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Êtes-vous sûr ?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/fr-FR/messages.json b/src/i18n/locales/fr-FR/messages.json index 50f9b606..0eb7d37b 100644 --- a/src/i18n/locales/fr-FR/messages.json +++ b/src/i18n/locales/fr-FR/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Envoyer" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "Répondre" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/fr-FR/nodes.json b/src/i18n/locales/fr-FR/nodes.json index 1e088170..07375418 100644 --- a/src/i18n/locales/fr-FR/nodes.json +++ b/src/i18n/locales/fr-FR/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favoris" + "label": "Favoris", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Erreur", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Capté", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/fr-FR/ui.json b/src/i18n/locales/fr-FR/ui.json index ff4ef6b8..0d14f2bf 100644 --- a/src/i18n/locales/fr-FR/ui.json +++ b/src/i18n/locales/fr-FR/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filtre" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Langue", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/it-IT/channels.json b/src/i18n/locales/it-IT/channels.json index c25a7b70..5f3480d9 100644 --- a/src/i18n/locales/it-IT/channels.json +++ b/src/i18n/locales/it-IT/channels.json @@ -1,69 +1,69 @@ { "page": { "sectionLabel": "Canali", - "channelName": "Channel: {{channelName}}", + "channelName": "Canale {{channelName}}", "broadcastLabel": "Principale", "channelIndex": "Ch {{index}}" }, "validation": { - "pskInvalid": "Please enter a valid {{bits}} bit PSK." + "pskInvalid": "Per favore inserisci un PSK valido di {{bits}} bit." }, "settings": { "label": "Impostazioni Canale", - "description": "Crypto, MQTT & misc settings" + "description": "Impostazioni di Crypto, MQTT e varie" }, "role": { "label": "Ruolo", - "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "description": "La telemetria del dispositivo è inviata su PRIMARIO. Solo un PRIMARIO è consentito", "options": { - "primary": "PRIMARY", - "disabled": "DISABLED", - "secondary": "SECONDARY" + "primary": "PRIMARIO", + "disabled": "DISABILITATO", + "secondary": "SECONDARIO" } }, "psk": { - "label": "Pre-Shared Key", - "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" + "label": "Chiave Pre-Condivisa", + "description": "Lunghezze PSK supportate: 256-bit, 128-bit, 8-bit, Vuoto (0-bit)", + "generate": "Genera" }, "name": { "label": "Nome", - "description": "A unique name for the channel <12 bytes, leave blank for default" + "description": "Un nome univoco per il canale <12 byte, lascia vuoto per default" }, "uplinkEnabled": { - "label": "Uplink Enabled", - "description": "Send messages from the local mesh to MQTT" + "label": "Uplink Abilitato", + "description": "Invia messaggi dalla mesh locale a MQTT" }, "downlinkEnabled": { - "label": "Downlink Enabled", - "description": "Send messages from MQTT to the local mesh" + "label": "Uplink Abilitato", + "description": "Invia messaggi da MQTT alla mesh locale" }, "positionPrecision": { - "label": "Location", - "description": "The precision of the location to share with the channel. Can be disabled.", + "label": "Posizione", + "description": "La precisione della posizione da condividere con il canale. Può essere disabilitata.", "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" + "none": "Non condividere la posizione", + "precise": "Posizione precisa", + "metric_km23": "Entro 23 chilometri", + "metric_km12": "Entro 12 chilometri", + "metric_km5_8": "Entro 5,8 chilometri", + "metric_km2_9": "Entro 2,9 chilometri", + "metric_km1_5": "Entro 1,5 chilometri", + "metric_m700": "Entro 700 metri", + "metric_m350": "Entro 350 metri", + "metric_m200": "Entro 200 metri", + "metric_m90": "Entro 90 metri", + "metric_m50": "Entro 50 metri", + "imperial_mi15": "Entro 15 miglia", + "imperial_mi7_3": "Entro 7,3 miglia", + "imperial_mi3_6": "Entro 3,6 miglia", + "imperial_mi1_8": "Entro 1,8 miglia", + "imperial_mi0_9": "Entro 0,9 miglia", + "imperial_mi0_5": "Entro 0,5 miglia", + "imperial_mi0_2": "Entro 0,2 miglia", + "imperial_ft600": "Entro 600 piedi", + "imperial_ft300": "Entro 300 piedi", + "imperial_ft150": "Entro 150 piedi" } } } diff --git a/src/i18n/locales/it-IT/commandPalette.json b/src/i18n/locales/it-IT/commandPalette.json index 28f2f942..9f80b57e 100644 --- a/src/i18n/locales/it-IT/commandPalette.json +++ b/src/i18n/locales/it-IT/commandPalette.json @@ -1,50 +1,50 @@ { - "emptyState": "No results found.", + "emptyState": "Nessun risultato trovato.", "page": { - "title": "Command Menu" + "title": "Menu Comandi" }, "pinGroup": { - "label": "Pin command group" + "label": "Fissa gruppo comandi" }, "unpinGroup": { - "label": "Unpin command group" + "label": "Rimuovi gruppo comandi" }, "goto": { - "label": "Goto", + "label": "Vai a", "command": { "messages": "Messaggi", "map": "Mappa", - "config": "Config", + "config": "Configurazione", "channels": "Canali", "nodes": "Nodi" } }, "manage": { - "label": "Manage", + "label": "Gestisci", "command": { - "switchNode": "Switch Node", - "connectNewNode": "Connect New Node" + "switchNode": "Cambia Nodo", + "connectNewNode": "Connetti Nuovo Nodo" } }, "contextual": { - "label": "Contextual", + "label": "Contestuale", "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", + "qrCode": "Codice QR", + "qrGenerator": "Generatore", "qrImport": "Importa", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", - "rebootToOtaMode": "Reboot To OTA Mode", - "resetNodeDb": "Reset Node DB", - "factoryResetDevice": "Factory Reset Device", - "factoryResetConfig": "Factory Reset Config" + "scheduleShutdown": "Pianifica Spegnimento", + "scheduleReboot": "Pianifica Riavvio", + "rebootToOtaMode": "Riavvia In Modalità OTA", + "resetNodeDb": "Resetta DB dei Nodi", + "factoryResetDevice": "Factory reset dispositivo", + "factoryResetConfig": "Factory reset impostazioni" } }, "debug": { "label": "Debug", "command": { - "reconfigure": "Reconfigure", - "clearAllStoredMessages": "Clear All Stored Message" + "reconfigure": "Riconfigura", + "clearAllStoredMessages": "Cancella Tutti i Messaggi Memorizzati" } } } diff --git a/src/i18n/locales/it-IT/common.json b/src/i18n/locales/it-IT/common.json index 665205de..f8664c86 100644 --- a/src/i18n/locales/it-IT/common.json +++ b/src/i18n/locales/it-IT/common.json @@ -1,36 +1,37 @@ { "button": { "apply": "Applica", - "backupKey": "Backup Key", + "backupKey": "Backup della chiave", "cancel": "Annulla", - "clearMessages": "Clear Messages", + "clearMessages": "Cancella Messaggi", "close": "Chiudi", - "confirm": "Confirm", + "confirm": "Conferma", "delete": "Elimina", - "dismiss": "Dismiss", - "download": "Download", - "export": "Export", - "generate": "Generate", - "regenerate": "Regenerate", + "dismiss": "Annulla", + "download": "Scarica", + "export": "Esporta", + "generate": "Genera", + "regenerate": "Rigenera", "import": "Importa", "message": "Messaggio", - "now": "Now", + "now": "Adesso", "ok": "Ok", - "print": "Print", - "rebootOtaNow": "Reboot to OTA Mode Now", + "print": "Stampa", + "rebootOtaNow": "Riavvia ora in modalità OTA", "remove": "Elimina", - "requestNewKeys": "Request New Keys", - "requestPosition": "Request Position", + "requestNewKeys": "Richiedi Nuove Chiavi", + "requestPosition": "Richiedi posizione", "reset": "Reset", "save": "Salva", "scanQr": "Scansiona codice QR", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", "fullTitle": "Meshtastic Web Client" }, - "loading": "Loading...", + "loading": "Caricamento in corso...", "unit": { "cps": "CPS", "dbm": "dBm", @@ -40,80 +41,101 @@ "plural": "Hops" }, "hopsAway": { - "one": "{{count}} hop away", - "plural": "{{count}} hops away", - "unknown": "Unknown hops away" + "one": "A {{count}} hop di distanza", + "plural": "A {{count}} hop di distanza", + "unknown": "Hop sconosciuti" }, "megahertz": "MHz", - "raw": "raw", + "raw": "grezzo", "meter": { - "one": "Meter", - "plural": "Meters", + "one": "Metro", + "plural": "Metri", "suffix": "m" }, "minute": { - "one": "Minute", - "plural": "Minutes" + "one": "Minuto", + "plural": "Minuti" + }, + "hour": { + "one": "Hour", + "plural": "Hours" }, "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", + "one": "Millisecondo", + "plural": "Millisecondi", "suffix": "ms" }, "second": { - "one": "Second", - "plural": "Seconds" + "one": "Secondo", + "plural": "Secondi" + }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" }, "snr": "SNR", "volt": { "one": "Volt", - "plural": "Volts", + "plural": "Volt", "suffix": "V" }, "record": { - "one": "Records", - "plural": "Records" + "one": "Record", + "plural": "Record" } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { - "longName": "Unknown", - "shortName": "UNK", - "notAvailable": "N/A", + "longName": "Sconosciuto", + "shortName": "SCON", + "notAvailable": "N/D", "num": "??" }, "nodeUnknownPrefix": "!", - "unset": "UNSET", + "unset": "ANNULLA", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { - "string": "Too long, expected less than or equal to {{maximum}} characters.", - "number": "Too big, expected a number smaller than or equal to {{maximum}}.", - "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + "string": "Troppo lungo, atteso minore o uguale a {{maximum}} caratteri.", + "number": "Troppo grande, ci si aspetta un numero minore o uguale a {{maximum}}.", + "bytes": "Troppo grande, atteso inferiore o uguale a {{params.maximum}} byte." }, "tooSmall": { - "string": "Too short, expected more than or equal to {{minimum}} characters.", - "number": "Too small, expected a number larger than or equal to {{minimum}}." + "string": "Troppo breve, atteso più di o uguale a {{minimum}} caratteri.", + "number": "Troppo piccolo, atteso un numero maggiore o uguale a {{minimum}}." }, "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", - "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + "ipv4": "Formato non valido, previsto un indirizzo IPv4.", + "key": "Formato non valido, prevista una chiave pre-condivisa codificata Base64 (PSK)." }, "invalidType": { - "number": "Invalid type, expected a number." + "number": "Tipo non valido, atteso un numero." }, "pskLength": { - "0bit": "Key is required to be empty.", - "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", - "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", - "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + "0bit": "La chiave deve essere vuota.", + "8bit": "La chiave deve essere una chiave pre-condivisa a 8 bit (PSK).", + "128bit": "La chiave deve essere una chiave pre-condivisa a 128 bit (PSK).", + "256bit": "La chiave deve essere una chiave pre-condivisa a 256 bit (PSK)." }, "required": { - "generic": "This field is required.", - "managed": "At least one admin key is requred if the node is managed.", - "key": "Key is required." + "generic": "Questo campo è obbligatorio.", + "managed": "Se il nodo è gestito, è richiesta almeno una chiave amministrativa.", + "key": "La chiave è obbligatoria." } } } diff --git a/src/i18n/locales/it-IT/dashboard.json b/src/i18n/locales/it-IT/dashboard.json index 5b521ab1..c31423a9 100644 --- a/src/i18n/locales/it-IT/dashboard.json +++ b/src/i18n/locales/it-IT/dashboard.json @@ -1,12 +1,12 @@ { "dashboard": { - "title": "Connected Devices", - "description": "Manage your connected Meshtastic devices.", + "title": "Dispositivi Connessi", + "description": "Gestisci i tuoi dispositivi Meshtastic collegati.", "connectionType_ble": "BLE", "connectionType_serial": "Seriale", "connectionType_network": "Rete", - "noDevicesTitle": "No devices connected", - "noDevicesDescription": "Connect a new device to get started.", - "button_newConnection": "New Connection" + "noDevicesTitle": "Nessun dispositivo connesso", + "noDevicesDescription": "Connetti un nuovo dispositivo per iniziare.", + "button_newConnection": "Nuova connessione" } } diff --git a/src/i18n/locales/it-IT/deviceConfig.json b/src/i18n/locales/it-IT/deviceConfig.json index 6ca4ef4d..bd89dd07 100644 --- a/src/i18n/locales/it-IT/deviceConfig.json +++ b/src/i18n/locales/it-IT/deviceConfig.json @@ -1,6 +1,6 @@ { "page": { - "title": "Configuration", + "title": "Configurazione", "tabBluetooth": "Bluetooth", "tabDevice": "Dispositivo", "tabDisplay": "Schermo", @@ -11,150 +11,150 @@ "tabSecurity": "Sicurezza" }, "sidebar": { - "label": "Modules" + "label": "Moduli" }, "device": { - "title": "Device Settings", - "description": "Settings for the device", + "title": "Impostazioni del dispositivo", + "description": "Le impostazioni del dispositivo", "buttonPin": { - "description": "Button pin override", - "label": "Button Pin" + "description": "Sovrascrivi pin pulsante", + "label": "Pulsante Pin" }, "buzzerPin": { - "description": "Buzzer pin override", - "label": "Buzzer Pin" + "description": "Sovrascrivi pin buzzer", + "label": "Pin Buzzer" }, "disableTripleClick": { - "description": "Disable triple click", - "label": "Disable Triple Click" + "description": "Disabilita triplo-click", + "label": "Disabilita triplo-click" }, "doubleTapAsButtonPress": { - "description": "Treat double tap as button press", - "label": "Double Tap as Button Press" + "description": "Tratta il doppio tocco come pressione pulsante", + "label": "Doppio tocco come pressione pulsante" }, "ledHeartbeatDisabled": { - "description": "Disable default blinking LED", - "label": "LED Heartbeat Disabled" + "description": "Disabilita il LED lampeggiante predefinito", + "label": "LED Heartbeat Disabilitato" }, "nodeInfoBroadcastInterval": { - "description": "How often to broadcast node info", - "label": "Node Info Broadcast Interval" + "description": "Quante volte trasmettere informazioni sul nodo", + "label": "Intervallo Di Trasmissione Info Nodo" }, "posixTimezone": { - "description": "The POSIX timezone string for the device", + "description": "La stringa di fuso orario POSIX per il dispositivo", "label": "POSIX Timezone" }, "rebroadcastMode": { - "description": "How to handle rebroadcasting", - "label": "Rebroadcast Mode" + "description": "Come gestire il rebroadcasting", + "label": "Modalità Rebroadcast" }, "role": { - "description": "What role the device performs on the mesh", + "description": "Quale ruolo il dispositivo svolge sulla mesh", "label": "Ruolo" } }, "bluetooth": { - "title": "Bluetooth Settings", - "description": "Settings for the Bluetooth module", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "title": "Impostazioni Bluetooth", + "description": "Impostazioni per il modulo Bluetooth", + "note": "Nota: alcuni dispositivi (ESP32) non possono utilizzare contemporaneamente Bluetooth e WiFi.", "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" + "description": "Abilita o disabilita Bluetooth", + "label": "Abilitato" }, "pairingMode": { - "description": "Pin selection behaviour.", + "description": "Comportamento di selezione pin.", "label": "Modalità abbinamento" }, "pin": { - "description": "Pin to use when pairing", + "description": "Pin da usare durante l'abbinamento", "label": "Pin" } }, "display": { - "description": "Settings for the device display", - "title": "Display Settings", + "description": "Impostazioni per il display del dispositivo", + "title": "Impostazioni Display", "headingBold": { - "description": "Bolden the heading text", - "label": "Bold Heading" + "description": "Metti in grassetto il testo dell'intestazione", + "label": "Intestazione in grassetto" }, "carouselDelay": { - "description": "How fast to cycle through windows", - "label": "Carousel Delay" + "description": "Quanto velocemente scorrere attraverso le finestre", + "label": "Ritardo Carosello" }, "compassNorthTop": { - "description": "Fix north to the top of compass", - "label": "Compass North Top" + "description": "Fissare il nord fino alla parte superiore della bussola", + "label": "Bussola Nord In Alto" }, "displayMode": { - "description": "Screen layout variant", - "label": "Display Mode" + "description": "Variante layout schermo", + "label": "Modalità di visualizzazione" }, "displayUnits": { - "description": "Display metric or imperial units", - "label": "Display Units" + "description": "Mostra unità metriche o imperiali", + "label": "Mostra Unità" }, "flipScreen": { - "description": "Flip display 180 degrees", - "label": "Flip Screen" + "description": "Rifletti la visualizzazione di 180 gradi", + "label": "Capovolgi schermo" }, "gpsDisplayUnits": { - "description": "Coordinate display format", - "label": "GPS Display Units" + "description": "Formato coordinate", + "label": "Unità Display GPS" }, "oledType": { - "description": "Type of OLED screen attached to the device", - "label": "OLED Type" + "description": "Tipo di schermo OLED collegato al dispositivo", + "label": "Tipo OLED" }, "screenTimeout": { - "description": "Turn off the display after this long", - "label": "Screen Timeout" + "description": "Spegni lo schermo dopo questo lungo periodo", + "label": "Timeout Schermo" }, "twelveHourClock": { - "description": "Use 12-hour clock format", - "label": "12-Hour Clock" + "description": "Usa formato orologio 12 ore", + "label": "Orologio 12 Ore" }, "wakeOnTapOrMotion": { - "description": "Wake the device on tap or motion", - "label": "Wake on Tap or Motion" + "description": "Risveglia il dispositivo al tocco o al movimento", + "label": "Sveglia al tocco o al movimento" } }, "lora": { - "title": "Mesh Settings", - "description": "Settings for the LoRa mesh", + "title": "Impostazioni Mesh", + "description": "Impostazioni per la mesh LoRa", "bandwidth": { - "description": "Channel bandwidth in MHz", + "description": "Larghezza di banda del canale in MHz", "label": "Larghezza di banda" }, "boostedRxGain": { - "description": "Boosted RX gain", - "label": "Boosted RX Gain" + "description": "Guadagno RX potenziato", + "label": "Guadagno RX potenziato" }, "codingRate": { - "description": "The denominator of the coding rate", - "label": "Coding Rate" + "description": "Il denominatore della velocità di codifica", + "label": "Velocità di codifica" }, "frequencyOffset": { - "description": "Frequency offset to correct for crystal calibration errors", - "label": "Frequency Offset" + "description": "Offset di frequenza per correggere gli errori di calibrazione del cristallo", + "label": "Offset Di Frequenza" }, "frequencySlot": { - "description": "LoRa frequency channel number", - "label": "Frequency Slot" + "description": "Numero canale di frequenza LoRa", + "label": "Slot di frequenza" }, "hopLimit": { - "description": "Maximum number of hops", - "label": "Hop Limit" + "description": "Numero massimo di hop", + "label": "Limite di hop" }, "ignoreMqtt": { - "description": "Don't forward MQTT messages over the mesh", + "description": "Non inoltrare i messaggi MQTT sulla mesh", "label": "Ignora MQTT" }, "modemPreset": { - "description": "Modem preset to use", + "description": "Preimpostazione modem da usare", "label": "Configurazione Modem" }, "okToMqtt": { - "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "description": "Quando impostato su true, questa configurazione indica che l'utente approva il caricamento del pacchetto su MQTT. Se impostato su false, ai nodi remoti viene richiesto di non inoltrare i pacchetti a MQTT", "label": "OK per MQTT" }, "overrideDutyCycle": { @@ -162,267 +162,267 @@ "label": "Ignora limite di Duty Cycle" }, "overrideFrequency": { - "description": "Override frequency", - "label": "Override Frequency" + "description": "Sovrascrivi frequenza", + "label": "Sovrascrivi frequenza" }, "region": { - "description": "Sets the region for your node", + "description": "Imposta la regione del tuo nodo", "label": "Regione" }, "spreadingFactor": { - "description": "Indicates the number of chirps per symbol", + "description": "Indica il numero di chirp per simbolo", "label": "Spreading Factor" }, "transmitEnabled": { - "description": "Enable/Disable transmit (TX) from the LoRa radio", - "label": "Transmit Enabled" + "description": "Abilita/Disabilita la trasmissione (TX) dalla radio LoRa", + "label": "Trasmissione Abilitata" }, "transmitPower": { - "description": "Max transmit power", - "label": "Transmit Power" + "description": "Potenza massima di trasmissione", + "label": "Potenza Di Trasmissione" }, "usePreset": { - "description": "Use one of the predefined modem presets", - "label": "Use Preset" + "description": "Usa una delle preimpostazioni predefinite del modem", + "label": "Utilizza il preset" }, "meshSettings": { - "description": "Settings for the LoRa mesh", - "label": "Mesh Settings" + "description": "Impostazioni per la mesh LoRa", + "label": "Impostazioni Mesh" }, "waveformSettings": { - "description": "Settings for the LoRa waveform", - "label": "Waveform Settings" + "description": "Impostazioni per la forma d'onda LoRa", + "label": "Impostazioni Forma d'onda" }, "radioSettings": { - "label": "Radio Settings", - "description": "Settings for the LoRa radio" + "label": "Impostazioni Radio", + "description": "Impostazioni per la radio LoRa" } }, "network": { - "title": "WiFi Config", - "description": "WiFi radio configuration", - "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "title": "Configurazione WiFi", + "description": "Configurazione radio WiFi", + "note": "Nota: alcuni dispositivi (ESP32) non possono utilizzare contemporaneamente Bluetooth e WiFi.", "addressMode": { - "description": "Address assignment selection", - "label": "Address Mode" + "description": "Selezione assegnazione indirizzo", + "label": "Modalità Indirizzo" }, "dns": { - "description": "DNS Server", + "description": "Server DNS", "label": "DNS" }, "ethernetEnabled": { - "description": "Enable or disable the Ethernet port", - "label": "Enabled" + "description": "Abilita o disabilita la porta Ethernet", + "label": "Abilitato" }, "gateway": { - "description": "Default Gateway", + "description": "Gateway predefinito", "label": "Gateway" }, "ip": { - "description": "IP Address", + "description": "Indirizzo IP", "label": "IP" }, "psk": { - "description": "Network password", + "description": "Password di rete", "label": "PSK" }, "ssid": { - "description": "Network name", + "description": "Nome rete", "label": "SSID" }, "subnet": { - "description": "Subnet Mask", + "description": "Subnet mask", "label": "Subnet" }, "wifiEnabled": { - "description": "Enable or disable the WiFi radio", - "label": "Enabled" + "description": "Abilita o disabilita la radio WiFi", + "label": "Abilitato" }, "meshViaUdp": { "label": "Mesh via UDP" }, "ntpServer": { - "label": "NTP Server" + "label": "Server NTP" }, "rsyslogServer": { - "label": "Rsyslog Server" + "label": "Server rsyslog" }, "ethernetConfigSettings": { - "description": "Ethernet port configuration", - "label": "Ethernet Config" + "description": "Configurazione porta Ethernet", + "label": "Configurazione Ethernet" }, "ipConfigSettings": { - "description": "IP configuration", - "label": "IP Config" + "description": "Configurazione IP", + "label": "Configurazione IP" }, "ntpConfigSettings": { - "description": "NTP configuration", - "label": "NTP Config" + "description": "Configurazione NTP", + "label": "Configurazione NTP" }, "rsyslogConfigSettings": { - "description": "Rsyslog configuration", - "label": "Rsyslog Config" + "description": "Configurazione di Rsyslog", + "label": "Configurazione di Rsyslog" }, "udpConfigSettings": { - "description": "UDP over Mesh configuration", + "description": "Configurazione UDP over Mesh", "label": "Configurazione UDP" } }, "position": { - "title": "Position Settings", - "description": "Settings for the position module", + "title": "Impostazioni Posizione", + "description": "Impostazioni per il modulo di posizione", "broadcastInterval": { - "description": "How often your position is sent out over the mesh", - "label": "Broadcast Interval" + "description": "Quante volte la tua posizione viene inviata attraverso la mesh", + "label": "Intervallo Di Trasmissione" }, "enablePin": { - "description": "GPS module enable pin override", - "label": "Enable Pin" + "description": "Modulo GPS abilita pin override", + "label": "Abilita Pin" }, "fixedPosition": { - "description": "Don't report GPS position, but a manually-specified one", - "label": "Fixed Position" + "description": "Non segnalare la posizione GPS, ma specificane una manualmente", + "label": "Posizione Fissa" }, "gpsMode": { - "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", - "label": "GPS Mode" + "description": "Configura se il GPS del dispositivo è abilitato, disabilitato o non presente", + "label": "Modalità GPS" }, "gpsUpdateInterval": { - "description": "How often a GPS fix should be acquired", - "label": "GPS Update Interval" + "description": "Quante volte una correzione GPS dovrebbe essere acquisita", + "label": "Intervallo di aggiornamento GPS" }, "positionFlags": { - "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", - "label": "Position Flags" + "description": "Campi opzionali da includere quando si assemblano messaggi di posizione. Più i campi sono selezionati, più grande sarà il messaggio porterà a un utilizzo più lungo del tempo di volo e un rischio più elevato di perdite dei pacchetti.", + "label": "Flag Di Posizione" }, "receivePin": { - "description": "GPS module RX pin override", - "label": "Receive Pin" + "description": "Sovrascrivi RX pin del Modulo GPS", + "label": "Pin di ricezione" }, "smartPositionEnabled": { - "description": "Only send position when there has been a meaningful change in location", - "label": "Enable Smart Position" + "description": "Invia posizione solo quando c'è stato un cambiamento significativo nella posizione", + "label": "Abilita Posizione Intelligente" }, "smartPositionMinDistance": { - "description": "Minimum distance (in meters) that must be traveled before a position update is sent", - "label": "Smart Position Minimum Distance" + "description": "Distanza minima (in metri) che deve essere percorsa prima di inviare un aggiornamento di posizione", + "label": "Distanza Minima Posizione Intelligente" }, "smartPositionMinInterval": { - "description": "Minimum interval (in seconds) that must pass before a position update is sent", - "label": "Smart Position Minimum Interval" + "description": "Intervallo minimo (in secondi) che deve passare prima di inviare un aggiornamento della posizione", + "label": "Intervallo Minimo Posizione Intelligente" }, "transmitPin": { - "description": "GPS module TX pin override", - "label": "Transmit Pin" + "description": "Sovrascrivi TX pin del Modulo GPS", + "label": "Pin di trasmissione" }, "intervalsSettings": { - "description": "How often to send position updates", - "label": "Intervals" + "description": "Quante volte inviare aggiornamenti di posizione", + "label": "Intervalli" }, "flags": { - "placeholder": "Select position flags...", - "altitude": "Altitude", - "altitudeGeoidalSeparation": "Altitude Geoidal Separation", - "altitudeMsl": "Altitude is Mean Sea Level", - "dop": "Dilution of precision (DOP) PDOP used by default", - "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", - "numSatellites": "Number of satellites", - "sequenceNumber": "Sequence number", + "placeholder": "Seleziona flag di posizione...", + "altitude": "Altitudine", + "altitudeGeoidalSeparation": "Altitudine Separazione Geoidale", + "altitudeMsl": "L'altitudine è riferita al livello medio del mare", + "dop": "Diluizione del PDOP di precisione (DOP) utilizzato per impostazione predefinita", + "hdopVdop": "Se DOP è impostato, usa i valori HDOP / VDOP invece di PDOP", + "numSatellites": "Numero di satelliti", + "sequenceNumber": "Numero sequenza", "timestamp": "Data e ora", "unset": "Non impostato", - "vehicleHeading": "Vehicle heading", - "vehicleSpeed": "Vehicle speed" + "vehicleHeading": "Direzione del veicolo", + "vehicleSpeed": "Velocità del veicolo" } }, "power": { "adcMultiplierOverride": { - "description": "Used for tweaking battery voltage reading", - "label": "ADC Multiplier Override ratio" + "description": "Utilizzato per modificare la lettura della tensione della batteria", + "label": "Sovrascrivi rapporto moltiplicatore ADC" }, "ina219Address": { - "description": "Address of the INA219 battery monitor", - "label": "INA219 Address" + "description": "Indirizzo del monitor batteria INA219", + "label": "Indirizzo INA219" }, "lightSleepDuration": { - "description": "How long the device will be in light sleep for", - "label": "Light Sleep Duration" + "description": "Per quanto tempo il dispositivo sarà in light sleep", + "label": "Durata light sleep" }, "minimumWakeTime": { - "description": "Minimum amount of time the device will stay awake for after receiving a packet", - "label": "Minimum Wake Time" + "description": "Quantità minima di tempo che il dispositivo rimarrà attivo per dopo aver ricevuto un pacchetto", + "label": "Tempo Di Risveglio Minimo" }, "noConnectionBluetoothDisabled": { - "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", - "label": "No Connection Bluetooth Disabled" + "description": "Se il dispositivo non riceve una connessione Bluetooth, la radio BLE sarà disattivata dopo questo lungo periodo", + "label": "Nessuna Connessione Bluetooth Disabilitata" }, "powerSavingEnabled": { - "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "description": "Selezionare se alimentato da una fonte a bassa corrente (cioè solare) per minimizzare il consumo energetico il più possibile.", "label": "Abilita modalità risparmio energetico" }, "shutdownOnBatteryDelay": { - "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", - "label": "Shutdown on battery delay" + "description": "Spegnimento automatico del nodo dopo questo lungo quando la batteria, 0 per indefinito", + "label": "Arresto in ritardo della batteria" }, "superDeepSleepDuration": { - "description": "How long the device will be in super deep sleep for", - "label": "Super Deep Sleep Duration" + "description": "Per quanto tempo il dispositivo sarà in deep sleep", + "label": "Durata Super Deep Sleep" }, "powerConfigSettings": { - "description": "Settings for the power module", + "description": "Impostazioni per il modulo di alimentazione", "label": "Configurazione Alimentazione" }, "sleepSettings": { - "description": "Sleep settings for the power module", - "label": "Sleep Settings" + "description": "Impostazioni di sospensione per il modulo di alimentazione", + "label": "Impostazioni Sleep" } }, "security": { - "description": "Settings for the Security configuration", - "title": "Security Settings", - "button_backupKey": "Backup Key", + "description": "Impostazioni per la configurazione di sicurezza", + "title": "Impostazioni di Sicurezza", + "button_backupKey": "Chiave Di Backup", "adminChannelEnabled": { - "description": "Allow incoming device control over the insecure legacy admin channel", - "label": "Allow Legacy Admin" + "description": "Consenti il controllo del dispositivo in arrivo sul canale di amministrazione ereditato insicuro", + "label": "Consenti Amministrazione Legacy" }, "enableDebugLogApi": { - "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", - "label": "Enable Debug Log API" + "description": "Output live debug logging su seriale, visualizza ed esporta i log di posizione dei dispositivi redatti su Bluetooth", + "label": "Abilita Debug Log API" }, "managed": { - "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", - "label": "Managed" + "description": "Se abilitata, le opzioni di configurazione del dispositivo possono essere modificate solo in remoto da un nodo di amministrazione remota tramite messaggi amministratori. Non abilitare questa opzione a meno che non sia stato configurato almeno un nodo Admin Remoto adatto, e la chiave pubblica è memorizzata in uno dei campi precedenti.", + "label": "Gestito" }, "privateKey": { - "description": "Used to create a shared key with a remote device", + "description": "Usato per creare una chiave condivisa con un dispositivo remoto", "label": "Chiave Privata" }, "publicKey": { - "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "description": "Inviato ad altri nodi sulla mesh per consentire loro di calcolare una chiave segreta condivisa", "label": "Chiave Pubblica" }, "primaryAdminKey": { - "description": "The primary public key authorized to send admin messages to this node", - "label": "Primary Admin Key" + "description": "La chiave pubblica primaria autorizzata a inviare messaggi di amministrazione a questo nodo", + "label": "Chiave Primaria Dell'Amministratore" }, "secondaryAdminKey": { - "description": "The secondary public key authorized to send admin messages to this node", - "label": "Secondary Admin Key" + "description": "La chiave pubblica secondaria autorizzata a inviare messaggi di amministrazione a questo nodo", + "label": "Chiave Secondaria Dell'Amministratore" }, "serialOutputEnabled": { - "description": "Serial Console over the Stream API", - "label": "Serial Output Enabled" + "description": "Console seriale attraverso la Stream API", + "label": "Output Seriale Abilitato" }, "tertiaryAdminKey": { - "description": "The tertiary public key authorized to send admin messages to this node", - "label": "Tertiary Admin Key" + "description": "La chiave pubblica terziaria autorizzata a inviare messaggi di amministrazione a questo nodo", + "label": "Chiave Di Amministrazione Terziaria" }, "adminSettings": { - "description": "Settings for Admin", - "label": "Admin Settings" + "description": "Impostazioni per Amministratore", + "label": "Impostazioni Amministratore" }, "loggingSettings": { - "description": "Settings for Logging", - "label": "Logging Settings" + "description": "Impostazioni per il logging", + "label": "Impostazioni Di Logging" } } } diff --git a/src/i18n/locales/it-IT/dialog.json b/src/i18n/locales/it-IT/dialog.json index 6c0197a4..402b6838 100644 --- a/src/i18n/locales/it-IT/dialog.json +++ b/src/i18n/locales/it-IT/dialog.json @@ -1,159 +1,171 @@ { "deleteMessages": { - "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" + "description": "Questa azione cancellerà tutta la cronologia dei messaggi. Non può essere annullata. Sei sicuro di voler continuare?", + "title": "Cancella Tutti I Messaggi" }, "deviceName": { - "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" + "description": "Il dispositivo verrà riavviato una volta salvata la configurazione.", + "longName": "Nome Lungo", + "shortName": "Nome Breve", + "title": "Cambia Nome Dispositivo" }, "import": { - "description": "The current LoRa configuration will be overridden.", + "description": "La configurazione attuale di LoRa sarà sovrascritta.", "error": { - "invalidUrl": "Invalid Meshtastic URL" + "invalidUrl": "URL Meshtastic non valido" }, - "channelPrefix": "Channel: ", - "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", - "usePreset": "Use Preset?", - "title": "Import Channel Set" + "channelPrefix": "Canale: ", + "channelSetUrl": "URL del Set di Canali/Codice QR", + "channels": "Canali:", + "usePreset": "Utilizza il preset?", + "title": "Importa Set Canale" }, "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" + "altitude": "Altitudine: ", + "coordinates": "Coordinate: ", + "title": "Posizione: {{identifier}}" }, "pkiRegenerateDialog": { - "title": "Regenerate Pre-Shared Key?", - "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" + "title": "Rigenerare La Chiave Pre-Condivisa?", + "description": "Sei sicuro di voler rigenerare la chiave pre-condivisa?", + "regenerate": "Rigenera" }, "newDeviceDialog": { - "title": "Connect New Device", + "title": "Connetti Nuovo Dispositivo", "https": "https", "http": "http", "tabHttp": "HTTP", "tabBluetooth": "Bluetooth", "tabSerial": "Seriale", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", - "connect": "Connect", + "useHttps": "Usa HTTPS", + "connecting": "Connessione in corso...", + "connect": "Connetti", "connectionFailedAlert": { - "title": "Connection Failed", - "descriptionPrefix": "Could not connect to the device. ", - "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", - "openLinkPrefix": "Please open ", - "openLinkSuffix": " in a new tab", - "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", - "learnMoreLink": "Learn more" + "title": "Connessione fallita", + "descriptionPrefix": "Impossibile connettersi al dispositivo.", + "httpsHint": "Se si utilizza HTTPS, potrebbe essere necessario prima accettare un certificato autofirmato. ", + "openLinkPrefix": "Apri per favore ", + "openLinkSuffix": " in una nuova scheda", + "acceptTlsWarningSuffix": ", accetta eventuali avvisi TLS se richiesto, quindi riprova", + "learnMoreLink": "Maggiori informazioni" }, "httpConnection": { - "label": "IP Address/Hostname", + "label": "Indirizzo IP/Hostname", "placeholder": "000.000.000.000 / meshtastic.local" }, "serialConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device", + "noDevicesPaired": "Nessun dispositivo ancora abbinato.", + "newDeviceButton": "Nuovo dispositivo", "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" }, "bluetoothConnection": { - "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" + "noDevicesPaired": "Nessun dispositivo ancora abbinato.", + "newDeviceButton": "Nuovo dispositivo" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", - "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", - "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "Questa applicazione richiede un <0>contesto sicuro. Si prega di connettersi utilizzando HTTPS o localhost.", + "additionallyRequiresSecureContext": "Inoltre, richiede un <0>contesto sicuro. Si prega di connettersi utilizzando HTTPS o localhost." } }, "nodeDetails": { "message": "Messaggio", - "requestPosition": "Request Position", + "requestPosition": "Richiedi posizione", "traceRoute": "Trace Route", - "airTxUtilization": "Air TX utilization", - "allRawMetrics": "All Raw Metrics:", - "batteryLevel": "Battery level", - "channelUtilization": "Channel utilization", - "details": "Details:", - "deviceMetrics": "Device Metrics:", + "airTxUtilization": "Tempo di Trasmissione Utilizzato", + "allRawMetrics": "Tutte Le Metriche Grezze:", + "batteryLevel": "Livello batteria", + "channelUtilization": "Utilizzo Canale", + "details": "Dettagli:", + "deviceMetrics": "Metriche Dispositivo:", "hardware": "Hardware: ", - "lastHeard": "Last Heard: ", - "nodeHexPrefix": "Node Hex: !", - "nodeNumber": "Node Number: ", - "position": "Position:", - "role": "Role: ", - "uptime": "Uptime: ", + "lastHeard": "Ultimo Contatto: ", + "nodeHexPrefix": "Nodo Hex: !", + "nodeNumber": "Numero Nodo: ", + "position": "Posizione:", + "role": "Ruolo: ", + "uptime": "Tempo di attività: ", "voltage": "Tensione", - "title": "Node Details for {{identifier}}", - "ignoreNode": "Ignore node", - "removeNode": "Remove node", - "unignoreNode": "Unignore node" + "title": "Dettagli nodo per {{identifier}}", + "ignoreNode": "Ignora nodo", + "removeNode": "Rimuovi Nodo", + "unignoreNode": "Non ignorare più nodo" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", - "loseKeysWarning": "If you lose your keys, you will need to reset your device.", - "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "loseKeysWarning": "Se perdi le tue chiavi, dovrai reimpostare il tuo dispositivo.", + "secureBackup": "È importante eseguire il backup delle chiavi pubbliche e private e memorizzare il backup in modo sicuro!", "footer": "=== END OF KEYS ===", "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", - "privateKey": "Private Key:", - "publicKey": "Public Key:", + "privateKey": "Chiave Privata:", + "publicKey": "Chiave Pubblica:", "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", - "title": "Backup Keys" + "title": "Backup chiavi" + }, + "pkiBackupReminder": { + "description": "Ti consigliamo di eseguire regolarmente il backup delle tue chiavi. Vuoi eseguire un backup?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" }, "pkiRegenerate": { - "description": "Are you sure you want to regenerate key pair?", - "title": "Regenerate Key Pair" + "description": "Sei sicuro di voler rigenerare la coppia di chiavi?", + "title": "Rigenera Coppia Chiavi" }, "qr": { - "addChannels": "Add Channels", - "replaceChannels": "Replace Channels", - "description": "The current LoRa configuration will also be shared.", - "sharableUrl": "Sharable URL", - "title": "Generate QR Code" + "addChannels": "Aggiungi canali", + "replaceChannels": "Sostituisci Canali", + "description": "Anche l'attuale configurazione di LoRa verrà condivisa.", + "sharableUrl": "URL Condivisibile", + "title": "Genera codice QR" }, "rebootOta": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", - "scheduled": "Reboot has been scheduled" + "title": "Pianifica Riavvio", + "description": "Riavvia il nodo connesso dopo un ritardo in modalità OTA (Over-the-Air).", + "enterDelay": "Inserisci ritardo (sec)", + "scheduled": "Il riavvio è stato pianificato" }, "reboot": { - "title": "Schedule Reboot", - "description": "Reboot the connected node after x minutes." + "title": "Pianifica Riavvio", + "description": "Riavvia il nodo connesso dopo x minuti." }, "refreshKeys": { "description": { - "acceptNewKeys": "This will remove the node from device and request new keys.", - "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", - "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + "acceptNewKeys": "Questo rimuoverà il nodo dal dispositivo e richiederà nuove chiavi.", + "keyMismatchReasonSuffix": ". Ciò è dovuto alla chiave pubblica corrente del nodo remoto che non corrisponde alla chiave precedentemente memorizzata per questo nodo.", + "unableToSendDmPrefix": "Il nodo non è in grado di inviare un messaggio diretto al nodo: " }, - "acceptNewKeys": "Accept New Keys", - "title": "Keys Mismatch - {{identifier}}" + "acceptNewKeys": "Accetta Nuove Chiavi", + "title": "Chiavi Non Corrispondenti - {{identifier}}" }, "removeNode": { - "description": "Are you sure you want to remove this Node?", - "title": "Remove Node?" + "description": "Sei sicuro di voler rimuovere questo nodo?", + "title": "Rimuovi Nodo?" }, "shutdown": { - "title": "Schedule Shutdown", - "description": "Turn off the connected node after x minutes." + "title": "Pianifica Spegnimento", + "description": "Spegni il nodo connesso dopo x minuti." }, "traceRoute": { - "routeToDestination": "Route to destination:", - "routeBack": "Route back:" + "routeToDestination": "Percorso di destinazione:", + "routeBack": "Percorso indietro:" }, "tracerouteResponse": { "title": "Traceroute: {{identifier}}" }, "unsafeRoles": { - "confirmUnderstanding": "Yes, I know what I'm doing", - "conjunction": " and the blog post about ", - "postamble": " and understand the implications of changing the role.", - "preamble": "I have read the ", - "choosingRightDeviceRole": "Choosing The Right Device Role", - "deviceRoleDocumentation": "Device Role Documentation", + "confirmUnderstanding": "Sì, so cosa sto facendo", + "conjunction": " e il blog post su ", + "postamble": " e capisco le implicazioni di un cambiamento di ruolo.", + "preamble": "Dichiaro di aver letto i ", + "choosingRightDeviceRole": "Scegliere il ruolo corretto del dispositivo", + "deviceRoleDocumentation": "Documentazione sul ruolo del dispositivo", "title": "Sei sicuro?" + }, + "managedMode": { + "confirmUnderstanding": "Sì, so cosa sto facendo", + "title": "Sei sicuro?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/it-IT/messages.json b/src/i18n/locales/it-IT/messages.json index 2f2dca24..7a8cd6bd 100644 --- a/src/i18n/locales/it-IT/messages.json +++ b/src/i18n/locales/it-IT/messages.json @@ -1,40 +1,39 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messaggi: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." + "title": "Seleziona una chat", + "text": "Ancora nessun messaggio." }, "selectChatPrompt": { - "text": "Select a channel or node to start messaging." + "text": "Selezionare un canale o un nodo per iniziare a messaggiare." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Invia" }, "actionsMenu": { - "addReactionLabel": "Add Reaction", + "addReactionLabel": "Aggiungi una Reazione", "replyLabel": "Rispondi" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Messaggio inviato", + "displayText": "Messaggio inviato" + }, + "failed": { + "label": "Invio messaggio non riuscito", + "displayText": "Invio fallito" + }, + "unknown": { + "label": "Stato messaggio sconosciuto", + "displayText": "Stato sconosciuto" + }, + "waiting": { + "label": "Inviando il messaggio...", + "displayText": "In attesa della consegna" } } } diff --git a/src/i18n/locales/it-IT/moduleConfig.json b/src/i18n/locales/it-IT/moduleConfig.json index 544512d5..c868c00b 100644 --- a/src/i18n/locales/it-IT/moduleConfig.json +++ b/src/i18n/locales/it-IT/moduleConfig.json @@ -2,163 +2,163 @@ "page": { "tabAmbientLighting": "Luce Ambientale", "tabAudio": "Audio", - "tabCannedMessage": "Canned", + "tabCannedMessage": "Predefiniti", "tabDetectionSensor": "Sensore Di Rilevamento", - "tabExternalNotification": "Ext Notif", + "tabExternalNotification": "Notifica Esterna", "tabMqtt": "MQTT", "tabNeighborInfo": "Informazioni Vicinato", "tabPaxcounter": "Paxcounter", "tabRangeTest": "Test Distanza", "tabSerial": "Seriale", - "tabStoreAndForward": "S&F", + "tabStoreAndForward": "S&I", "tabTelemetry": "Telemetria" }, "ambientLighting": { - "title": "Ambient Lighting Settings", - "description": "Settings for the Ambient Lighting module", + "title": "Configurazione Illuminazione Ambientale", + "description": "Impostazioni per il modulo Illuminazione Ambientale", "ledState": { - "label": "LED State", - "description": "Sets LED to on or off" + "label": "Stato LED", + "description": "Imposta LED su acceso o spento" }, "current": { "label": "Attuale", - "description": "Sets the current for the LED output. Default is 10" + "description": "Imposta la corrente per l'uscita LED. Il valore predefinito è 10" }, "red": { "label": "Rosso", - "description": "Sets the red LED level. Values are 0-255" + "description": "Imposta il livello rosso del LED. I valori sono 0-255" }, "green": { "label": "Verde", - "description": "Sets the green LED level. Values are 0-255" + "description": "Imposta il livello verde del LED. I valori sono 0-255" }, "blue": { "label": "Blu", - "description": "Sets the blue LED level. Values are 0-255" + "description": "Imposta il livello blu del LED. I valori sono 0-255" } }, "audio": { - "title": "Audio Settings", - "description": "Settings for the Audio module", + "title": "Impostazioni audio", + "description": "Impostazioni per il modulo audio", "codec2Enabled": { - "label": "Codec 2 Enabled", - "description": "Enable Codec 2 audio encoding" + "label": "Codec 2 Abilitato", + "description": "Abilita la codifica audio Codec 2" }, "pttPin": { - "label": "PTT Pin", - "description": "GPIO pin to use for PTT" + "label": "Pin PTT", + "description": "GPIO pin da utilizzare per PTT" }, "bitrate": { "label": "Bitrate", - "description": "Bitrate to use for audio encoding" + "description": "Bitrate da usare per la codifica audio" }, "i2sWs": { "label": "i2S WS", - "description": "GPIO pin to use for i2S WS" + "description": "GPIO pin da usare per i2S WS" }, "i2sSd": { "label": "i2S SD", - "description": "GPIO pin to use for i2S SD" + "description": "GPIO pin da usare per i2S SD" }, "i2sDin": { "label": "i2S DIN", - "description": "GPIO pin to use for i2S DIN" + "description": "GPIO pin da usare per i2S DIN" }, "i2sSck": { "label": "i2S SCK", - "description": "GPIO pin to use for i2S SCK" + "description": "GPIO pin da usare per i2S SCK" } }, "cannedMessage": { - "title": "Canned Message Settings", - "description": "Settings for the Canned Message module", + "title": "Impostazioni Messaggi Predefiniti", + "description": "Impostazioni per i Messaggi Predefiniti", "moduleEnabled": { - "label": "Module Enabled", - "description": "Enable Canned Message" + "label": "Modulo abilitato", + "description": "Abilita Messaggi Predefiniti" }, "rotary1Enabled": { - "label": "Rotary Encoder #1 Enabled", - "description": "Enable the rotary encoder" + "label": "Encoder Rotativo #1 Abilitato", + "description": "Abilita l'encoder rotativo" }, "inputbrokerPinA": { "label": "Encoder Pin A", - "description": "GPIO Pin Value (1-39) For encoder port A" + "description": "Valore Pin GPIO (1-39) Per porta encoder A" }, "inputbrokerPinB": { "label": "Encoder Pin B", - "description": "GPIO Pin Value (1-39) For encoder port B" + "description": "Valore Pin GPIO (1-39) Per porta encoder B" }, "inputbrokerPinPress": { - "label": "Encoder Pin Press", - "description": "GPIO Pin Value (1-39) For encoder Press" + "label": "Pin Pressione Encoder", + "description": "Valore Pin GPIO (1-39) Per la pressione dell'encoder" }, "inputbrokerEventCw": { - "label": "Clockwise event", - "description": "Select input event." + "label": "Evento in senso orario", + "description": "Seleziona evento in ingresso." }, "inputbrokerEventCcw": { - "label": "Counter Clockwise event", - "description": "Select input event." + "label": "Evento in senso antiorario", + "description": "Seleziona evento in ingresso." }, "inputbrokerEventPress": { - "label": "Press event", - "description": "Select input event" + "label": "Evento pressione", + "description": "Seleziona evento in ingresso" }, "updown1Enabled": { - "label": "Up Down enabled", - "description": "Enable the up / down encoder" + "label": "Su Giù abilitato", + "description": "Abilita l'encoder su / giù" }, "allowInputSource": { - "label": "Allow Input Source", - "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + "label": "Consenti sorgente di input", + "description": "Seleziona da: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" }, "sendBell": { - "label": "Send Bell", - "description": "Sends a bell character with each message" + "label": "Invia Campanella", + "description": "Invia un carattere campanella con ogni messaggio" } }, "detectionSensor": { - "title": "Detection Sensor Settings", - "description": "Settings for the Detection Sensor module", + "title": "Configurazione Sensore Rilevamento", + "description": "Impostazioni per il modulo sensore di rilevamento", "enabled": { - "label": "Enabled", - "description": "Enable or disable Detection Sensor Module" + "label": "Abilitato", + "description": "Abilita o disabilita il modulo del sensore di rilevamento" }, "minimumBroadcastSecs": { - "label": "Minimum Broadcast Seconds", - "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + "label": "Secondi Di Trasmissione Minimi", + "description": "L'intervallo in secondi di quanto spesso possiamo inviare un messaggio alla mesh quando viene rilevato un cambiamento di stato" }, "stateBroadcastSecs": { - "label": "State Broadcast Seconds", - "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + "label": "Secondi Trasmissione di Stato", + "description": "L'intervallo in secondi di quanto spesso dovremmo inviare un messaggio alla mesh con lo stato attuale indipendentemente dai cambiamenti" }, "sendBell": { - "label": "Send Bell", - "description": "Send ASCII bell with alert message" + "label": "Invia Campanella", + "description": "Invia campanella ASCII con messaggio di avviso" }, "name": { - "label": "Friendly Name", - "description": "Used to format the message sent to mesh, max 20 Characters" + "label": "Nome Descrittivo", + "description": "Usato per formattare il messaggio inviato a mesh, max 20 Caratteri" }, "monitorPin": { - "label": "Monitor Pin", - "description": "The GPIO pin to monitor for state changes" + "label": "Pin Monitor", + "description": "Il pin GPIO da monitorare per i cambiamenti di stato" }, "detectionTriggerType": { - "label": "Detection Triggered Type", - "description": "The type of trigger event to be used" + "label": "Tipo di trigger di rilevamento", + "description": "Il tipo di evento di trigger da usare" }, "usePullup": { - "label": "Use Pullup", - "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + "label": "Usa Pullup", + "description": "Indica se usare o meno la modalità INPUT_PULLUP per il pin GPIO" } }, "externalNotification": { - "title": "External Notification Settings", - "description": "Configure the external notification module", + "title": "Configurazione Notifiche Esterne", + "description": "Configura il modulo notifiche esterno", "enabled": { - "label": "Module Enabled", - "description": "Enable External Notification" + "label": "Modulo abilitato", + "description": "Abilita Notifiche Esterne" }, "outputMs": { "label": "Output MS", @@ -169,243 +169,243 @@ "description": "Output" }, "outputVibra": { - "label": "Output Vibrate", - "description": "Output Vibrate" + "label": "Vibrazione Output", + "description": "Vibrazione Output" }, "outputBuzzer": { - "label": "Output Buzzer", - "description": "Output Buzzer" + "label": "Buzzer Output", + "description": "Buzzer Output" }, "active": { - "label": "Active", - "description": "Active" + "label": "Attivo", + "description": "Attivo" }, "alertMessage": { - "label": "Alert Message", - "description": "Alert Message" + "label": "Messaggio di allerta", + "description": "Messaggio di allerta" }, "alertMessageVibra": { - "label": "Alert Message Vibrate", - "description": "Alert Message Vibrate" + "label": "Vibrazione Messaggio Di Allerta", + "description": "Vibrazione Messaggio Di Allerta" }, "alertMessageBuzzer": { - "label": "Alert Message Buzzer", - "description": "Alert Message Buzzer" + "label": "Buzzer Messaggio Di Allerta", + "description": "Buzzer Messaggio Di Allerta" }, "alertBell": { - "label": "Alert Bell", - "description": "Should an alert be triggered when receiving an incoming bell?" + "label": "Campanella Di Allarme", + "description": "Occorre attivare una segnalazione quando si riceve un campanello in entrata?" }, "alertBellVibra": { - "label": "Alert Bell Vibrate", - "description": "Alert Bell Vibrate" + "label": "Vibrazione campanella di allarme", + "description": "Vibrazione campanella di allarme" }, "alertBellBuzzer": { - "label": "Alert Bell Buzzer", - "description": "Alert Bell Buzzer" + "label": "Buzzer campanella di allarme", + "description": "Buzzer campanella di allarme" }, "usePwm": { - "label": "Use PWM", - "description": "Use PWM" + "label": "Usa PWM", + "description": "Usa PWM" }, "nagTimeout": { "label": "Nag Timeout", "description": "Nag Timeout" }, "useI2sAsBuzzer": { - "label": "Use I²S Pin as Buzzer", - "description": "Designate I²S Pin as Buzzer Output" + "label": "Usa I2S come buzzer", + "description": "Designa il Pin I²S come Uscita Buzzer" } }, "mqtt": { - "title": "MQTT Settings", - "description": "Settings for the MQTT module", + "title": "Impostazioni MQTT", + "description": "Impostazioni per il modulo MQTT", "enabled": { - "label": "Enabled", - "description": "Enable or disable MQTT" + "label": "Abilitato", + "description": "Abilita o disabilita MQTT" }, "address": { - "label": "MQTT Server Address", - "description": "MQTT server address to use for default/custom servers" + "label": "Indirizzo Server MQTT", + "description": "Indirizzo server MQTT da usare per i server predefiniti/personalizzati" }, "username": { - "label": "MQTT Username", - "description": "MQTT username to use for default/custom servers" + "label": "Username MQTT", + "description": "Username MQTT da usare per i server predefiniti/personalizzati" }, "password": { - "label": "MQTT Password", - "description": "MQTT password to use for default/custom servers" + "label": "Password MQTT", + "description": "Password MQTT da usare per server predefiniti/personalizzati" }, "encryptionEnabled": { - "label": "Encryption Enabled", - "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + "label": "Crittografia Abilitata", + "description": "Abilita o disabilita la crittografia MQTT. Nota: Tutti i messaggi sono inviati al broker MQTT non cifrati se questa opzione non è abilitata, anche quando i canali uplink hanno chiavi di crittografia impostate. Ciò include i dati di posizione." }, "jsonEnabled": { - "label": "JSON Enabled", - "description": "Whether to send/consume JSON packets on MQTT" + "label": "JSON Abilitato", + "description": "Indica se inviare/consumare pacchetti JSON su MQTT" }, "tlsEnabled": { - "label": "TLS Enabled", - "description": "Enable or disable TLS" + "label": "TLS abilitato", + "description": "Abilita o disabilita MQTT" }, "root": { "label": "Root topic", - "description": "MQTT root topic to use for default/custom servers" + "description": "Topic root MQTT da utilizzare per server predefiniti/personalizzati" }, "proxyToClientEnabled": { - "label": "MQTT Client Proxy Enabled", - "description": "Utilizes the network connection to proxy MQTT messages to the client." + "label": "Proxy Client MQTT Abilitato", + "description": "Utilizza la connessione di rete per fare da proxy ai messaggi MQTT verso il client." }, "mapReportingEnabled": { - "label": "Map Reporting Enabled", - "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + "label": "Segnalazione sulla Mappa Abilitata", + "description": "Il tuo nodo invierà periodicamente un pacchetto di segnalazione mappa non criptato al server MQTT configurato, questo include id, nome breve e lungo, posizione approssimativa, modello hardware, ruolo, versione del firmware, regione LoRa, preset del modem e nome del canale primario." }, "mapReportSettings": { "publishIntervalSecs": { - "label": "Map Report Publish Interval (s)", - "description": "Interval in seconds to publish map reports" + "label": "Intervallo di Pubblicazione Segnalazione Mappa (s)", + "description": "Intervallo in secondi per pubblicare le segnalazioni mappa" }, "positionPrecision": { - "label": "Approximate Location", - "description": "Position shared will be accurate within this distance", + "label": "Posizione Approssimativa", + "description": "La posizione condivisa sarà accurata entro questa distanza", "options": { - "metric_km23": "Within 23 km", - "metric_km12": "Within 12 km", - "metric_km5_8": "Within 5.8 km", - "metric_km2_9": "Within 2.9 km", - "metric_km1_5": "Within 1.5 km", - "metric_m700": "Within 700 m", - "metric_m350": "Within 350 m", - "metric_m200": "Within 200 m", - "metric_m90": "Within 90 m", - "metric_m50": "Within 50 m", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" + "metric_km23": "Entro 23 km", + "metric_km12": "Entro 12 km", + "metric_km5_8": "Entro 5,8 km", + "metric_km2_9": "Entro 2,9 km", + "metric_km1_5": "Entro 1,5 km", + "metric_m700": "Entro 700 m", + "metric_m350": "Entro 350 m", + "metric_m200": "Entro 200 m", + "metric_m90": "Entro 90 m", + "metric_m50": "Entro 50 m", + "imperial_mi15": "Entro 15 miglia", + "imperial_mi7_3": "Entro 7,3 miglia", + "imperial_mi3_6": "Entro 3,6 miglia", + "imperial_mi1_8": "Entro 1,8 miglia", + "imperial_mi0_9": "Entro 0,9 miglia", + "imperial_mi0_5": "Entro 0,5 miglia", + "imperial_mi0_2": "Entro 0,2 miglia", + "imperial_ft600": "Entro 600 piedi", + "imperial_ft300": "Entro 300 piedi", + "imperial_ft150": "Entro 150 piedi" } } } }, "neighborInfo": { - "title": "Neighbor Info Settings", - "description": "Settings for the Neighbor Info module", + "title": "Impostazioni Informazioni Vicini", + "description": "Impostazioni per il modulo Informazioni Vicini", "enabled": { - "label": "Enabled", - "description": "Enable or disable Neighbor Info Module" + "label": "Abilitato", + "description": "Abilita o disabilita Modulo Info Vicini" }, "updateInterval": { - "label": "Update Interval", - "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + "label": "Intervallo di Aggiornamento", + "description": "Intervallo in secondi di quanto spesso dovremmo cercare di inviare le nostre Info Vicini alla mesh" } }, "paxcounter": { - "title": "Paxcounter Settings", - "description": "Settings for the Paxcounter module", + "title": "Impostazioni Paxcounter", + "description": "Impostazioni per il modulo Paxcounter", "enabled": { - "label": "Module Enabled", - "description": "Enable Paxcounter" + "label": "Modulo abilitato", + "description": "Abilita Paxcounter" }, "paxcounterUpdateInterval": { - "label": "Update Interval (seconds)", - "description": "How long to wait between sending paxcounter packets" + "label": "Intervallo di aggiornamento (secondi)", + "description": "Per quanto tempo attendere tra l'invio di pacchetti paxcounter" }, "wifiThreshold": { - "label": "WiFi RSSI Threshold", - "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + "label": "Soglia RSSI WiFi", + "description": "A quale livello RSSI WiFi dovrebbe aumentare il contatore. Predefinito a -80." }, "bleThreshold": { - "label": "BLE RSSI Threshold", - "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + "label": "Soglia RSSI BLE", + "description": "A quale livello RSSI BLE dovrebbe aumentare il contatore. Predefinito a -80." } }, "rangeTest": { - "title": "Range Test Settings", - "description": "Settings for the Range Test module", + "title": "Impostazioni Di Range Test", + "description": "Impostazioni per il modulo Range Test", "enabled": { - "label": "Module Enabled", - "description": "Enable Range Test" + "label": "Modulo abilitato", + "description": "Abilita Range Test" }, "sender": { - "label": "Message Interval", - "description": "How long to wait between sending test packets" + "label": "Intervallo Dei Messaggi", + "description": "Per quanto tempo attendere tra l'invio dei pacchetti di test" }, "save": { - "label": "Save CSV to storage", - "description": "ESP32 Only" + "label": "Salva CSV nella memoria", + "description": "Solo ESP32" } }, "serial": { - "title": "Serial Settings", - "description": "Settings for the Serial module", + "title": "Impostazioni Seriale", + "description": "Impostazioni per il modulo seriale", "enabled": { - "label": "Module Enabled", - "description": "Enable Serial output" + "label": "Modulo abilitato", + "description": "Abilita output seriale" }, "echo": { "label": "Echo", - "description": "Any packets you send will be echoed back to your device" + "description": "Tutti i pacchetti che invii verranno rimandati indietro al tuo dispositivo" }, "rxd": { - "label": "Receive Pin", - "description": "Set the GPIO pin to the RXD pin you have set up." + "label": "Pin di ricezione", + "description": "Imposta il pin GPIO al pin RXD che hai configurato." }, "txd": { - "label": "Transmit Pin", - "description": "Set the GPIO pin to the TXD pin you have set up." + "label": "Pin di trasmissione", + "description": "Imposta il pin GPIO al pin TXD che hai configurato." }, "baud": { - "label": "Baud Rate", - "description": "The serial baud rate" + "label": "Baud rate", + "description": "La velocità di trasmissione seriale" }, "timeout": { "label": "Timeout", - "description": "Seconds to wait before we consider your packet as 'done'" + "description": "Secondi da attesa prima di considerare il tuo pacchetto come 'fatto'" }, "mode": { - "label": "Mode", - "description": "Select Mode" + "label": "Modalità", + "description": "Seleziona modalità" }, "overrideConsoleSerialPort": { - "label": "Override Console Serial Port", - "description": "If you have a serial port connected to the console, this will override it." + "label": "Sovrascrivi La Porta Seriale Della Console", + "description": "Se si dispone di una porta seriale collegata alla console, questa verrà sostituita." } }, "storeForward": { - "title": "Store & Forward Settings", - "description": "Settings for the Store & Forward module", + "title": "Configurazione Salva & Inoltra", + "description": "Impostazioni per il modulo Salva & Inoltra", "enabled": { - "label": "Module Enabled", - "description": "Enable Store & Forward" + "label": "Modulo abilitato", + "description": "Abilita Salva & Inoltra" }, "heartbeat": { - "label": "Heartbeat Enabled", - "description": "Enable Store & Forward heartbeat" + "label": "Heartbeat Abilitato", + "description": "Abilita heartbeat Store & Forward" }, "records": { "label": "Numero di record", - "description": "Number of records to store" + "description": "Numero di record da memorizzare" }, "historyReturnMax": { "label": "Cronologia ritorno max", - "description": "Max number of records to return" + "description": "Numero massimo di record da restituire" }, "historyReturnWindow": { "label": "Finestra di ritorno cronologia", - "description": "Max number of records to return" + "description": "Numero massimo di record da restituire" } }, "telemetry": { - "title": "Telemetry Settings", - "description": "Settings for the Telemetry module", + "title": "Impostazioni Telemetria", + "description": "Impostazioni per il modulo Telemetria", "deviceUpdateInterval": { - "label": "Device Metrics", + "label": "Metriche Dispositivo", "description": "Intervallo aggiornamento metriche dispositivo (secondi)" }, "environmentUpdateInterval": { @@ -413,36 +413,36 @@ "description": "" }, "environmentMeasurementEnabled": { - "label": "Module Enabled", - "description": "Enable the Environment Telemetry" + "label": "Modulo abilitato", + "description": "Abilita la telemetria Ambiente" }, "environmentScreenEnabled": { - "label": "Displayed on Screen", - "description": "Show the Telemetry Module on the OLED" + "label": "Visualizzato sullo schermo", + "description": "Mostra il modulo di telemetria sull'OLED" }, "environmentDisplayFahrenheit": { - "label": "Display Fahrenheit", - "description": "Display temp in Fahrenheit" + "label": "Mostra Fahrenheit", + "description": "Mostra la temperatura in Fahrenheit" }, "airQualityEnabled": { - "label": "Air Quality Enabled", - "description": "Enable the Air Quality Telemetry" + "label": "Qualità Dell'Aria Abilitata", + "description": "Abilita la telemetria della qualità dell'aria" }, "airQualityInterval": { - "label": "Air Quality Update Interval", - "description": "How often to send Air Quality data over the mesh" + "label": "Intervallo Di Aggiornamento Qualità Dell'Aria", + "description": "Quanto spesso inviare dati sulla qualità dell'aria sulla mesh" }, "powerMeasurementEnabled": { - "label": "Power Measurement Enabled", - "description": "Enable the Power Measurement Telemetry" + "label": "Misurazione Alimentazione Abilitata", + "description": "Abilita la telemetria di misura della alimentazione" }, "powerUpdateInterval": { - "label": "Power Update Interval", - "description": "How often to send Power data over the mesh" + "label": "Intervallo Di Aggiornamento Alimentazione", + "description": "Quanto spesso inviare i dati di alimentazione sulla mesh" }, "powerScreenEnabled": { - "label": "Power Screen Enabled", - "description": "Enable the Power Telemetry Screen" + "label": "Schermo Di Alimentazione Abilitato", + "description": "Abilita lo schermo di Telemetria di alimentazione" } } } diff --git a/src/i18n/locales/it-IT/nodes.json b/src/i18n/locales/it-IT/nodes.json index cfaa76be..08bb7559 100644 --- a/src/i18n/locales/it-IT/nodes.json +++ b/src/i18n/locales/it-IT/nodes.json @@ -1,51 +1,63 @@ { "nodeDetail": { "publicKeyEnabled": { - "label": "Public Key Enabled" + "label": "Chiave Pubblica Abilitata" }, "noPublicKey": { - "label": "No Public Key" + "label": "Nessuna Chiave Pubblica" }, "directMessage": { - "label": "Direct Message {{shortName}}" + "label": "Messaggio Diretto {{shortName}}" }, "favorite": { - "label": "Preferito" + "label": "Preferito", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { - "label": "Not a Favorite" + "label": "Non è un preferito" + }, + "error": { + "label": "Errori", + "text": "An error occurred while fetching node details. Please try again later." }, "status": { - "heard": "Heard", + "heard": "Sentito", "mqtt": "MQTT" }, "elevation": { - "label": "Elevation" + "label": "Altezza" }, "channelUtil": { - "label": "Channel Util" + "label": "Utilizzo Canale" }, "airtimeUtil": { - "label": "Airtime Util" + "label": "Utilizzo Airtime" } }, "nodesTable": { "headings": { - "longName": "Long Name", - "connection": "Connection", - "lastHeard": "Last Heard", - "encryption": "Encryption", - "model": "Model", - "macAddress": "MAC Address" + "longName": "Nome Lungo", + "connection": "Connessione", + "lastHeard": "Ultimo Contatto", + "encryption": "Crittografia", + "model": "Modello", + "macAddress": "Indirizzo MAC" }, "connectionStatus": { "direct": "Diretto", - "away": "away", + "away": "assente", "unknown": "-", - "viaMqtt": ", via MQTT" + "viaMqtt": ", tramite MQTT" }, "lastHeardStatus": { - "never": "Never" + "never": "Mai" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Richiedi posizione" } } diff --git a/src/i18n/locales/it-IT/ui.json b/src/i18n/locales/it-IT/ui.json index 110b4ffb..2925be76 100644 --- a/src/i18n/locales/it-IT/ui.json +++ b/src/i18n/locales/it-IT/ui.json @@ -1,93 +1,111 @@ { "navigation": { - "title": "Navigation", + "title": "Navigazione", "messages": "Messaggi", "map": "Mappa", - "config": "Config", - "radioConfig": "Radio Config", - "moduleConfig": "Module Config", + "config": "Configurazione", + "radioConfig": "Configurazione Radio", + "moduleConfig": "Configurazione Modulo", "channels": "Canali", "nodes": "Nodi" }, "app": { "title": "Meshtastic", - "logo": "Meshtastic Logo" + "logo": "Logo Meshtastic" }, "sidebar": { "collapseToggle": { "button": { - "open": "Open sidebar", - "close": "Close sidebar" + "open": "Apri barra laterale", + "close": "Chiudi barra laterale" } }, "deviceInfo": { - "volts": "{{voltage}} volts", + "volts": "{{voltage}} volt", "firmware": { "title": "Firmware", "version": "v{{version}}", - "buildDate": "Build date: {{date}}" + "buildDate": "Data di build: {{date}}" }, "deviceName": { - "title": "Device Name", - "changeName": "Change Device Name", - "placeholder": "Enter device name" + "title": "Nome del dispositivo", + "changeName": "Cambia Nome Del Dispositivo", + "placeholder": "Inserisci il nome del dispositivo" }, - "editDeviceName": "Edit device name" + "editDeviceName": "Modifica il nome del dispositivo" } }, "batteryStatus": { - "charging": "{{level}}% charging", - "pluggedIn": "Plugged in", + "charging": "{{level}}% in carica", + "pluggedIn": "Alimentato", "title": "Batteria" }, "search": { - "nodes": "Search nodes...", - "channels": "Search channels...", - "commandPalette": "Search commands..." + "nodes": "Cerca nodi...", + "channels": "Cerca canali...", + "commandPalette": "Cerca comandi..." }, "toast": { "positionRequestSent": { - "title": "Position request sent." + "title": "Richiesta di posizione inviata." }, "requestingPosition": { - "title": "Requesting position, please wait..." + "title": "Richiesta di posizione, attendere prego..." }, "sendingTraceroute": { - "title": "Sending Traceroute, please wait..." + "title": "Invio di Traceroute, attendere prego..." }, "tracerouteSent": { - "title": "Traceroute sent." + "title": "Traceroute inviato." }, "savedChannel": { - "title": "Saved Channel: {{channelName}}" + "title": "Canale Salvato: {{channelName}}" }, "messages": { "pkiEncryption": { - "title": "Chat is using PKI encryption." + "title": "La chat sta usando la crittografia PKI." }, "pskEncryption": { - "title": "Chat is using PSK encryption." + "title": "La chat sta usando la crittografia PSK." } }, "configSaveError": { - "title": "Error Saving Config", - "description": "An error occurred while saving the configuration." + "title": "Errore Salvataggio Configurazione", + "description": "Si è verificato un errore durante il salvataggio di questa configurazione." }, "validationError": { - "title": "Config Errors Exist", - "description": "Please fix the configuration errors before saving." + "title": "Esistono errori di configurazione", + "description": "Correggi gli errori di configurazione prima di salvare." }, "saveSuccess": { - "title": "Saving Config", - "description": "The configuration change {{case}} has been saved." + "title": "Salvataggio Configurazione", + "description": "La modifica di configurazione {{case}} è stata salvata." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { "copied": { - "label": "Copied!" + "label": "Copiato!" }, "copyToClipboard": { - "label": "Copy to clipboard" + "label": "Copia negli appunti" }, "hidePassword": { "label": "Nascondi password" @@ -96,14 +114,14 @@ "label": "Visualizza password" }, "deliveryStatus": { - "delivered": "Delivered", - "failed": "Delivery Failed", - "waiting": "Waiting", - "unknown": "Unknown" + "delivered": "Consegnato", + "failed": "Consegna Fallita", + "waiting": "In attesa", + "unknown": "Sconosciuto" } }, "general": { - "label": "General" + "label": "Generale" }, "hardware": { "label": "Hardware" @@ -117,85 +135,94 @@ "filter": { "label": "Filtro" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { - "label": "Clear input" + "label": "Cancella input" }, "resetFilters": { - "label": "Reset Filters" + "label": "Ripristina Filtri" }, "nodeName": { - "label": "Node name/number", + "label": "Nome/numero del nodo", "placeholder": "Meshtastic 1234" }, "airtimeUtilization": { - "label": "Airtime Utilization (%)" + "label": "Tempo di Trasmissione Utilizzato (%)" }, "batteryLevel": { - "label": "Battery level (%)", - "labelText": "Battery level (%): {{value}}" + "label": "Livello batteria (%)", + "labelText": "Livello batteria (%): {{value}}" }, "batteryVoltage": { - "label": "Battery voltage (V)", + "label": "Tensione della Batteria (V)", "title": "Tensione" }, "channelUtilization": { - "label": "Channel Utilization (%)" + "label": "Utilizzo Canale (%)" }, "hops": { "direct": "Diretto", - "label": "Number of hops", - "text": "Number of hops: {{value}}" + "label": "Numero di hop", + "text": "Numero di hop: {{value}}" }, "lastHeard": { "label": "Ricevuto più di recente", - "labelText": "Last heard: {{value}}", - "nowLabel": "Now" + "labelText": "Ultimo contatto: {{value}}", + "nowLabel": "Adesso" }, "snr": { - "label": "SNR (db)" + "label": "SNR (dB)" }, "favorites": { - "label": "Favorites" + "label": "Preferiti" }, "hide": { - "label": "Hide" + "label": "Nascondi" }, "showOnly": { - "label": "Show Only" + "label": "Mostra Solo" }, "viaMqtt": { - "label": "Connected via MQTT" + "label": "Connesso tramite MQTT" + }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" }, "language": { "label": "Lingua", - "changeLanguage": "Change Language" + "changeLanguage": "Cambia Lingua" }, "theme": { "dark": "Scuro", "light": "Chiaro", - "system": "Automatic", - "changeTheme": "Change Color Scheme" + "system": "Automatico", + "changeTheme": "Modifica lo schema dei colori" }, "errorPage": { - "title": "This is a little embarrassing...", - "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", - "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", - "reportInstructions": "Please include the following information in your report:", + "title": "Questo è un po' imbarazzante...", + "description1": "Siamo davvero spiacenti, ma si è verificato un errore nel client web che ha causato il crash.
Questo non dovrebbe accadere e stiamo lavorando duramente per risolverlo.", + "description2": "Il modo migliore per evitare che ciò accada di nuovo a voi o a chiunque altro è quello di riferire la questione a noi.", + "reportInstructions": "Per favore includi le seguenti informazioni nel tuo report:", "reportSteps": { - "step1": "What you were doing when the error occurred", - "step2": "What you expected to happen", - "step3": "What actually happened", - "step4": "Any other relevant information" - }, - "reportLink": "You can report the issue to our <0>GitHub", - "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", + "step1": "Cosa stavi facendo quando si è verificato l'errore", + "step2": "Cosa ti aspettavi succedesse", + "step3": "Quello che è successo realmente", + "step4": "Altre informazioni rilevanti" + }, + "reportLink": "Puoi segnalare il problema al nostro <0>GitHub", + "dashboardLink": "Ritorna alla <0>dashboard", + "detailsSummary": "Dettagli Errore", + "errorMessageLabel": "Messaggio di errore:", "stackTraceLabel": "Stack trace:", "fallbackError": "{{error}}" }, "footer": { - "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "text": "Powered by <0>▲ Vercel | Meshtastic® è un marchio registrato di Meshtastic LLC. | <1>Informazioni Legali", "commitSha": "Commit SHA: {{sha}}" } } diff --git a/src/i18n/locales/ja-JP/common.json b/src/i18n/locales/ja-JP/common.json index e594bfd1..000754fb 100644 --- a/src/i18n/locales/ja-JP/common.json +++ b/src/i18n/locales/ja-JP/common.json @@ -24,7 +24,8 @@ "reset": "リセット", "save": "保存", "scanQr": "QRコードをスキャン", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SN比", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/ja-JP/dialog.json b/src/i18n/locales/ja-JP/dialog.json index ca055f94..86498524 100644 --- a/src/i18n/locales/ja-JP/dialog.json +++ b/src/i18n/locales/ja-JP/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "よろしいですか?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "よろしいですか?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/ja-JP/messages.json b/src/i18n/locales/ja-JP/messages.json index b6835744..62ae8df7 100644 --- a/src/i18n/locales/ja-JP/messages.json +++ b/src/i18n/locales/ja-JP/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "送信" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "返信" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/ja-JP/nodes.json b/src/i18n/locales/ja-JP/nodes.json index c019ff57..181220f0 100644 --- a/src/i18n/locales/ja-JP/nodes.json +++ b/src/i18n/locales/ja-JP/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "お気に入り" + "label": "お気に入り", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "エラー", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/ja-JP/ui.json b/src/i18n/locales/ja-JP/ui.json index 95fa0250..56983270 100644 --- a/src/i18n/locales/ja-JP/ui.json +++ b/src/i18n/locales/ja-JP/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "絞り込み" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "言語設定", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/ko-KR/channels.json b/src/i18n/locales/ko-KR/channels.json new file mode 100644 index 00000000..0987f269 --- /dev/null +++ b/src/i18n/locales/ko-KR/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "채널", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Primary", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "채널 설정", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "역할", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "이름", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/ko-KR/commandPalette.json b/src/i18n/locales/ko-KR/commandPalette.json new file mode 100644 index 00000000..a7bcc191 --- /dev/null +++ b/src/i18n/locales/ko-KR/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "메시지", + "map": "지도", + "config": "Config", + "channels": "채널", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "불러오기", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/ko-KR/common.json b/src/i18n/locales/ko-KR/common.json new file mode 100644 index 00000000..6b7b6a87 --- /dev/null +++ b/src/i18n/locales/ko-KR/common.json @@ -0,0 +1,141 @@ +{ + "button": { + "apply": "적용", + "backupKey": "Backup Key", + "cancel": "취소", + "clearMessages": "Clear Messages", + "close": "닫기", + "confirm": "Confirm", + "delete": "삭제", + "dismiss": "Dismiss", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "불러오기", + "message": "메시지", + "now": "Now", + "ok": "확인", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "지우기", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "초기화", + "save": "저장", + "scanQr": " QR코드 스캔", + "traceRoute": "Trace Route", + "submit": "Submit" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, + "snr": "SNR", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", + "256bit": "256 bit" + }, + "unknown": { + "longName": "Unknown", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "node": "Node", + "formValidation": { + "unsavedChanges": "Unsaved changes", + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/ko-KR/dashboard.json b/src/i18n/locales/ko-KR/dashboard.json new file mode 100644 index 00000000..c3dc1447 --- /dev/null +++ b/src/i18n/locales/ko-KR/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "시리얼", + "connectionType_network": "네트워크", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/ko-KR/deviceConfig.json b/src/i18n/locales/ko-KR/deviceConfig.json new file mode 100644 index 00000000..c26b0244 --- /dev/null +++ b/src/i18n/locales/ko-KR/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "블루투스", + "tabDevice": "기기", + "tabDisplay": "화면", + "tabLora": "LoRa", + "tabNetwork": "네트워크", + "tabPosition": "위치", + "tabPower": "전원", + "tabSecurity": "보안" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX 시간대" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "역할" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Enabled" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "페어링 모드" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "대역폭" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "MQTT로 부터 수신 무시" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "모뎀 프리셋" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "MQTT로 전송 허용" + }, + "overrideDutyCycle": { + "description": "Duty Cycle 무시", + "label": "Duty Cycle 무시" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "지역" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Radio Settings", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Enabled" + }, + "gateway": { + "description": "Default Gateway", + "label": "게이트웨이" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "서브넷" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Enabled" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "UDP 설정" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "타임스탬프", + "unset": "해제", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "저젼력 모드 설정" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "전원 설정" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "개인 키" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "공개 키" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/ko-KR/dialog.json b/src/i18n/locales/ko-KR/dialog.json new file mode 100644 index 00000000..8e2459f4 --- /dev/null +++ b/src/i18n/locales/ko-KR/dialog.json @@ -0,0 +1,171 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "블루투스", + "tabSerial": "시리얼", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "메시지", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "전압", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generate QR Code" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "확실합니까?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "확실합니까?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." + } +} diff --git a/src/i18n/locales/ko-KR/messages.json b/src/i18n/locales/ko-KR/messages.json new file mode 100644 index 00000000..e1d652ea --- /dev/null +++ b/src/i18n/locales/ko-KR/messages.json @@ -0,0 +1,39 @@ +{ + "page": { + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Enter your message here...", + "sendButton": "보내기" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Reply" + }, + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" + } + } +} diff --git a/src/i18n/locales/ko-KR/moduleConfig.json b/src/i18n/locales/ko-KR/moduleConfig.json new file mode 100644 index 00000000..628da18b --- /dev/null +++ b/src/i18n/locales/ko-KR/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "조명", + "tabAudio": "오디오", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "감지 센서", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "이웃 정보", + "tabPaxcounter": "팍스카운터", + "tabRangeTest": "거리 테스트", + "tabSerial": "시리얼", + "tabStoreAndForward": "S&F", + "tabTelemetry": "텔레메트리" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "전류", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "빨강", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "초록", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "파랑", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Enabled", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "시간 초과됨", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Mode", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "기기 메트릭 업데이트 간격 (초)" + }, + "environmentUpdateInterval": { + "label": "환경 메트릭 업데이트 간격 (초)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/ko-KR/nodes.json b/src/i18n/locales/ko-KR/nodes.json new file mode 100644 index 00000000..e6e37463 --- /dev/null +++ b/src/i18n/locales/ko-KR/nodes.json @@ -0,0 +1,63 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "즐겨찾기", + "tooltip": "Add or remove this node from your favorites" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "error": { + "label": "오류", + "text": "An error occurred while fetching node details. Please try again later." + }, + "status": { + "heard": "Heard", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "직접 연결", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" + } +} diff --git a/src/i18n/locales/ko-KR/ui.json b/src/i18n/locales/ko-KR/ui.json new file mode 100644 index 00000000..d413bed1 --- /dev/null +++ b/src/i18n/locales/ko-KR/ui.json @@ -0,0 +1,228 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "메시지", + "map": "지도", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "채널", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "펌웨어", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "배터리" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "비밀번호 숨김" + }, + "showPassword": { + "label": "비밀번호 보기" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Waiting", + "unknown": "Unknown" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "하드웨어" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "역할" + }, + "filter": { + "label": "필터" + }, + "advanced": { + "label": "Advanced" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "전압" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "직접 연결", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "최근 수신", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, + "language": { + "label": "언어", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "다크", + "light": "라이트", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/nl-NL/common.json b/src/i18n/locales/nl-NL/common.json index 28b10515..e426f48b 100644 --- a/src/i18n/locales/nl-NL/common.json +++ b/src/i18n/locales/nl-NL/common.json @@ -24,7 +24,8 @@ "reset": "Reset", "save": "Opslaan", "scanQr": "Scan QR-code", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/nl-NL/dialog.json b/src/i18n/locales/nl-NL/dialog.json index d575cca2..0c6555cd 100644 --- a/src/i18n/locales/nl-NL/dialog.json +++ b/src/i18n/locales/nl-NL/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Weet u het zeker?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Weet u het zeker?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/nl-NL/messages.json b/src/i18n/locales/nl-NL/messages.json index 48c98b4a..2572ee9e 100644 --- a/src/i18n/locales/nl-NL/messages.json +++ b/src/i18n/locales/nl-NL/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Verzend" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "Reply" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/nl-NL/nodes.json b/src/i18n/locales/nl-NL/nodes.json index 5ff9d341..925ab911 100644 --- a/src/i18n/locales/nl-NL/nodes.json +++ b/src/i18n/locales/nl-NL/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favoriet" + "label": "Favoriet", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Foutmelding", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/nl-NL/ui.json b/src/i18n/locales/nl-NL/ui.json index 6db74c2a..2cb34f46 100644 --- a/src/i18n/locales/nl-NL/ui.json +++ b/src/i18n/locales/nl-NL/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filter" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Taal", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/pl-PL/channels.json b/src/i18n/locales/pl-PL/channels.json new file mode 100644 index 00000000..ddbc26b5 --- /dev/null +++ b/src/i18n/locales/pl-PL/channels.json @@ -0,0 +1,69 @@ +{ + "page": { + "sectionLabel": "Kanały", + "channelName": "Channel: {{channelName}}", + "broadcastLabel": "Podstawowy", + "channelIndex": "Ch {{index}}" + }, + "validation": { + "pskInvalid": "Please enter a valid {{bits}} bit PSK." + }, + "settings": { + "label": "Ustawienia kanału", + "description": "Crypto, MQTT & misc settings" + }, + "role": { + "label": "Rola", + "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + "options": { + "primary": "PRIMARY", + "disabled": "DISABLED", + "secondary": "SECONDARY" + } + }, + "psk": { + "label": "Pre-Shared Key", + "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + "generate": "Generate" + }, + "name": { + "label": "Nazwa", + "description": "A unique name for the channel <12 bytes, leave blank for default" + }, + "uplinkEnabled": { + "label": "Uplink Enabled", + "description": "Send messages from the local mesh to MQTT" + }, + "downlinkEnabled": { + "label": "Downlink Enabled", + "description": "Send messages from MQTT to the local mesh" + }, + "positionPrecision": { + "label": "Location", + "description": "The precision of the location to share with the channel. Can be disabled.", + "options": { + "none": "Do not share location", + "precise": "Precise Location", + "metric_km23": "Within 23 kilometers", + "metric_km12": "Within 12 kilometers", + "metric_km5_8": "Within 5.8 kilometers", + "metric_km2_9": "Within 2.9 kilometers", + "metric_km1_5": "Within 1.5 kilometers", + "metric_m700": "Within 700 meters", + "metric_m350": "Within 350 meters", + "metric_m200": "Within 200 meters", + "metric_m90": "Within 90 meters", + "metric_m50": "Within 50 meters", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } +} diff --git a/src/i18n/locales/pl-PL/commandPalette.json b/src/i18n/locales/pl-PL/commandPalette.json new file mode 100644 index 00000000..5526ed2d --- /dev/null +++ b/src/i18n/locales/pl-PL/commandPalette.json @@ -0,0 +1,50 @@ +{ + "emptyState": "No results found.", + "page": { + "title": "Command Menu" + }, + "pinGroup": { + "label": "Pin command group" + }, + "unpinGroup": { + "label": "Unpin command group" + }, + "goto": { + "label": "Goto", + "command": { + "messages": "Wiadomości", + "map": "Mapa", + "config": "Config", + "channels": "Kanały", + "nodes": "Nodes" + } + }, + "manage": { + "label": "Manage", + "command": { + "switchNode": "Switch Node", + "connectNewNode": "Connect New Node" + } + }, + "contextual": { + "label": "Contextual", + "command": { + "qrCode": "QR Code", + "qrGenerator": "Generator", + "qrImport": "Import", + "scheduleShutdown": "Schedule Shutdown", + "scheduleReboot": "Schedule Reboot", + "rebootToOtaMode": "Reboot To OTA Mode", + "resetNodeDb": "Reset Node DB", + "factoryResetDevice": "Factory Reset Device", + "factoryResetConfig": "Factory Reset Config" + } + }, + "debug": { + "label": "Debug", + "command": { + "reconfigure": "Reconfigure", + "clearAllStoredMessages": "Clear All Stored Message" + } + } +} diff --git a/src/i18n/locales/pl-PL/common.json b/src/i18n/locales/pl-PL/common.json new file mode 100644 index 00000000..6aa8233a --- /dev/null +++ b/src/i18n/locales/pl-PL/common.json @@ -0,0 +1,141 @@ +{ + "button": { + "apply": "Zastosuj", + "backupKey": "Backup Key", + "cancel": "Anuluj", + "clearMessages": "Clear Messages", + "close": "Zamknij", + "confirm": "Confirm", + "delete": "Usuń", + "dismiss": "Zamknij", + "download": "Download", + "export": "Export", + "generate": "Generate", + "regenerate": "Regenerate", + "import": "Import", + "message": "Wiadomość", + "now": "Now", + "ok": "OK", + "print": "Print", + "rebootOtaNow": "Reboot to OTA Mode Now", + "remove": "Usuń", + "requestNewKeys": "Request New Keys", + "requestPosition": "Request Position", + "reset": "Zresetuj", + "save": "Zapisz", + "scanQr": "Scan QR Code", + "traceRoute": "Trace Route", + "submit": "Submit" + }, + "app": { + "title": "Meshtastic", + "fullTitle": "Meshtastic Web Client" + }, + "loading": "Loading...", + "unit": { + "cps": "CPS", + "dbm": "dBm", + "hertz": "Hz", + "hop": { + "one": "Hop", + "plural": "Hops" + }, + "hopsAway": { + "one": "{{count}} hop away", + "plural": "{{count}} hops away", + "unknown": "Unknown hops away" + }, + "megahertz": "MHz", + "raw": "raw", + "meter": { + "one": "Meter", + "plural": "Meters", + "suffix": "m" + }, + "minute": { + "one": "Minute", + "plural": "Minutes" + }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, + "millisecond": { + "one": "Millisecond", + "plural": "Milliseconds", + "suffix": "ms" + }, + "second": { + "one": "Second", + "plural": "Seconds" + }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, + "snr": "SNR:", + "volt": { + "one": "Volt", + "plural": "Volts", + "suffix": "V" + }, + "record": { + "one": "Records", + "plural": "Records" + } + }, + "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", + "256bit": "256 bit" + }, + "unknown": { + "longName": "Nieznany", + "shortName": "UNK", + "notAvailable": "N/A", + "num": "??" + }, + "nodeUnknownPrefix": "!", + "unset": "UNSET", + "fallbackName": "Meshtastic {{last4}}", + "node": "Node", + "formValidation": { + "unsavedChanges": "Unsaved changes", + "tooBig": { + "string": "Too long, expected less than or equal to {{maximum}} characters.", + "number": "Too big, expected a number smaller than or equal to {{maximum}}.", + "bytes": "Too big, expected less than or equal to {{params.maximum}} bytes." + }, + "tooSmall": { + "string": "Too short, expected more than or equal to {{minimum}} characters.", + "number": "Too small, expected a number larger than or equal to {{minimum}}." + }, + "invalidFormat": { + "ipv4": "Invalid format, expected an IPv4 address.", + "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." + }, + "invalidType": { + "number": "Invalid type, expected a number." + }, + "pskLength": { + "0bit": "Key is required to be empty.", + "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", + "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", + "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." + }, + "required": { + "generic": "This field is required.", + "managed": "At least one admin key is requred if the node is managed.", + "key": "Key is required." + } + } +} diff --git a/src/i18n/locales/pl-PL/dashboard.json b/src/i18n/locales/pl-PL/dashboard.json new file mode 100644 index 00000000..f479246f --- /dev/null +++ b/src/i18n/locales/pl-PL/dashboard.json @@ -0,0 +1,12 @@ +{ + "dashboard": { + "title": "Connected Devices", + "description": "Manage your connected Meshtastic devices.", + "connectionType_ble": "BLE", + "connectionType_serial": "Seryjny", + "connectionType_network": "Sieć", + "noDevicesTitle": "No devices connected", + "noDevicesDescription": "Connect a new device to get started.", + "button_newConnection": "New Connection" + } +} diff --git a/src/i18n/locales/pl-PL/deviceConfig.json b/src/i18n/locales/pl-PL/deviceConfig.json new file mode 100644 index 00000000..406284fe --- /dev/null +++ b/src/i18n/locales/pl-PL/deviceConfig.json @@ -0,0 +1,428 @@ +{ + "page": { + "title": "Configuration", + "tabBluetooth": "Bluetooth", + "tabDevice": "Urządzenie", + "tabDisplay": "Wyświetlacz", + "tabLora": "LoRa", + "tabNetwork": "Sieć", + "tabPosition": "Pozycjonowanie", + "tabPower": "Zasilanie", + "tabSecurity": "Bezpieczeństwo" + }, + "sidebar": { + "label": "Modules" + }, + "device": { + "title": "Device Settings", + "description": "Settings for the device", + "buttonPin": { + "description": "Button pin override", + "label": "Button Pin" + }, + "buzzerPin": { + "description": "Buzzer pin override", + "label": "Buzzer Pin" + }, + "disableTripleClick": { + "description": "Disable triple click", + "label": "Disable Triple Click" + }, + "doubleTapAsButtonPress": { + "description": "Treat double tap as button press", + "label": "Double Tap as Button Press" + }, + "ledHeartbeatDisabled": { + "description": "Disable default blinking LED", + "label": "LED Heartbeat Disabled" + }, + "nodeInfoBroadcastInterval": { + "description": "How often to broadcast node info", + "label": "Node Info Broadcast Interval" + }, + "posixTimezone": { + "description": "The POSIX timezone string for the device", + "label": "POSIX Timezone" + }, + "rebroadcastMode": { + "description": "How to handle rebroadcasting", + "label": "Rebroadcast Mode" + }, + "role": { + "description": "What role the device performs on the mesh", + "label": "Rola" + } + }, + "bluetooth": { + "title": "Bluetooth Settings", + "description": "Settings for the Bluetooth module", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "enabled": { + "description": "Enable or disable Bluetooth", + "label": "Włączony" + }, + "pairingMode": { + "description": "Pin selection behaviour.", + "label": "Pairing mode" + }, + "pin": { + "description": "Pin to use when pairing", + "label": "Pin" + } + }, + "display": { + "description": "Settings for the device display", + "title": "Display Settings", + "headingBold": { + "description": "Bolden the heading text", + "label": "Bold Heading" + }, + "carouselDelay": { + "description": "How fast to cycle through windows", + "label": "Carousel Delay" + }, + "compassNorthTop": { + "description": "Fix north to the top of compass", + "label": "Compass North Top" + }, + "displayMode": { + "description": "Screen layout variant", + "label": "Display Mode" + }, + "displayUnits": { + "description": "Display metric or imperial units", + "label": "Display Units" + }, + "flipScreen": { + "description": "Flip display 180 degrees", + "label": "Flip Screen" + }, + "gpsDisplayUnits": { + "description": "Coordinate display format", + "label": "GPS Display Units" + }, + "oledType": { + "description": "Type of OLED screen attached to the device", + "label": "OLED Type" + }, + "screenTimeout": { + "description": "Turn off the display after this long", + "label": "Screen Timeout" + }, + "twelveHourClock": { + "description": "Use 12-hour clock format", + "label": "12-Hour Clock" + }, + "wakeOnTapOrMotion": { + "description": "Wake the device on tap or motion", + "label": "Wake on Tap or Motion" + } + }, + "lora": { + "title": "Mesh Settings", + "description": "Settings for the LoRa mesh", + "bandwidth": { + "description": "Channel bandwidth in MHz", + "label": "Bandwidth" + }, + "boostedRxGain": { + "description": "Boosted RX gain", + "label": "Boosted RX Gain" + }, + "codingRate": { + "description": "The denominator of the coding rate", + "label": "Coding Rate" + }, + "frequencyOffset": { + "description": "Frequency offset to correct for crystal calibration errors", + "label": "Frequency Offset" + }, + "frequencySlot": { + "description": "LoRa frequency channel number", + "label": "Frequency Slot" + }, + "hopLimit": { + "description": "Maximum number of hops", + "label": "Hop Limit" + }, + "ignoreMqtt": { + "description": "Don't forward MQTT messages over the mesh", + "label": "Ignore MQTT" + }, + "modemPreset": { + "description": "Modem preset to use", + "label": "Modem Preset" + }, + "okToMqtt": { + "description": "When set to true, this configuration indicates that the user approves the packet to be uploaded to MQTT. If set to false, remote nodes are requested not to forward packets to MQTT", + "label": "OK to MQTT" + }, + "overrideDutyCycle": { + "description": "Override Duty Cycle", + "label": "Override Duty Cycle" + }, + "overrideFrequency": { + "description": "Override frequency", + "label": "Override Frequency" + }, + "region": { + "description": "Sets the region for your node", + "label": "Region" + }, + "spreadingFactor": { + "description": "Indicates the number of chirps per symbol", + "label": "Spreading Factor" + }, + "transmitEnabled": { + "description": "Enable/Disable transmit (TX) from the LoRa radio", + "label": "Transmit Enabled" + }, + "transmitPower": { + "description": "Max transmit power", + "label": "Transmit Power" + }, + "usePreset": { + "description": "Use one of the predefined modem presets", + "label": "Use Preset" + }, + "meshSettings": { + "description": "Settings for the LoRa mesh", + "label": "Mesh Settings" + }, + "waveformSettings": { + "description": "Settings for the LoRa waveform", + "label": "Waveform Settings" + }, + "radioSettings": { + "label": "Ustawienia radia", + "description": "Settings for the LoRa radio" + } + }, + "network": { + "title": "WiFi Config", + "description": "WiFi radio configuration", + "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", + "addressMode": { + "description": "Address assignment selection", + "label": "Address Mode" + }, + "dns": { + "description": "DNS Server", + "label": "DNS" + }, + "ethernetEnabled": { + "description": "Enable or disable the Ethernet port", + "label": "Włączony" + }, + "gateway": { + "description": "Default Gateway", + "label": "Brama domyślna" + }, + "ip": { + "description": "IP Address", + "label": "IP" + }, + "psk": { + "description": "Network password", + "label": "PSK" + }, + "ssid": { + "description": "Network name", + "label": "SSID" + }, + "subnet": { + "description": "Subnet Mask", + "label": "Subnet" + }, + "wifiEnabled": { + "description": "Enable or disable the WiFi radio", + "label": "Włączony" + }, + "meshViaUdp": { + "label": "Mesh via UDP" + }, + "ntpServer": { + "label": "NTP Server" + }, + "rsyslogServer": { + "label": "Rsyslog Server" + }, + "ethernetConfigSettings": { + "description": "Ethernet port configuration", + "label": "Ethernet Config" + }, + "ipConfigSettings": { + "description": "IP configuration", + "label": "IP Config" + }, + "ntpConfigSettings": { + "description": "NTP configuration", + "label": "NTP Config" + }, + "rsyslogConfigSettings": { + "description": "Rsyslog configuration", + "label": "Rsyslog Config" + }, + "udpConfigSettings": { + "description": "UDP over Mesh configuration", + "label": "Ustawienia UDP" + } + }, + "position": { + "title": "Position Settings", + "description": "Settings for the position module", + "broadcastInterval": { + "description": "How often your position is sent out over the mesh", + "label": "Broadcast Interval" + }, + "enablePin": { + "description": "GPS module enable pin override", + "label": "Enable Pin" + }, + "fixedPosition": { + "description": "Don't report GPS position, but a manually-specified one", + "label": "Fixed Position" + }, + "gpsMode": { + "description": "Configure whether device GPS is Enabled, Disabled, or Not Present", + "label": "GPS Mode" + }, + "gpsUpdateInterval": { + "description": "How often a GPS fix should be acquired", + "label": "GPS Update Interval" + }, + "positionFlags": { + "description": "Optional fields to include when assembling position messages. The more fields are selected, the larger the message will be leading to longer airtime usage and a higher risk of packet loss.", + "label": "Position Flags" + }, + "receivePin": { + "description": "GPS module RX pin override", + "label": "Receive Pin" + }, + "smartPositionEnabled": { + "description": "Only send position when there has been a meaningful change in location", + "label": "Enable Smart Position" + }, + "smartPositionMinDistance": { + "description": "Minimum distance (in meters) that must be traveled before a position update is sent", + "label": "Smart Position Minimum Distance" + }, + "smartPositionMinInterval": { + "description": "Minimum interval (in seconds) that must pass before a position update is sent", + "label": "Smart Position Minimum Interval" + }, + "transmitPin": { + "description": "GPS module TX pin override", + "label": "Transmit Pin" + }, + "intervalsSettings": { + "description": "How often to send position updates", + "label": "Intervals" + }, + "flags": { + "placeholder": "Select position flags...", + "altitude": "Altitude", + "altitudeGeoidalSeparation": "Altitude Geoidal Separation", + "altitudeMsl": "Altitude is Mean Sea Level", + "dop": "Dilution of precision (DOP) PDOP used by default", + "hdopVdop": "If DOP is set, use HDOP / VDOP values instead of PDOP", + "numSatellites": "Number of satellites", + "sequenceNumber": "Sequence number", + "timestamp": "Znacznik czasu", + "unset": "Nieustawiony", + "vehicleHeading": "Vehicle heading", + "vehicleSpeed": "Vehicle speed" + } + }, + "power": { + "adcMultiplierOverride": { + "description": "Used for tweaking battery voltage reading", + "label": "ADC Multiplier Override ratio" + }, + "ina219Address": { + "description": "Address of the INA219 battery monitor", + "label": "INA219 Address" + }, + "lightSleepDuration": { + "description": "How long the device will be in light sleep for", + "label": "Light Sleep Duration" + }, + "minimumWakeTime": { + "description": "Minimum amount of time the device will stay awake for after receiving a packet", + "label": "Minimum Wake Time" + }, + "noConnectionBluetoothDisabled": { + "description": "If the device does not receive a Bluetooth connection, the BLE radio will be disabled after this long", + "label": "No Connection Bluetooth Disabled" + }, + "powerSavingEnabled": { + "description": "Select if powered from a low-current source (i.e. solar), to minimize power consumption as much as possible.", + "label": "Enable power saving mode" + }, + "shutdownOnBatteryDelay": { + "description": "Automatically shutdown node after this long when on battery, 0 for indefinite", + "label": "Shutdown on battery delay" + }, + "superDeepSleepDuration": { + "description": "How long the device will be in super deep sleep for", + "label": "Super Deep Sleep Duration" + }, + "powerConfigSettings": { + "description": "Settings for the power module", + "label": "Konfiguracja zarządzania energią" + }, + "sleepSettings": { + "description": "Sleep settings for the power module", + "label": "Sleep Settings" + } + }, + "security": { + "description": "Settings for the Security configuration", + "title": "Security Settings", + "button_backupKey": "Backup Key", + "adminChannelEnabled": { + "description": "Allow incoming device control over the insecure legacy admin channel", + "label": "Allow Legacy Admin" + }, + "enableDebugLogApi": { + "description": "Output live debug logging over serial, view and export position-redacted device logs over Bluetooth", + "label": "Enable Debug Log API" + }, + "managed": { + "description": "If enabled, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless at least one suitable Remote Admin node has been setup, and the public key is stored in one of the fields above.", + "label": "Managed" + }, + "privateKey": { + "description": "Used to create a shared key with a remote device", + "label": "Klucz prywatny" + }, + "publicKey": { + "description": "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + "label": "Klucz publiczny" + }, + "primaryAdminKey": { + "description": "The primary public key authorized to send admin messages to this node", + "label": "Primary Admin Key" + }, + "secondaryAdminKey": { + "description": "The secondary public key authorized to send admin messages to this node", + "label": "Secondary Admin Key" + }, + "serialOutputEnabled": { + "description": "Serial Console over the Stream API", + "label": "Serial Output Enabled" + }, + "tertiaryAdminKey": { + "description": "The tertiary public key authorized to send admin messages to this node", + "label": "Tertiary Admin Key" + }, + "adminSettings": { + "description": "Settings for Admin", + "label": "Admin Settings" + }, + "loggingSettings": { + "description": "Settings for Logging", + "label": "Logging Settings" + } + } +} diff --git a/src/i18n/locales/pl-PL/dialog.json b/src/i18n/locales/pl-PL/dialog.json new file mode 100644 index 00000000..bf55cb58 --- /dev/null +++ b/src/i18n/locales/pl-PL/dialog.json @@ -0,0 +1,171 @@ +{ + "deleteMessages": { + "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", + "title": "Clear All Messages" + }, + "deviceName": { + "description": "The Device will restart once the config is saved.", + "longName": "Long Name", + "shortName": "Short Name", + "title": "Change Device Name" + }, + "import": { + "description": "The current LoRa configuration will be overridden.", + "error": { + "invalidUrl": "Invalid Meshtastic URL" + }, + "channelPrefix": "Channel: ", + "channelSetUrl": "Channel Set/QR Code URL", + "channels": "Channels:", + "usePreset": "Use Preset?", + "title": "Import Channel Set" + }, + "locationResponse": { + "altitude": "Altitude: ", + "coordinates": "Coordinates: ", + "title": "Location: {{identifier}}" + }, + "pkiRegenerateDialog": { + "title": "Regenerate Pre-Shared Key?", + "description": "Are you sure you want to regenerate the pre-shared key?", + "regenerate": "Regenerate" + }, + "newDeviceDialog": { + "title": "Connect New Device", + "https": "https", + "http": "http", + "tabHttp": "HTTP", + "tabBluetooth": "Bluetooth", + "tabSerial": "Seryjny", + "useHttps": "Use HTTPS", + "connecting": "Connecting...", + "connect": "Connect", + "connectionFailedAlert": { + "title": "Connection Failed", + "descriptionPrefix": "Could not connect to the device. ", + "httpsHint": "If using HTTPS, you may need to accept a self-signed certificate first. ", + "openLinkPrefix": "Please open ", + "openLinkSuffix": " in a new tab", + "acceptTlsWarningSuffix": ", accept any TLS warnings if prompted, then try again", + "learnMoreLink": "Learn more" + }, + "httpConnection": { + "label": "IP Address/Hostname", + "placeholder": "000.000.000.000 / meshtastic.local" + }, + "serialConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device", + "deviceIdentifier": "# {{index}} - {{vendorId}} - {{productId}}" + }, + "bluetoothConnection": { + "noDevicesPaired": "No devices paired yet.", + "newDeviceButton": "New device" + }, + "validation": { + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", + "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", + "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." + } + }, + "nodeDetails": { + "message": "Wiadomość", + "requestPosition": "Request Position", + "traceRoute": "Trace Route", + "airTxUtilization": "Air TX utilization", + "allRawMetrics": "All Raw Metrics:", + "batteryLevel": "Battery level", + "channelUtilization": "Channel utilization", + "details": "Details:", + "deviceMetrics": "Device Metrics:", + "hardware": "Hardware: ", + "lastHeard": "Last Heard: ", + "nodeHexPrefix": "Node Hex: !", + "nodeNumber": "Node Number: ", + "position": "Position:", + "role": "Role: ", + "uptime": "Uptime: ", + "voltage": "Napięcie", + "title": "Node Details for {{identifier}}", + "ignoreNode": "Ignore node", + "removeNode": "Remove node", + "unignoreNode": "Unignore node" + }, + "pkiBackup": { + "loseKeysWarning": "If you lose your keys, you will need to reset your device.", + "secureBackup": "Its important to backup your public and private keys and store your backup securely!", + "footer": "=== END OF KEYS ===", + "header": "=== MESHTASTIC KEYS FOR {{longName}} ({{shortName}}) ===", + "privateKey": "Private Key:", + "publicKey": "Public Key:", + "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", + "title": "Backup Keys" + }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, + "pkiRegenerate": { + "description": "Are you sure you want to regenerate key pair?", + "title": "Regenerate Key Pair" + }, + "qr": { + "addChannels": "Add Channels", + "replaceChannels": "Replace Channels", + "description": "The current LoRa configuration will also be shared.", + "sharableUrl": "Sharable URL", + "title": "Generuj Kod QR" + }, + "rebootOta": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", + "enterDelay": "Enter delay (sec)", + "scheduled": "Reboot has been scheduled" + }, + "reboot": { + "title": "Schedule Reboot", + "description": "Reboot the connected node after x minutes." + }, + "refreshKeys": { + "description": { + "acceptNewKeys": "This will remove the node from device and request new keys.", + "keyMismatchReasonSuffix": ". This is due to the remote node's current public key does not match the previously stored key for this node.", + "unableToSendDmPrefix": "Your node is unable to send a direct message to node: " + }, + "acceptNewKeys": "Accept New Keys", + "title": "Keys Mismatch - {{identifier}}" + }, + "removeNode": { + "description": "Are you sure you want to remove this Node?", + "title": "Remove Node?" + }, + "shutdown": { + "title": "Schedule Shutdown", + "description": "Turn off the connected node after x minutes." + }, + "traceRoute": { + "routeToDestination": "Route to destination:", + "routeBack": "Route back:" + }, + "tracerouteResponse": { + "title": "Traceroute: {{identifier}}" + }, + "unsafeRoles": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "conjunction": " and the blog post about ", + "postamble": " and understand the implications of changing the role.", + "preamble": "I have read the ", + "choosingRightDeviceRole": "Choosing The Right Device Role", + "deviceRoleDocumentation": "Device Role Documentation", + "title": "Jesteś pewny?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Jesteś pewny?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." + } +} diff --git a/src/i18n/locales/pl-PL/messages.json b/src/i18n/locales/pl-PL/messages.json new file mode 100644 index 00000000..c947bf7e --- /dev/null +++ b/src/i18n/locales/pl-PL/messages.json @@ -0,0 +1,39 @@ +{ + "page": { + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" + }, + "emptyState": { + "title": "Select a Chat", + "text": "No messages yet." + }, + "selectChatPrompt": { + "text": "Select a channel or node to start messaging." + }, + "sendMessage": { + "placeholder": "Enter your message here...", + "sendButton": "Wyślij" + }, + "actionsMenu": { + "addReactionLabel": "Add Reaction", + "replyLabel": "Odpowiedz" + }, + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" + } + } +} diff --git a/src/i18n/locales/pl-PL/moduleConfig.json b/src/i18n/locales/pl-PL/moduleConfig.json new file mode 100644 index 00000000..66d635ef --- /dev/null +++ b/src/i18n/locales/pl-PL/moduleConfig.json @@ -0,0 +1,448 @@ +{ + "page": { + "tabAmbientLighting": "Ambient Lighting", + "tabAudio": "Audio", + "tabCannedMessage": "Canned", + "tabDetectionSensor": "Detection Sensor", + "tabExternalNotification": "Ext Notif", + "tabMqtt": "MQTT", + "tabNeighborInfo": "Neighbor Info", + "tabPaxcounter": "Paxcounter", + "tabRangeTest": "Test zasięgu", + "tabSerial": "Seryjny", + "tabStoreAndForward": "S&F", + "tabTelemetry": "Telemetria" + }, + "ambientLighting": { + "title": "Ambient Lighting Settings", + "description": "Settings for the Ambient Lighting module", + "ledState": { + "label": "LED State", + "description": "Sets LED to on or off" + }, + "current": { + "label": "Natężenie", + "description": "Sets the current for the LED output. Default is 10" + }, + "red": { + "label": "Red", + "description": "Sets the red LED level. Values are 0-255" + }, + "green": { + "label": "Green", + "description": "Sets the green LED level. Values are 0-255" + }, + "blue": { + "label": "Blue", + "description": "Sets the blue LED level. Values are 0-255" + } + }, + "audio": { + "title": "Audio Settings", + "description": "Settings for the Audio module", + "codec2Enabled": { + "label": "Codec 2 Enabled", + "description": "Enable Codec 2 audio encoding" + }, + "pttPin": { + "label": "PTT Pin", + "description": "GPIO pin to use for PTT" + }, + "bitrate": { + "label": "Bitrate", + "description": "Bitrate to use for audio encoding" + }, + "i2sWs": { + "label": "i2S WS", + "description": "GPIO pin to use for i2S WS" + }, + "i2sSd": { + "label": "i2S SD", + "description": "GPIO pin to use for i2S SD" + }, + "i2sDin": { + "label": "i2S DIN", + "description": "GPIO pin to use for i2S DIN" + }, + "i2sSck": { + "label": "i2S SCK", + "description": "GPIO pin to use for i2S SCK" + } + }, + "cannedMessage": { + "title": "Canned Message Settings", + "description": "Settings for the Canned Message module", + "moduleEnabled": { + "label": "Module Enabled", + "description": "Enable Canned Message" + }, + "rotary1Enabled": { + "label": "Rotary Encoder #1 Enabled", + "description": "Enable the rotary encoder" + }, + "inputbrokerPinA": { + "label": "Encoder Pin A", + "description": "GPIO Pin Value (1-39) For encoder port A" + }, + "inputbrokerPinB": { + "label": "Encoder Pin B", + "description": "GPIO Pin Value (1-39) For encoder port B" + }, + "inputbrokerPinPress": { + "label": "Encoder Pin Press", + "description": "GPIO Pin Value (1-39) For encoder Press" + }, + "inputbrokerEventCw": { + "label": "Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventCcw": { + "label": "Counter Clockwise event", + "description": "Select input event." + }, + "inputbrokerEventPress": { + "label": "Press event", + "description": "Select input event" + }, + "updown1Enabled": { + "label": "Up Down enabled", + "description": "Enable the up / down encoder" + }, + "allowInputSource": { + "label": "Allow Input Source", + "description": "Select from: '_any', 'rotEnc1', 'upDownEnc1', 'cardkb'" + }, + "sendBell": { + "label": "Send Bell", + "description": "Sends a bell character with each message" + } + }, + "detectionSensor": { + "title": "Detection Sensor Settings", + "description": "Settings for the Detection Sensor module", + "enabled": { + "label": "Włączony", + "description": "Enable or disable Detection Sensor Module" + }, + "minimumBroadcastSecs": { + "label": "Minimum Broadcast Seconds", + "description": "The interval in seconds of how often we can send a message to the mesh when a state change is detected" + }, + "stateBroadcastSecs": { + "label": "State Broadcast Seconds", + "description": "The interval in seconds of how often we should send a message to the mesh with the current state regardless of changes" + }, + "sendBell": { + "label": "Send Bell", + "description": "Send ASCII bell with alert message" + }, + "name": { + "label": "Friendly Name", + "description": "Used to format the message sent to mesh, max 20 Characters" + }, + "monitorPin": { + "label": "Monitor Pin", + "description": "The GPIO pin to monitor for state changes" + }, + "detectionTriggerType": { + "label": "Detection Triggered Type", + "description": "The type of trigger event to be used" + }, + "usePullup": { + "label": "Use Pullup", + "description": "Whether or not use INPUT_PULLUP mode for GPIO pin" + } + }, + "externalNotification": { + "title": "External Notification Settings", + "description": "Configure the external notification module", + "enabled": { + "label": "Module Enabled", + "description": "Enable External Notification" + }, + "outputMs": { + "label": "Output MS", + "description": "Output MS" + }, + "output": { + "label": "Output", + "description": "Output" + }, + "outputVibra": { + "label": "Output Vibrate", + "description": "Output Vibrate" + }, + "outputBuzzer": { + "label": "Output Buzzer", + "description": "Output Buzzer" + }, + "active": { + "label": "Active", + "description": "Active" + }, + "alertMessage": { + "label": "Alert Message", + "description": "Alert Message" + }, + "alertMessageVibra": { + "label": "Alert Message Vibrate", + "description": "Alert Message Vibrate" + }, + "alertMessageBuzzer": { + "label": "Alert Message Buzzer", + "description": "Alert Message Buzzer" + }, + "alertBell": { + "label": "Alert Bell", + "description": "Should an alert be triggered when receiving an incoming bell?" + }, + "alertBellVibra": { + "label": "Alert Bell Vibrate", + "description": "Alert Bell Vibrate" + }, + "alertBellBuzzer": { + "label": "Alert Bell Buzzer", + "description": "Alert Bell Buzzer" + }, + "usePwm": { + "label": "Use PWM", + "description": "Use PWM" + }, + "nagTimeout": { + "label": "Nag Timeout", + "description": "Nag Timeout" + }, + "useI2sAsBuzzer": { + "label": "Use I²S Pin as Buzzer", + "description": "Designate I²S Pin as Buzzer Output" + } + }, + "mqtt": { + "title": "MQTT Settings", + "description": "Settings for the MQTT module", + "enabled": { + "label": "Włączony", + "description": "Enable or disable MQTT" + }, + "address": { + "label": "MQTT Server Address", + "description": "MQTT server address to use for default/custom servers" + }, + "username": { + "label": "MQTT Username", + "description": "MQTT username to use for default/custom servers" + }, + "password": { + "label": "MQTT Password", + "description": "MQTT password to use for default/custom servers" + }, + "encryptionEnabled": { + "label": "Encryption Enabled", + "description": "Enable or disable MQTT encryption. Note: All messages are sent to the MQTT broker unencrypted if this option is not enabled, even when your uplink channels have encryption keys set. This includes position data." + }, + "jsonEnabled": { + "label": "JSON Enabled", + "description": "Whether to send/consume JSON packets on MQTT" + }, + "tlsEnabled": { + "label": "TLS Enabled", + "description": "Enable or disable TLS" + }, + "root": { + "label": "Root topic", + "description": "MQTT root topic to use for default/custom servers" + }, + "proxyToClientEnabled": { + "label": "MQTT Client Proxy Enabled", + "description": "Utilizes the network connection to proxy MQTT messages to the client." + }, + "mapReportingEnabled": { + "label": "Map Reporting Enabled", + "description": "Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, short and long name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name." + }, + "mapReportSettings": { + "publishIntervalSecs": { + "label": "Map Report Publish Interval (s)", + "description": "Interval in seconds to publish map reports" + }, + "positionPrecision": { + "label": "Approximate Location", + "description": "Position shared will be accurate within this distance", + "options": { + "metric_km23": "Within 23 km", + "metric_km12": "Within 12 km", + "metric_km5_8": "Within 5.8 km", + "metric_km2_9": "Within 2.9 km", + "metric_km1_5": "Within 1.5 km", + "metric_m700": "Within 700 m", + "metric_m350": "Within 350 m", + "metric_m200": "Within 200 m", + "metric_m90": "Within 90 m", + "metric_m50": "Within 50 m", + "imperial_mi15": "Within 15 miles", + "imperial_mi7_3": "Within 7.3 miles", + "imperial_mi3_6": "Within 3.6 miles", + "imperial_mi1_8": "Within 1.8 miles", + "imperial_mi0_9": "Within 0.9 miles", + "imperial_mi0_5": "Within 0.5 miles", + "imperial_mi0_2": "Within 0.2 miles", + "imperial_ft600": "Within 600 feet", + "imperial_ft300": "Within 300 feet", + "imperial_ft150": "Within 150 feet" + } + } + } + }, + "neighborInfo": { + "title": "Neighbor Info Settings", + "description": "Settings for the Neighbor Info module", + "enabled": { + "label": "Włączony", + "description": "Enable or disable Neighbor Info Module" + }, + "updateInterval": { + "label": "Update Interval", + "description": "Interval in seconds of how often we should try to send our Neighbor Info to the mesh" + } + }, + "paxcounter": { + "title": "Paxcounter Settings", + "description": "Settings for the Paxcounter module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Paxcounter" + }, + "paxcounterUpdateInterval": { + "label": "Update Interval (seconds)", + "description": "How long to wait between sending paxcounter packets" + }, + "wifiThreshold": { + "label": "WiFi RSSI Threshold", + "description": "At what WiFi RSSI level should the counter increase. Defaults to -80." + }, + "bleThreshold": { + "label": "BLE RSSI Threshold", + "description": "At what BLE RSSI level should the counter increase. Defaults to -80." + } + }, + "rangeTest": { + "title": "Range Test Settings", + "description": "Settings for the Range Test module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Range Test" + }, + "sender": { + "label": "Message Interval", + "description": "How long to wait between sending test packets" + }, + "save": { + "label": "Save CSV to storage", + "description": "ESP32 Only" + } + }, + "serial": { + "title": "Serial Settings", + "description": "Settings for the Serial module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Serial output" + }, + "echo": { + "label": "Echo", + "description": "Any packets you send will be echoed back to your device" + }, + "rxd": { + "label": "Receive Pin", + "description": "Set the GPIO pin to the RXD pin you have set up." + }, + "txd": { + "label": "Transmit Pin", + "description": "Set the GPIO pin to the TXD pin you have set up." + }, + "baud": { + "label": "Baud Rate", + "description": "The serial baud rate" + }, + "timeout": { + "label": "Limit czasu", + "description": "Seconds to wait before we consider your packet as 'done'" + }, + "mode": { + "label": "Tryb", + "description": "Select Mode" + }, + "overrideConsoleSerialPort": { + "label": "Override Console Serial Port", + "description": "If you have a serial port connected to the console, this will override it." + } + }, + "storeForward": { + "title": "Store & Forward Settings", + "description": "Settings for the Store & Forward module", + "enabled": { + "label": "Module Enabled", + "description": "Enable Store & Forward" + }, + "heartbeat": { + "label": "Heartbeat Enabled", + "description": "Enable Store & Forward heartbeat" + }, + "records": { + "label": "Number of records", + "description": "Number of records to store" + }, + "historyReturnMax": { + "label": "History return max", + "description": "Max number of records to return" + }, + "historyReturnWindow": { + "label": "History return window", + "description": "Max number of records to return" + } + }, + "telemetry": { + "title": "Telemetry Settings", + "description": "Settings for the Telemetry module", + "deviceUpdateInterval": { + "label": "Device Metrics", + "description": "Device metrics update interval (seconds)" + }, + "environmentUpdateInterval": { + "label": "Environment metrics update interval (seconds)", + "description": "" + }, + "environmentMeasurementEnabled": { + "label": "Module Enabled", + "description": "Enable the Environment Telemetry" + }, + "environmentScreenEnabled": { + "label": "Displayed on Screen", + "description": "Show the Telemetry Module on the OLED" + }, + "environmentDisplayFahrenheit": { + "label": "Display Fahrenheit", + "description": "Display temp in Fahrenheit" + }, + "airQualityEnabled": { + "label": "Air Quality Enabled", + "description": "Enable the Air Quality Telemetry" + }, + "airQualityInterval": { + "label": "Air Quality Update Interval", + "description": "How often to send Air Quality data over the mesh" + }, + "powerMeasurementEnabled": { + "label": "Power Measurement Enabled", + "description": "Enable the Power Measurement Telemetry" + }, + "powerUpdateInterval": { + "label": "Power Update Interval", + "description": "How often to send Power data over the mesh" + }, + "powerScreenEnabled": { + "label": "Power Screen Enabled", + "description": "Enable the Power Telemetry Screen" + } + } +} diff --git a/src/i18n/locales/pl-PL/nodes.json b/src/i18n/locales/pl-PL/nodes.json new file mode 100644 index 00000000..7359999d --- /dev/null +++ b/src/i18n/locales/pl-PL/nodes.json @@ -0,0 +1,63 @@ +{ + "nodeDetail": { + "publicKeyEnabled": { + "label": "Public Key Enabled" + }, + "noPublicKey": { + "label": "No Public Key" + }, + "directMessage": { + "label": "Direct Message {{shortName}}" + }, + "favorite": { + "label": "Ulubiony", + "tooltip": "Add or remove this node from your favorites" + }, + "notFavorite": { + "label": "Not a Favorite" + }, + "error": { + "label": "Błąd", + "text": "An error occurred while fetching node details. Please try again later." + }, + "status": { + "heard": "Usłyszano", + "mqtt": "MQTT" + }, + "elevation": { + "label": "Elevation" + }, + "channelUtil": { + "label": "Channel Util" + }, + "airtimeUtil": { + "label": "Airtime Util" + } + }, + "nodesTable": { + "headings": { + "longName": "Long Name", + "connection": "Connection", + "lastHeard": "Last Heard", + "encryption": "Encryption", + "model": "Model", + "macAddress": "MAC Address" + }, + "connectionStatus": { + "direct": "Bezpośrednio", + "away": "away", + "unknown": "-", + "viaMqtt": ", via MQTT" + }, + "lastHeardStatus": { + "never": "Never" + } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" + } +} diff --git a/src/i18n/locales/pl-PL/ui.json b/src/i18n/locales/pl-PL/ui.json new file mode 100644 index 00000000..5be83c39 --- /dev/null +++ b/src/i18n/locales/pl-PL/ui.json @@ -0,0 +1,228 @@ +{ + "navigation": { + "title": "Navigation", + "messages": "Wiadomości", + "map": "Mapa", + "config": "Config", + "radioConfig": "Radio Config", + "moduleConfig": "Module Config", + "channels": "Kanały", + "nodes": "Nodes" + }, + "app": { + "title": "Meshtastic", + "logo": "Meshtastic Logo" + }, + "sidebar": { + "collapseToggle": { + "button": { + "open": "Open sidebar", + "close": "Close sidebar" + } + }, + "deviceInfo": { + "volts": "{{voltage}} volts", + "firmware": { + "title": "Firmware", + "version": "v{{version}}", + "buildDate": "Build date: {{date}}" + }, + "deviceName": { + "title": "Device Name", + "changeName": "Change Device Name", + "placeholder": "Enter device name" + }, + "editDeviceName": "Edit device name" + } + }, + "batteryStatus": { + "charging": "{{level}}% charging", + "pluggedIn": "Plugged in", + "title": "Bateria" + }, + "search": { + "nodes": "Search nodes...", + "channels": "Search channels...", + "commandPalette": "Search commands..." + }, + "toast": { + "positionRequestSent": { + "title": "Position request sent." + }, + "requestingPosition": { + "title": "Requesting position, please wait..." + }, + "sendingTraceroute": { + "title": "Sending Traceroute, please wait..." + }, + "tracerouteSent": { + "title": "Traceroute sent." + }, + "savedChannel": { + "title": "Saved Channel: {{channelName}}" + }, + "messages": { + "pkiEncryption": { + "title": "Chat is using PKI encryption." + }, + "pskEncryption": { + "title": "Chat is using PSK encryption." + } + }, + "configSaveError": { + "title": "Error Saving Config", + "description": "An error occurred while saving the configuration." + }, + "validationError": { + "title": "Config Errors Exist", + "description": "Please fix the configuration errors before saving." + }, + "saveSuccess": { + "title": "Saving Config", + "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + } + }, + "notifications": { + "copied": { + "label": "Copied!" + }, + "copyToClipboard": { + "label": "Copy to clipboard" + }, + "hidePassword": { + "label": "Ukryj hasło" + }, + "showPassword": { + "label": "Pokaż hasło" + }, + "deliveryStatus": { + "delivered": "Delivered", + "failed": "Delivery Failed", + "waiting": "Czekam. . .", + "unknown": "Nieznany" + } + }, + "general": { + "label": "General" + }, + "hardware": { + "label": "Hardware" + }, + "metrics": { + "label": "Metrics" + }, + "role": { + "label": "Rola" + }, + "filter": { + "label": "Filtr" + }, + "advanced": { + "label": "Advanced" + }, + "clearInput": { + "label": "Clear input" + }, + "resetFilters": { + "label": "Reset Filters" + }, + "nodeName": { + "label": "Node name/number", + "placeholder": "Meshtastic 1234" + }, + "airtimeUtilization": { + "label": "Airtime Utilization (%)" + }, + "batteryLevel": { + "label": "Battery level (%)", + "labelText": "Battery level (%): {{value}}" + }, + "batteryVoltage": { + "label": "Battery voltage (V)", + "title": "Napięcie" + }, + "channelUtilization": { + "label": "Channel Utilization (%)" + }, + "hops": { + "direct": "Bezpośrednio", + "label": "Number of hops", + "text": "Number of hops: {{value}}" + }, + "lastHeard": { + "label": "Aktywność", + "labelText": "Last heard: {{value}}", + "nowLabel": "Now" + }, + "snr": { + "label": "SNR (db)" + }, + "favorites": { + "label": "Favorites" + }, + "hide": { + "label": "Hide" + }, + "showOnly": { + "label": "Show Only" + }, + "viaMqtt": { + "label": "Connected via MQTT" + }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, + "language": { + "label": "Język", + "changeLanguage": "Change Language" + }, + "theme": { + "dark": "Ciemny", + "light": "Jasny", + "system": "Automatic", + "changeTheme": "Change Color Scheme" + }, + "errorPage": { + "title": "This is a little embarrassing...", + "description1": "We are really sorry but an error occurred in the web client that caused it to crash.
This is not supposed to happen, and we are working hard to fix it.", + "description2": "The best way to prevent this from happening again to you or anyone else is to report the issue to us.", + "reportInstructions": "Please include the following information in your report:", + "reportSteps": { + "step1": "What you were doing when the error occurred", + "step2": "What you expected to happen", + "step3": "What actually happened", + "step4": "Any other relevant information" + }, + "reportLink": "You can report the issue to our <0>GitHub", + "dashboardLink": "Return to the <0>dashboard", + "detailsSummary": "Error Details", + "errorMessageLabel": "Error message:", + "stackTraceLabel": "Stack trace:", + "fallbackError": "{{error}}" + }, + "footer": { + "text": "Powered by <0>▲ Vercel | Meshtastic® is a registered trademark of Meshtastic LLC. | <1>Legal Information", + "commitSha": "Commit SHA: {{sha}}" + } +} diff --git a/src/i18n/locales/pt-PT/common.json b/src/i18n/locales/pt-PT/common.json index 369852e3..c2d1d592 100644 --- a/src/i18n/locales/pt-PT/common.json +++ b/src/i18n/locales/pt-PT/common.json @@ -24,7 +24,8 @@ "reset": "Redefinir", "save": "Salvar", "scanQr": "Ler código QR", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/pt-PT/dialog.json b/src/i18n/locales/pt-PT/dialog.json index 91c118c9..a584527b 100644 --- a/src/i18n/locales/pt-PT/dialog.json +++ b/src/i18n/locales/pt-PT/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Confirma?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Confirma?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/pt-PT/messages.json b/src/i18n/locales/pt-PT/messages.json index 13cbef08..cd7260a8 100644 --- a/src/i18n/locales/pt-PT/messages.json +++ b/src/i18n/locales/pt-PT/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Enviar" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "Responder" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/pt-PT/nodes.json b/src/i18n/locales/pt-PT/nodes.json index 6d0cd384..f263d4cc 100644 --- a/src/i18n/locales/pt-PT/nodes.json +++ b/src/i18n/locales/pt-PT/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favoritos" + "label": "Favoritos", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Erros", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/pt-PT/ui.json b/src/i18n/locales/pt-PT/ui.json index 05b6bb5e..6e413306 100644 --- a/src/i18n/locales/pt-PT/ui.json +++ b/src/i18n/locales/pt-PT/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filtrar" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Idioma", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/sv-SE/common.json b/src/i18n/locales/sv-SE/common.json index c3dae4e5..997064ee 100644 --- a/src/i18n/locales/sv-SE/common.json +++ b/src/i18n/locales/sv-SE/common.json @@ -24,7 +24,8 @@ "reset": "Nollställ", "save": "Spara", "scanQr": "Skanna QR-kod", - "traceRoute": "Spåra rutt" + "traceRoute": "Spåra rutt", + "submit": "Spara" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "minut", "plural": "minuter" }, + "hour": { + "one": "Timme", + "plural": "Timmar" + }, "millisecond": { "one": "millisekund", "plural": "millisekunder", @@ -64,6 +69,18 @@ "one": "sekund", "plural": "sekunder" }, + "day": { + "one": "Dag", + "plural": "Dagar" + }, + "month": { + "one": "Månad", + "plural": "Månader" + }, + "year": { + "one": "År", + "plural": "År" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Tom", + "8bit": "8 bitar", + "128bit": "128 bitar", "256bit": "256 bitar" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "EJ SATT", "fallbackName": "Meshtastic {{last4}}", + "node": "Nod", "formValidation": { + "unsavedChanges": "Osparade ändringar", "tooBig": { "string": "Texten är för lång. Ange en text mindre än eller lika med {{maximum}} tecken långt.", "number": "Värdet är för stort. Ange ett numeriskt värde mindre än eller lika med {{maximum}}.", diff --git a/src/i18n/locales/sv-SE/dashboard.json b/src/i18n/locales/sv-SE/dashboard.json index 69c12fff..f9ac6a24 100644 --- a/src/i18n/locales/sv-SE/dashboard.json +++ b/src/i18n/locales/sv-SE/dashboard.json @@ -5,7 +5,7 @@ "connectionType_ble": "BLE", "connectionType_serial": "Seriell kommunikation", "connectionType_network": "Nätverk", - "noDevicesTitle": "Inga enheter anslutna", + "noDevicesTitle": "Inga anslutna enheter ", "noDevicesDescription": "Anslut en ny enhet för att komma igång.", "button_newConnection": "Ny anslutning" } diff --git a/src/i18n/locales/sv-SE/dialog.json b/src/i18n/locales/sv-SE/dialog.json index 1a256bb5..0ed123b8 100644 --- a/src/i18n/locales/sv-SE/dialog.json +++ b/src/i18n/locales/sv-SE/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "Ny enhet" }, "validation": { - "requiresFeatures": "Den här anslutningstypen kräver <0>. Använd en webbläsare som stöds, till exempel Chrome eller Edge.", + "requiresWebBluetooth": "Den här anslutningstypen kräver <0>Web Bluetooth. Använd en webbläsare som stöds, till exempel Chrome eller Edge.", + "requiresWebSerial": "Den här anslutningstypen kräver <0>Web Serial. Använd en webbläsare som stöds, till exempel Chrome eller Edge.", "requiresSecureContext": "Denna applikation kräver en <0>säker kontext. Anslut med HTTPS eller localhost.", "additionallyRequiresSecureContext": "Dessutom kräver den ett <0>säker kontext. Vänligen anslut med HTTPS eller localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Ta bort favoritmarkering" }, "pkiBackup": { - "description": "Vi rekommenderar att du säkerhetskopierar dina nycklar regelbundet. Vill du säkerhetskopiera nu?", "loseKeysWarning": "Om du förlorar dina nycklar måste du återställa din enhet.", "secureBackup": "Det är viktigt att säkerhetskopiera dina publika och privata nycklar och förvara din säkerhetskopia säkert.", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Säkerhetskopiera nycklar" }, + "pkiBackupReminder": { + "description": "Vi rekommenderar att du säkerhetskopierar dina nycklar regelbundet. Vill du säkerhetskopiera nu?", + "title": "Påminnelse om säkerhetskopiering", + "remindLaterPrefix": "Påminn mig om", + "remindNever": "Påminn mig aldrig", + "backupNow": "Säkerhetskopiera nu" + }, "pkiRegenerate": { "description": "Är du säker på att du vill förnya nyckelpar?", "title": "Förnya nyckelpar" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Att välja rätt enhetsroll", "deviceRoleDocumentation": "Dokumentation för enhetsroll", "title": "Är du säker?" + }, + "managedMode": { + "confirmUnderstanding": "Ja, jag vet vad jag gör", + "title": "Är du säker?", + "description": "Aktivering av fjärrhanterat läge blockerar klienter (inklusive webbklienten) från att skriva inställningar till en radio. När detta är aktiverat kan enhetens inställningar endast ändras via fjärradministratörsmeddelanden. Den här inställningen krävs inte för fjärradministration." } } diff --git a/src/i18n/locales/sv-SE/messages.json b/src/i18n/locales/sv-SE/messages.json index ae25ae8d..203b600f 100644 --- a/src/i18n/locales/sv-SE/messages.json +++ b/src/i18n/locales/sv-SE/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Meddelanden: {{chatName}}" + "title": "Meddelanden: {{chatName}}", + "placeholder": "Ange meddelande" }, "emptyState": { "title": "Välj en chatt", @@ -10,31 +11,29 @@ "text": "Välj en kanal eller nod för att börja chatta." }, "sendMessage": { - "placeholder": "Skriv ditt meddelande här...", + "placeholder": "Ange ditt meddelande här...", "sendButton": "Skicka" }, "actionsMenu": { "addReactionLabel": "Lägg till reaktion", "replyLabel": "Svara" }, - "item": { - "status": { - "delivered": { - "label": "Meddelandet har levererats", - "displayText": "Meddelandet har levererats" - }, - "failed": { - "label": "Meddelandeleverans misslyckades", - "displayText": "Leverans misslyckades" - }, - "unknown": { - "label": "Okänd meddelandestatus", - "displayText": "Okänd status" - }, - "waiting": { - "ariaLabel": "Skickar meddelande", - "displayText": "Väntar på leverans" - } + "deliveryStatus": { + "delivered": { + "label": "Meddelandet har levererats", + "displayText": "Meddelandet har levererats" + }, + "failed": { + "label": "Meddelandeleverans misslyckades", + "displayText": "Leverans misslyckades" + }, + "unknown": { + "label": "Okänd meddelandestatus", + "displayText": "Okänd status" + }, + "waiting": { + "label": "Skickar meddelande", + "displayText": "Väntar på leverans" } } } diff --git a/src/i18n/locales/sv-SE/nodes.json b/src/i18n/locales/sv-SE/nodes.json index 57a5bafa..97855c4c 100644 --- a/src/i18n/locales/sv-SE/nodes.json +++ b/src/i18n/locales/sv-SE/nodes.json @@ -10,11 +10,16 @@ "label": "Direktmeddelande {{shortName}}" }, "favorite": { - "label": "Favorit" + "label": "Favorit", + "tooltip": "Lägg till eller ta bort den här noden från dina favoriter" }, "notFavorite": { "label": "Inte en favorit" }, + "error": { + "label": "Fel", + "text": "Ett fel inträffade vid hämtning av nodens detaljer. Försök igen senare." + }, "status": { "heard": "Hörd", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Aldrig" } + }, + "actions": { + "added": "Tillagd", + "removed": "Borttagen", + "ignoreNode": "Ignorera nod", + "unignoreNode": "Ta bort ignorering", + "requestPosition": "Begär plats" } } diff --git a/src/i18n/locales/sv-SE/ui.json b/src/i18n/locales/sv-SE/ui.json index 50044c1f..dee4cf1e 100644 --- a/src/i18n/locales/sv-SE/ui.json +++ b/src/i18n/locales/sv-SE/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Sparar inställningarna", "description": "Ändrignarna av {{case}}-inställningarna har sparats." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} dina favoriter.", + "action": { + "added": "La till", + "removed": "Tog bort", + "to": "till", + "from": "från" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} dina ignorerade noder", + "action": { + "added": "La till", + "removed": "Tog bort", + "to": "till", + "from": "från" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filter" }, + "advanced": { + "label": "Advancerat" + }, "clearInput": { "label": "Rensa inmatning" }, @@ -166,9 +187,15 @@ "viaMqtt": { "label": "Ansluten via MQTT" }, + "hopsUnknown": { + "label": "Okänt antal hopp" + }, + "showUnheard": { + "label": "Aldrig hörd" + }, "language": { "label": "Språk", - "changeLanguage": "Ändra språk" + "changeLanguage": "Byt språk" }, "theme": { "dark": "Mörkt", diff --git a/src/i18n/locales/tr-TR/common.json b/src/i18n/locales/tr-TR/common.json index 52768d33..3fab7218 100644 --- a/src/i18n/locales/tr-TR/common.json +++ b/src/i18n/locales/tr-TR/common.json @@ -24,7 +24,8 @@ "reset": "Sıfırla", "save": "Kaydet", "scanQr": "QR Kodu Tara", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "Hour", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/tr-TR/dialog.json b/src/i18n/locales/tr-TR/dialog.json index 2419a70d..1ba90500 100644 --- a/src/i18n/locales/tr-TR/dialog.json +++ b/src/i18n/locales/tr-TR/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "Emin misiniz?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "Emin misiniz?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/tr-TR/messages.json b/src/i18n/locales/tr-TR/messages.json index ebfacb84..7bdb2d22 100644 --- a/src/i18n/locales/tr-TR/messages.json +++ b/src/i18n/locales/tr-TR/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "Gönder" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "Reply" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/tr-TR/nodes.json b/src/i18n/locales/tr-TR/nodes.json index 38af1597..04a314a1 100644 --- a/src/i18n/locales/tr-TR/nodes.json +++ b/src/i18n/locales/tr-TR/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favori" + "label": "Favori", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Hata", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "Ignore Node", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/tr-TR/ui.json b/src/i18n/locales/tr-TR/ui.json index 6b59b9ab..efbdbfb6 100644 --- a/src/i18n/locales/tr-TR/ui.json +++ b/src/i18n/locales/tr-TR/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "Filtre" }, + "advanced": { + "label": "Advanced" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Dil", "changeLanguage": "Change Language" diff --git a/src/i18n/locales/uk-UA/channels.json b/src/i18n/locales/uk-UA/channels.json index 5e74e00a..8eabfa03 100644 --- a/src/i18n/locales/uk-UA/channels.json +++ b/src/i18n/locales/uk-UA/channels.json @@ -1,9 +1,9 @@ { "page": { - "sectionLabel": "Channels", - "channelName": "Channel: {{channelName}}", - "broadcastLabel": "Primary", - "channelIndex": "Ch {{index}}" + "sectionLabel": "Канали", + "channelName": "Канал: {{channelName}}", + "broadcastLabel": "Основний", + "channelIndex": "Кн {{index}}" }, "validation": { "pskInvalid": "Please enter a valid {{bits}} bit PSK." @@ -13,7 +13,7 @@ "description": "Crypto, MQTT & misc settings" }, "role": { - "label": "Role", + "label": "Роль", "description": "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", "options": { "primary": "PRIMARY", @@ -24,7 +24,7 @@ "psk": { "label": "Pre-Shared Key", "description": "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - "generate": "Generate" + "generate": "Згенерувати" }, "name": { "label": "Ім'я", @@ -39,31 +39,31 @@ "description": "Send messages from MQTT to the local mesh" }, "positionPrecision": { - "label": "Location", + "label": "Місце розташування", "description": "The precision of the location to share with the channel. Can be disabled.", "options": { - "none": "Do not share location", - "precise": "Precise Location", - "metric_km23": "Within 23 kilometers", - "metric_km12": "Within 12 kilometers", - "metric_km5_8": "Within 5.8 kilometers", - "metric_km2_9": "Within 2.9 kilometers", - "metric_km1_5": "Within 1.5 kilometers", - "metric_m700": "Within 700 meters", - "metric_m350": "Within 350 meters", - "metric_m200": "Within 200 meters", - "metric_m90": "Within 90 meters", - "metric_m50": "Within 50 meters", - "imperial_mi15": "Within 15 miles", - "imperial_mi7_3": "Within 7.3 miles", - "imperial_mi3_6": "Within 3.6 miles", - "imperial_mi1_8": "Within 1.8 miles", - "imperial_mi0_9": "Within 0.9 miles", - "imperial_mi0_5": "Within 0.5 miles", - "imperial_mi0_2": "Within 0.2 miles", - "imperial_ft600": "Within 600 feet", - "imperial_ft300": "Within 300 feet", - "imperial_ft150": "Within 150 feet" + "none": "Не повідомляти місце знаходження", + "precise": "Точне місце розташування", + "metric_km23": "У межах 23 км", + "metric_km12": "У межах 12 км", + "metric_km5_8": "У межах 5,8 км", + "metric_km2_9": "У межах 2,9 км", + "metric_km1_5": "У межах 1,5 км", + "metric_m700": "У межах 700 м", + "metric_m350": "У межах 350 м", + "metric_m200": "У межах 200 м", + "metric_m90": "У межах 90 м", + "metric_m50": "У межах 50 м", + "imperial_mi15": "У межах 15 миль", + "imperial_mi7_3": "У межах 7,3 милі", + "imperial_mi3_6": "У межах 3,6 милі", + "imperial_mi1_8": "У межах 1,8 милі", + "imperial_mi0_9": "У межах 0,9 милі", + "imperial_mi0_5": "У межах 0,5 милі", + "imperial_mi0_2": "У межах 0,2 милі", + "imperial_ft600": "У межах 600 фт", + "imperial_ft300": "У межах 300 фт", + "imperial_ft150": "У межах 150 фт" } } } diff --git a/src/i18n/locales/uk-UA/commandPalette.json b/src/i18n/locales/uk-UA/commandPalette.json index 42dac9c8..c04c4fa5 100644 --- a/src/i18n/locales/uk-UA/commandPalette.json +++ b/src/i18n/locales/uk-UA/commandPalette.json @@ -15,8 +15,8 @@ "messages": "Повідомлення", "map": "Мапа", "config": "Config", - "channels": "Channels", - "nodes": "Nodes" + "channels": "Канали", + "nodes": "Вузли" } }, "manage": { @@ -29,11 +29,11 @@ "contextual": { "label": "Contextual", "command": { - "qrCode": "QR Code", - "qrGenerator": "Generator", + "qrCode": "QR-код", + "qrGenerator": "Генератор", "qrImport": "Import", - "scheduleShutdown": "Schedule Shutdown", - "scheduleReboot": "Schedule Reboot", + "scheduleShutdown": "Розклад вимкнення", + "scheduleReboot": "Розклад перезавантаження", "rebootToOtaMode": "Reboot To OTA Mode", "resetNodeDb": "Reset Node DB", "factoryResetDevice": "Factory Reset Device", diff --git a/src/i18n/locales/uk-UA/common.json b/src/i18n/locales/uk-UA/common.json index 2ad86595..02667ac1 100644 --- a/src/i18n/locales/uk-UA/common.json +++ b/src/i18n/locales/uk-UA/common.json @@ -24,17 +24,18 @@ "reset": "Скинути", "save": "Зберегти", "scanQr": "Scan QR Code", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", "fullTitle": "Meshtastic Web Client" }, - "loading": "Loading...", + "loading": "Завантаження...", "unit": { "cps": "CPS", - "dbm": "dBm", - "hertz": "Hz", + "dbm": "дБм", + "hertz": "Гц", "hop": { "one": "Hop", "plural": "Hops" @@ -44,29 +45,45 @@ "plural": "{{count}} hops away", "unknown": "Unknown hops away" }, - "megahertz": "MHz", + "megahertz": "МГц", "raw": "raw", "meter": { - "one": "Meter", + "one": "Метр", "plural": "Meters", - "suffix": "m" + "suffix": "м" }, "minute": { "one": "Minute", - "plural": "Minutes" + "plural": "Хвилин" + }, + "hour": { + "one": "Година", + "plural": "Годин" }, "millisecond": { - "one": "Millisecond", - "plural": "Milliseconds", - "suffix": "ms" + "one": "Мілісекунда", + "plural": "Мілісекунди", + "suffix": "мс" }, "second": { - "one": "Second", - "plural": "Seconds" + "one": "Секунда", + "plural": "Секунд" + }, + "day": { + "one": "День", + "plural": "Днів" + }, + "month": { + "one": "Місяць", + "plural": "Місяців" + }, + "year": { + "one": "Year", + "plural": "Years" }, "snr": "SNR", "volt": { - "one": "Volt", + "one": "Вольт", "plural": "Volts", "suffix": "V" }, @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "Empty", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", @@ -98,20 +120,20 @@ "number": "Too small, expected a number larger than or equal to {{minimum}}." }, "invalidFormat": { - "ipv4": "Invalid format, expected an IPv4 address.", + "ipv4": "Невірний формат, потрібна IPv4-адреса.", "key": "Invalid format, expected a Base64 encoded pre-shared key (PSK)." }, "invalidType": { "number": "Invalid type, expected a number." }, "pskLength": { - "0bit": "Key is required to be empty.", + "0bit": "Ключ повинен бути пустим.", "8bit": "Key is required to be an 8 bit pre-shared key (PSK).", "128bit": "Key is required to be a 128 bit pre-shared key (PSK).", "256bit": "Key is required to be a 256 bit pre-shared key (PSK)." }, "required": { - "generic": "This field is required.", + "generic": "Це поле є обов'язковим.", "managed": "At least one admin key is requred if the node is managed.", "key": "Key is required." } diff --git a/src/i18n/locales/uk-UA/dashboard.json b/src/i18n/locales/uk-UA/dashboard.json index 3a3cd869..4fad3e69 100644 --- a/src/i18n/locales/uk-UA/dashboard.json +++ b/src/i18n/locales/uk-UA/dashboard.json @@ -3,8 +3,8 @@ "title": "Connected Devices", "description": "Manage your connected Meshtastic devices.", "connectionType_ble": "BLE", - "connectionType_serial": "Serial", - "connectionType_network": "Network", + "connectionType_serial": "Серійний порт", + "connectionType_network": "Мережа", "noDevicesTitle": "No devices connected", "noDevicesDescription": "Connect a new device to get started.", "button_newConnection": "New Connection" diff --git a/src/i18n/locales/uk-UA/deviceConfig.json b/src/i18n/locales/uk-UA/deviceConfig.json index a5619c72..0de85c36 100644 --- a/src/i18n/locales/uk-UA/deviceConfig.json +++ b/src/i18n/locales/uk-UA/deviceConfig.json @@ -1,20 +1,20 @@ { "page": { - "title": "Configuration", + "title": "Налаштування", "tabBluetooth": "Bluetooth", - "tabDevice": "Device", - "tabDisplay": "Display", + "tabDevice": "Пристрій", + "tabDisplay": "Дисплей", "tabLora": "LoRa", - "tabNetwork": "Network", + "tabNetwork": "Мережа", "tabPosition": "Position", - "tabPower": "Power", - "tabSecurity": "Security" + "tabPower": "Живлення", + "tabSecurity": "Безпека" }, "sidebar": { - "label": "Modules" + "label": "Модулі" }, "device": { - "title": "Device Settings", + "title": "Налаштування пристрою", "description": "Settings for the device", "buttonPin": { "description": "Button pin override", @@ -54,12 +54,12 @@ } }, "bluetooth": { - "title": "Bluetooth Settings", + "title": "Налаштування Bluetooth", "description": "Settings for the Bluetooth module", "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", "enabled": { - "description": "Enable or disable Bluetooth", - "label": "Enabled" + "description": "Увімкнути або вимкнути Bluetooth", + "label": "Увімкнено" }, "pairingMode": { "description": "Pin selection behaviour.", @@ -147,7 +147,7 @@ }, "ignoreMqtt": { "description": "Don't forward MQTT messages over the mesh", - "label": "Ignore MQTT" + "label": "Ігнорувати MQTT" }, "modemPreset": { "description": "Modem preset to use", @@ -199,7 +199,7 @@ } }, "network": { - "title": "WiFi Config", + "title": "Налаштування WiFi", "description": "WiFi radio configuration", "note": "Note: Some devices (ESP32) cannot use both Bluetooth and WiFi at the same time.", "addressMode": { @@ -207,7 +207,7 @@ "label": "Address Mode" }, "dns": { - "description": "DNS Server", + "description": "DNS-сервер", "label": "DNS" }, "ethernetEnabled": { @@ -216,7 +216,7 @@ }, "gateway": { "description": "Default Gateway", - "label": "Gateway" + "label": "Шлюз" }, "ip": { "description": "IP Address", @@ -231,21 +231,21 @@ "label": "SSID" }, "subnet": { - "description": "Subnet Mask", - "label": "Subnet" + "description": "Маска підмережі", + "label": "Підмережа" }, "wifiEnabled": { - "description": "Enable or disable the WiFi radio", + "description": "Увімкнути або вимкнути WiFi радіо", "label": "Enabled" }, "meshViaUdp": { "label": "Mesh via UDP" }, "ntpServer": { - "label": "NTP Server" + "label": "NTP-сервер" }, "rsyslogServer": { - "label": "Rsyslog Server" + "label": "Rsyslog-сервер" }, "ethernetConfigSettings": { "description": "Ethernet port configuration", @@ -256,16 +256,16 @@ "label": "IP Config" }, "ntpConfigSettings": { - "description": "NTP configuration", + "description": "Налаштування NTP", "label": "NTP Config" }, "rsyslogConfigSettings": { "description": "Rsyslog configuration", - "label": "Rsyslog Config" + "label": "Налаштування Rsyslog" }, "udpConfigSettings": { "description": "UDP over Mesh configuration", - "label": "UDP Config" + "label": "Налаштування UDP" } }, "position": { @@ -321,7 +321,7 @@ }, "flags": { "placeholder": "Select position flags...", - "altitude": "Altitude", + "altitude": "Висота", "altitudeGeoidalSeparation": "Altitude Geoidal Separation", "altitudeMsl": "Altitude is Mean Sea Level", "dop": "Dilution of precision (DOP) PDOP used by default", @@ -369,16 +369,16 @@ }, "powerConfigSettings": { "description": "Settings for the power module", - "label": "Power Config" + "label": "Налаштування живлення" }, "sleepSettings": { "description": "Sleep settings for the power module", - "label": "Sleep Settings" + "label": "Налаштування режиму сну" } }, "security": { "description": "Settings for the Security configuration", - "title": "Security Settings", + "title": "Налаштування безпеки", "button_backupKey": "Backup Key", "adminChannelEnabled": { "description": "Allow incoming device control over the insecure legacy admin channel", diff --git a/src/i18n/locales/uk-UA/dialog.json b/src/i18n/locales/uk-UA/dialog.json index deb2c712..20bdd125 100644 --- a/src/i18n/locales/uk-UA/dialog.json +++ b/src/i18n/locales/uk-UA/dialog.json @@ -1,34 +1,34 @@ { "deleteMessages": { "description": "This action will clear all message history. This cannot be undone. Are you sure you want to continue?", - "title": "Clear All Messages" + "title": "Очистити всі повідомлення" }, "deviceName": { "description": "The Device will restart once the config is saved.", - "longName": "Long Name", - "shortName": "Short Name", - "title": "Change Device Name" + "longName": "Довга назва", + "shortName": "Коротка назва", + "title": "Змінити назву пристрою" }, "import": { "description": "The current LoRa configuration will be overridden.", "error": { "invalidUrl": "Invalid Meshtastic URL" }, - "channelPrefix": "Channel: ", + "channelPrefix": "Канал: ", "channelSetUrl": "Channel Set/QR Code URL", - "channels": "Channels:", + "channels": "Канали:", "usePreset": "Use Preset?", "title": "Import Channel Set" }, "locationResponse": { - "altitude": "Altitude: ", - "coordinates": "Coordinates: ", - "title": "Location: {{identifier}}" + "altitude": "Висота: ", + "coordinates": "Координати: ", + "title": "Розташування: {{identifier}}" }, "pkiRegenerateDialog": { "title": "Regenerate Pre-Shared Key?", "description": "Are you sure you want to regenerate the pre-shared key?", - "regenerate": "Regenerate" + "regenerate": "Перегенерувати" }, "newDeviceDialog": { "title": "Connect New Device", @@ -37,8 +37,8 @@ "tabHttp": "HTTP", "tabBluetooth": "Bluetooth", "tabSerial": "Serial", - "useHttps": "Use HTTPS", - "connecting": "Connecting...", + "useHttps": "Використовувати HTTPS", + "connecting": "Підключення...", "connect": "Connect", "connectionFailedAlert": { "title": "Connection Failed", @@ -60,10 +60,11 @@ }, "bluetoothConnection": { "noDevicesPaired": "No devices paired yet.", - "newDeviceButton": "New device" + "newDeviceButton": "Новий пристрій" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -111,16 +118,16 @@ "replaceChannels": "Replace Channels", "description": "The current LoRa configuration will also be shared.", "sharableUrl": "Sharable URL", - "title": "Generate QR Code" + "title": "Згенерувати QR-код" }, "rebootOta": { - "title": "Schedule Reboot", + "title": "Запланувати перезавантаження", "description": "Reboot the connected node after a delay into OTA (Over-the-Air) mode.", - "enterDelay": "Enter delay (sec)", + "enterDelay": "Введіть затримку (сек)", "scheduled": "Reboot has been scheduled" }, "reboot": { - "title": "Schedule Reboot", + "title": "Запланувати перезавантаження", "description": "Reboot the connected node after x minutes." }, "refreshKeys": { @@ -154,6 +161,11 @@ "preamble": "I have read the ", "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", - "title": "Are you sure?" + "title": "Ви впевнені?" + }, + "managedMode": { + "confirmUnderstanding": "Я знаю, що роблю", + "title": "Ви впевнені?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/uk-UA/messages.json b/src/i18n/locales/uk-UA/messages.json index 90e2d3b3..0500adb8 100644 --- a/src/i18n/locales/uk-UA/messages.json +++ b/src/i18n/locales/uk-UA/messages.json @@ -1,40 +1,39 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Повідомлення: {{chatName}}", + "placeholder": "Введіть повідомлення" }, "emptyState": { - "title": "Select a Chat", - "text": "No messages yet." + "title": "Оберіть чат", + "text": "Поки немає повідомлень." }, "selectChatPrompt": { - "text": "Select a channel or node to start messaging." + "text": "Виберіть канал або вузол для початку обміну повідомленнями." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Введіть ваше повідомлення тут...", "sendButton": "Надіслати" }, "actionsMenu": { - "addReactionLabel": "Add Reaction", - "replyLabel": "Reply" + "addReactionLabel": "Додати реакцію", + "replyLabel": "Відповісти" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Повідомлення доставлено", + "displayText": "Повідомлення доставлено" + }, + "failed": { + "label": "Помилка доставлення повідомлення", + "displayText": "Надсилання не відбулося" + }, + "unknown": { + "label": "Статус повідомлення невідомий", + "displayText": "Невідомий стан" + }, + "waiting": { + "label": "Надсилання повідомлення", + "displayText": "Очікування доставки" } } } diff --git a/src/i18n/locales/uk-UA/moduleConfig.json b/src/i18n/locales/uk-UA/moduleConfig.json index caacbe17..89074e3d 100644 --- a/src/i18n/locales/uk-UA/moduleConfig.json +++ b/src/i18n/locales/uk-UA/moduleConfig.json @@ -1,17 +1,17 @@ { "page": { "tabAmbientLighting": "Ambient Lighting", - "tabAudio": "Audio", + "tabAudio": "Аудіо", "tabCannedMessage": "Canned", "tabDetectionSensor": "Detection Sensor", "tabExternalNotification": "Ext Notif", "tabMqtt": "MQTT", "tabNeighborInfo": "Neighbor Info", "tabPaxcounter": "Paxcounter", - "tabRangeTest": "Range Test", + "tabRangeTest": "Тест дальності", "tabSerial": "Serial", "tabStoreAndForward": "S&F", - "tabTelemetry": "Telemetry" + "tabTelemetry": "Телеметрія" }, "ambientLighting": { "title": "Ambient Lighting Settings", @@ -25,15 +25,15 @@ "description": "Sets the current for the LED output. Default is 10" }, "red": { - "label": "Red", + "label": "Червоний", "description": "Sets the red LED level. Values are 0-255" }, "green": { - "label": "Green", + "label": "Зелений", "description": "Sets the green LED level. Values are 0-255" }, "blue": { - "label": "Blue", + "label": "Синій", "description": "Sets the blue LED level. Values are 0-255" } }, @@ -218,7 +218,7 @@ } }, "mqtt": { - "title": "MQTT Settings", + "title": "Налаштування MQTT", "description": "Settings for the MQTT module", "enabled": { "label": "Enabled", @@ -229,11 +229,11 @@ "description": "MQTT server address to use for default/custom servers" }, "username": { - "label": "MQTT Username", + "label": "Ім'я користувача MQTT", "description": "MQTT username to use for default/custom servers" }, "password": { - "label": "MQTT Password", + "label": "Пароль MQTT", "description": "MQTT password to use for default/custom servers" }, "encryptionEnabled": { diff --git a/src/i18n/locales/uk-UA/nodes.json b/src/i18n/locales/uk-UA/nodes.json index 5202f039..f0ca01bc 100644 --- a/src/i18n/locales/uk-UA/nodes.json +++ b/src/i18n/locales/uk-UA/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "Favorite" + "label": "Favorite", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "Помилка", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "Heard", "mqtt": "MQTT" @@ -31,21 +36,28 @@ }, "nodesTable": { "headings": { - "longName": "Long Name", + "longName": "Довга назва", "connection": "Connection", "lastHeard": "Last Heard", - "encryption": "Encryption", + "encryption": "Шифрування", "model": "Model", - "macAddress": "MAC Address" + "macAddress": "MAC-адреса" }, "connectionStatus": { "direct": "Direct", "away": "away", "unknown": "-", - "viaMqtt": ", via MQTT" + "viaMqtt": ", через MQTT" }, "lastHeardStatus": { - "never": "Never" + "never": "Ніколи" } + }, + "actions": { + "added": "Додано", + "removed": "Видалено", + "ignoreNode": "Ігнорувати вузол", + "unignoreNode": "Unignore Node", + "requestPosition": "Запитати позицію" } } diff --git a/src/i18n/locales/uk-UA/ui.json b/src/i18n/locales/uk-UA/ui.json index e9f80e00..92c8b4b3 100644 --- a/src/i18n/locales/uk-UA/ui.json +++ b/src/i18n/locales/uk-UA/ui.json @@ -1,29 +1,29 @@ { "navigation": { - "title": "Navigation", + "title": "Навігація", "messages": "Повідомлення", "map": "Мапа", "config": "Config", - "radioConfig": "Radio Config", + "radioConfig": "Налаштування радіо", "moduleConfig": "Module Config", - "channels": "Channels", - "nodes": "Nodes" + "channels": "Канали", + "nodes": "Вузли" }, "app": { "title": "Meshtastic", - "logo": "Meshtastic Logo" + "logo": "Логотип Meshtastic" }, "sidebar": { "collapseToggle": { "button": { - "open": "Open sidebar", - "close": "Close sidebar" + "open": "Відкрити бічну панель", + "close": "Закрити бічну панель" } }, "deviceInfo": { - "volts": "{{voltage}} volts", + "volts": "{{voltage}} Вольт", "firmware": { - "title": "Firmware", + "title": "Прошивка", "version": "v{{version}}", "buildDate": "Build date: {{date}}" }, @@ -38,7 +38,7 @@ "batteryStatus": { "charging": "{{level}}% charging", "pluggedIn": "Plugged in", - "title": "Battery" + "title": "Батарея" }, "search": { "nodes": "Search nodes...", @@ -80,11 +80,29 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Додано", + "removed": "Видалено", + "to": "до", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Додано", + "removed": "Видалено", + "to": "до", + "from": "from" + } } }, "notifications": { "copied": { - "label": "Copied!" + "label": "Скопійовано!" }, "copyToClipboard": { "label": "Copy to clipboard" @@ -96,9 +114,9 @@ "label": "Show password" }, "deliveryStatus": { - "delivered": "Delivered", + "delivered": "Доставлено", "failed": "Delivery Failed", - "waiting": "Waiting", + "waiting": "Очікування", "unknown": "Unknown" } }, @@ -109,7 +127,7 @@ "label": "Hardware" }, "metrics": { - "label": "Metrics" + "label": "Метрики" }, "role": { "label": "Role" @@ -117,6 +135,9 @@ "filter": { "label": "Фільтри" }, + "advanced": { + "label": "Розширені" + }, "clearInput": { "label": "Clear input" }, @@ -136,7 +157,7 @@ }, "batteryVoltage": { "label": "Battery voltage (V)", - "title": "Voltage" + "title": "Напруга" }, "channelUtilization": { "label": "Channel Utilization (%)" @@ -149,16 +170,16 @@ "lastHeard": { "label": "Last heard", "labelText": "Last heard: {{value}}", - "nowLabel": "Now" + "nowLabel": "Зараз" }, "snr": { - "label": "SNR (db)" + "label": "SNR (дБ)" }, "favorites": { "label": "Favorites" }, "hide": { - "label": "Hide" + "label": "Сховати" }, "showOnly": { "label": "Show Only" @@ -166,15 +187,21 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "Мова", - "changeLanguage": "Change Language" + "changeLanguage": "Змінити мову" }, "theme": { "dark": "Темна", "light": "Світла", "system": "Automatic", - "changeTheme": "Change Color Scheme" + "changeTheme": "Змінити схему кольорів" }, "errorPage": { "title": "This is a little embarrassing...", @@ -189,8 +216,8 @@ }, "reportLink": "You can report the issue to our <0>GitHub", "dashboardLink": "Return to the <0>dashboard", - "detailsSummary": "Error Details", - "errorMessageLabel": "Error message:", + "detailsSummary": "Інформація про помилку", + "errorMessageLabel": "Помилка:", "stackTraceLabel": "Stack trace:", "fallbackError": "{{error}}" }, diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index d5c38965..0498cc54 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -24,7 +24,8 @@ "reset": "重置", "save": "保存", "scanQr": "扫描二维码", - "traceRoute": "Trace Route" + "traceRoute": "Trace Route", + "submit": "Submit" }, "app": { "title": "Meshtastic", @@ -55,6 +56,10 @@ "one": "Minute", "plural": "Minutes" }, + "hour": { + "one": "小时", + "plural": "Hours" + }, "millisecond": { "one": "Millisecond", "plural": "Milliseconds", @@ -64,6 +69,18 @@ "one": "Second", "plural": "Seconds" }, + "day": { + "one": "Day", + "plural": "Days" + }, + "month": { + "one": "Month", + "plural": "Months" + }, + "year": { + "one": "Year", + "plural": "Years" + }, "snr": "SNR", "volt": { "one": "Volt", @@ -76,6 +93,9 @@ } }, "security": { + "0bit": "空", + "8bit": "8 bit", + "128bit": "128 bit", "256bit": "256 bit" }, "unknown": { @@ -87,7 +107,9 @@ "nodeUnknownPrefix": "!", "unset": "UNSET", "fallbackName": "Meshtastic {{last4}}", + "node": "Node", "formValidation": { + "unsavedChanges": "Unsaved changes", "tooBig": { "string": "Too long, expected less than or equal to {{maximum}} characters.", "number": "Too big, expected a number smaller than or equal to {{maximum}}.", diff --git a/src/i18n/locales/zh-CN/dialog.json b/src/i18n/locales/zh-CN/dialog.json index fc2afbb7..f3203783 100644 --- a/src/i18n/locales/zh-CN/dialog.json +++ b/src/i18n/locales/zh-CN/dialog.json @@ -63,7 +63,8 @@ "newDeviceButton": "New device" }, "validation": { - "requiresFeatures": "This connection type requires <0>. Please use a supported browser, like Chrome or Edge.", + "requiresWebBluetooth": "This connection type requires <0>Web Bluetooth. Please use a supported browser, like Chrome or Edge.", + "requiresWebSerial": "This connection type requires <0>Web Serial. Please use a supported browser, like Chrome or Edge.", "requiresSecureContext": "This application requires a <0>secure context. Please connect using HTTPS or localhost.", "additionallyRequiresSecureContext": "Additionally, it requires a <0>secure context. Please connect using HTTPS or localhost." } @@ -92,7 +93,6 @@ "unignoreNode": "Unignore node" }, "pkiBackup": { - "description": "We recommend backing up your key data regularly. Would you like to back up now?", "loseKeysWarning": "If you lose your keys, you will need to reset your device.", "secureBackup": "Its important to backup your public and private keys and store your backup securely!", "footer": "=== END OF KEYS ===", @@ -102,6 +102,13 @@ "fileName": "meshtastic_keys_{{longName}}_{{shortName}}.txt", "title": "Backup Keys" }, + "pkiBackupReminder": { + "description": "We recommend backing up your key data regularly. Would you like to back up now?", + "title": "Backup Reminder", + "remindLaterPrefix": "Remind me in", + "remindNever": "Never remind me", + "backupNow": "Back up now" + }, "pkiRegenerate": { "description": "Are you sure you want to regenerate key pair?", "title": "Regenerate Key Pair" @@ -155,5 +162,10 @@ "choosingRightDeviceRole": "Choosing The Right Device Role", "deviceRoleDocumentation": "Device Role Documentation", "title": "是否确认?" + }, + "managedMode": { + "confirmUnderstanding": "Yes, I know what I'm doing", + "title": "是否确认?", + "description": "Enabling Managed Mode blocks client applications (including the web client) from writing configurations to a radio. Once enabled, radio configurations can only be changed through Remote Admin messages. This setting is not required for remote node administration." } } diff --git a/src/i18n/locales/zh-CN/messages.json b/src/i18n/locales/zh-CN/messages.json index b61de68d..35f3380b 100644 --- a/src/i18n/locales/zh-CN/messages.json +++ b/src/i18n/locales/zh-CN/messages.json @@ -1,6 +1,7 @@ { "page": { - "title": "Messages: {{chatName}}" + "title": "Messages: {{chatName}}", + "placeholder": "Enter Message" }, "emptyState": { "title": "Select a Chat", @@ -10,31 +11,29 @@ "text": "Select a channel or node to start messaging." }, "sendMessage": { - "placeholder": "Type your message here...", + "placeholder": "Enter your message here...", "sendButton": "传送" }, "actionsMenu": { "addReactionLabel": "Add Reaction", "replyLabel": "回复" }, - "item": { - "status": { - "delivered": { - "label": "Message delivered", - "displayText": "Message delivered" - }, - "failed": { - "label": "Message delivery failed", - "displayText": "Delivery failed" - }, - "unknown": { - "label": "Message status unknown", - "displayText": "Unknown state" - }, - "waiting": { - "ariaLabel": "Sending message", - "displayText": "Waiting for delivery" - } + "deliveryStatus": { + "delivered": { + "label": "Message delivered", + "displayText": "Message delivered" + }, + "failed": { + "label": "Message delivery failed", + "displayText": "Delivery failed" + }, + "unknown": { + "label": "Message status unknown", + "displayText": "Unknown state" + }, + "waiting": { + "label": "Sending message", + "displayText": "Waiting for delivery" } } } diff --git a/src/i18n/locales/zh-CN/nodes.json b/src/i18n/locales/zh-CN/nodes.json index 6f1ac1b4..f33a4313 100644 --- a/src/i18n/locales/zh-CN/nodes.json +++ b/src/i18n/locales/zh-CN/nodes.json @@ -10,11 +10,16 @@ "label": "Direct Message {{shortName}}" }, "favorite": { - "label": "收藏" + "label": "收藏", + "tooltip": "Add or remove this node from your favorites" }, "notFavorite": { "label": "Not a Favorite" }, + "error": { + "label": "错误", + "text": "An error occurred while fetching node details. Please try again later." + }, "status": { "heard": "收到", "mqtt": "MQTT" @@ -47,5 +52,12 @@ "lastHeardStatus": { "never": "Never" } + }, + "actions": { + "added": "Added", + "removed": "Removed", + "ignoreNode": "忽略节点", + "unignoreNode": "Unignore Node", + "requestPosition": "Request Position" } } diff --git a/src/i18n/locales/zh-CN/ui.json b/src/i18n/locales/zh-CN/ui.json index e93db7f6..a74f34f3 100644 --- a/src/i18n/locales/zh-CN/ui.json +++ b/src/i18n/locales/zh-CN/ui.json @@ -80,6 +80,24 @@ "saveSuccess": { "title": "Saving Config", "description": "The configuration change {{case}} has been saved." + }, + "favoriteNode": { + "title": "{{action}} {{nodeName}} {{direction}} favorites.", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } + }, + "ignoreNode": { + "title": "{{action}} {{nodeName}} {{direction}} ignore list", + "action": { + "added": "Added", + "removed": "Removed", + "to": "to", + "from": "from" + } } }, "notifications": { @@ -117,6 +135,9 @@ "filter": { "label": "筛选器csvfganw" }, + "advanced": { + "label": "高级" + }, "clearInput": { "label": "Clear input" }, @@ -166,6 +187,12 @@ "viaMqtt": { "label": "Connected via MQTT" }, + "hopsUnknown": { + "label": "Unknown number of hops" + }, + "showUnheard": { + "label": "Never heard" + }, "language": { "label": "语言", "changeLanguage": "Change Language" From 6c676fa8da29c18be29385a375405528cd562622 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 23 Jun 2025 22:26:01 -0400 Subject: [PATCH 25/37] add git sub module (#678) --- src/core/connection | 1 + 1 file changed, 1 insertion(+) create mode 160000 src/core/connection diff --git a/src/core/connection b/src/core/connection new file mode 160000 index 00000000..830ca07a --- /dev/null +++ b/src/core/connection @@ -0,0 +1 @@ +Subproject commit 830ca07a0b8cb61d81dd0406cb9efab804228a78 From e2f03aaf81cfce858b176a25e2cdbd61a2769c71 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Tue, 24 Jun 2025 18:19:26 -0400 Subject: [PATCH 26/37] feat: add dependency injection using tanstack context (#680) * feat: add dep injection using tanstack context * fixed small typo --- .gitignore | 3 +- .gitmodules | 3 ++ .../NodeDetailsDialog/NodeDetailsDialog.tsx | 1 + .../PageComponents/Messages/MessageItem.tsx | 6 +-- src/components/UI/Generator.tsx | 2 +- src/core/stores/deviceStore.ts | 20 +++++++++ src/index.tsx | 41 +++++++++++++------ src/pages/Messages.tsx | 10 ++--- src/routes.tsx | 39 ++++++++++++++---- 9 files changed, 95 insertions(+), 30 deletions(-) create mode 100644 .gitmodules diff --git a/.gitignore b/.gitignore index ec3dfc3a..76c403ce 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ stats.html .vercel .vite dev-dist -__screenshots__* \ No newline at end of file +__screenshots__* +*.diff \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..1e24054e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/core/connection"] + path = src/core/connection + url = https://github.com/meshtastic/js.git diff --git a/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx b/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx index 9a80194d..356ab3b1 100644 --- a/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx +++ b/src/components/Dialog/NodeDetailsDialog/NodeDetailsDialog.tsx @@ -82,6 +82,7 @@ export const NodeDetailsDialog = ({ function handleDirectMessage() { if (!node) return; navigate({ to: `/messages/direct/${node.num}` }); + setDialogOpen("nodeDetails", false); } function handleRequestPosition() { diff --git a/src/components/PageComponents/Messages/MessageItem.tsx b/src/components/PageComponents/Messages/MessageItem.tsx index dbcfd533..ee38e674 100644 --- a/src/components/PageComponents/Messages/MessageItem.tsx +++ b/src/components/PageComponents/Messages/MessageItem.tsx @@ -51,7 +51,7 @@ interface MessageItemProps { export const MessageItem = ({ message }: MessageItemProps) => { const { getNode } = useDevice(); const { getMyNodeNum } = useMessageStore(); - const { t, i18n } = useTranslation(); + const { t, i18n } = useTranslation("messages"); const MESSAGE_STATUS_MAP = useMemo( (): Record => ({ @@ -78,7 +78,7 @@ export const MessageItem = ({ message }: MessageItemProps) => { ); const UNKNOWN_STATUS = useMemo((): MessageStatusInfo => ({ - displayText: t("delveryStatus.unknown.displayText"), + displayText: t("deliveryStatus.unknown.displayText"), icon: AlertCircle, ariaLabel: t("deliveryStatus.unknown.label"), iconClassName: "text-red-500 dark:text-red-400", @@ -99,7 +99,7 @@ export const MessageItem = ({ message }: MessageItemProps) => { const { displayName, shortName, isFavorite } = useMemo(() => { const userIdHex = message.from.toString(16).toUpperCase().padStart(2, "0"); const last4 = userIdHex.slice(-4); - const fallbackName = t("message_item_fallbackName_withLastFour", { last4 }); + const fallbackName = t("fallbackName", { last4 }); const longName = messageUser?.user?.longName; const derivedShortName = messageUser?.user?.shortName || fallbackName; const derivedDisplayName = longName || derivedShortName; diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 22fa2921..a2098037 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -70,7 +70,7 @@ const Generator = ( key: "bit8", }, { - text: t("security.empty"), + text: t("security.0bit"), value: "0", key: "bit0", }, diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index 5b8d20c0..21850517 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -114,6 +114,8 @@ export interface Device { hasNodeError: (nodeNum: number) => boolean; incrementUnread: (nodeNum: number) => void; resetUnread: (nodeNum: number) => void; + getUnreadCount: (nodeNum: number) => number; + getAllUnreadCount: () => number; getNodes: ( filter?: (node: Protobuf.Mesh.NodeInfo) => boolean, ) => Protobuf.Mesh.NodeInfo[]; @@ -664,6 +666,24 @@ export const useDeviceStore = createStore((set, get) => ({ }), ); }, + getUnreadCount: (nodeNum: number): number => { + const device = get().devices.get(id); + if (!device) { + return 0; + } + return device.unreadCounts.get(nodeNum) ?? 0; + }, + getAllUnreadCount: (): number => { + const device = get().devices.get(id); + if (!device) { + return 0; + } + let totalUnread = 0; + device.unreadCounts.forEach((count) => { + totalUnread += count; + }); + return totalUnread; + }, resetUnread: (nodeNum: number) => { set( produce((draft) => { diff --git a/src/index.tsx b/src/index.tsx index dbaafd39..e2661887 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,11 +1,15 @@ +import React from "react"; import "@app/index.css"; import { enableMapSet } from "immer"; import "maplibre-gl/dist/maplibre-gl.css"; -import { StrictMode, Suspense } from "react"; +import { Suspense } from "react"; import { createRoot } from "react-dom/client"; import "./i18n/config.ts"; import { createRouter, RouterProvider } from "@tanstack/react-router"; -import { routeTree } from "@app/routes.tsx"; +import { router } from "@app/routes.tsx"; +import { useAppStore } from "@core/stores/appStore.ts"; +import { useMessageStore } from "@core/stores/messageStore/index.ts"; +import { useTranslation } from "react-i18next"; declare module "@tanstack/react-router" { interface Register { @@ -16,16 +20,27 @@ declare module "@tanstack/react-router" { const container = document.getElementById("root") as HTMLElement; const root = createRoot(container); -enableMapSet(); +function IndexPage() { + enableMapSet(); + const appStore = useAppStore(); + const messageStore = useMessageStore(); + const translation = useTranslation(); -const router = createRouter({ - routeTree, -}); + const context = React.useMemo(() => ({ + stores: { + app: appStore, + message: messageStore, + }, + i18n: translation, + }), [appStore, messageStore]); -root.render( - - - - - , -); + return ( + + + + + + ); +} + +root.render(); diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 96bb7b0e..51e7c6ca 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -47,7 +47,7 @@ export const MessagesPage = () => { getNodes, getNode, hasNodeError, - unreadCounts, + getUnreadCount, resetUnread, connection, } = useDevice(); @@ -105,7 +105,7 @@ export const MessagesPage = () => { }) .map((node) => ({ ...node, - unreadCount: unreadCounts.get(node.num) ?? 0, + unreadCount: getUnreadCount(node.num) ?? 0, })) .sort((a, b) => { const diff = b.unreadCount - a.unreadCount; @@ -211,7 +211,7 @@ export const MessagesPage = () => { {filteredChannels?.map((channel) => ( { ), [ filteredChannels, - unreadCounts, numericChatId, chatType, isCollapsed, + getUnreadCount, navigateToChat, resetUnread, t, @@ -249,7 +249,7 @@ export const MessagesPage = () => { () => (
- + {pages.map((link) => { return ( { })} -
+
{children}
diff --git a/packages/web/src/components/generic/DeviceImage.tsx b/packages/web/src/components/generic/DeviceImage.tsx index b80ebbac..ef96a429 100644 --- a/packages/web/src/components/generic/DeviceImage.tsx +++ b/packages/web/src/components/generic/DeviceImage.tsx @@ -47,7 +47,7 @@ const hardwareModelToFilename: { [key: string]: string } = { }; export const DeviceImage = ({ deviceType, className }: DeviceImageProps) => { - const getPath = (device: string) => `/${device}`; + const getPath = (device: string) => `/devices/${device}`; const device = hardwareModelToFilename[deviceType] || "unknown.svg"; return {device}; }; From d3446b64a390f97c33901cda144c47dc0f7d4ba0 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 7 Jul 2025 10:43:58 -0400 Subject: [PATCH 32/37] removed tests from ci pipeline (#694) --- .github/workflows/ci.yml | 3 --- .github/workflows/pr.yml | 4 ---- 2 files changed, 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18b60047..ab5c4648 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,5 @@ jobs: - name: Check formatter run: deno task format --check - - name: Run tests - run: deno task test - - name: Build Package run: deno task build diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 98ec0454..02a23fe1 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -48,10 +48,6 @@ jobs: working-directory: packages/web run: deno task format --check - - name: Run tests - working-directory: packages/web - run: deno task test - - name: Build Package working-directory: packages/web run: deno task build \ No newline at end of file From 8989478af44ef2c327280ae3b4126bad71d6e0ad Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 7 Jul 2025 11:43:17 -0400 Subject: [PATCH 33/37] update caching for ci/cd (#695) --- .github/workflows/ci.yml | 7 ++----- .github/workflows/pr.yml | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab5c4648..17419933 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,14 +29,11 @@ jobs: with: path: | ~/.cache/deno - ./deno.lock - key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.lock') }} + packages/web/deno.lock + key: ${{ runner.os }}-deno-${{ hashFiles('packages/web/deno.lock') }} restore-keys: | ${{ runner.os }}-deno- - - name: Cache Dependencies - run: deno cache /packages/web/src/index.tsx - - name: Run linter run: deno task lint diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 02a23fe1..12935b63 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -36,10 +36,6 @@ jobs: restore-keys: | ${{ runner.os }}-deno- - - name: Cache Dependencies - working-directory: packages/web - run: deno cache src/index.tsx - - name: Run linter working-directory: packages/web run: deno task lint From 684cf30d2f7662c6847ed2601c2e0862bafaf08f Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 7 Jul 2025 11:49:18 -0400 Subject: [PATCH 34/37] add npmrc to root (#696) --- .npmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .npmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..41583e36 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@jsr:registry=https://npm.jsr.io From 3bcda37e6656953b045afe51e3fbd23a00714531 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 7 Jul 2025 11:52:48 -0400 Subject: [PATCH 35/37] update pr workflow (#697) --- .github/workflows/pr.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 12935b63..db505f84 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,9 +1,6 @@ -name: Push to Main CI +name: Pull Request CI -on: - push: - branches: - - main +on: pull_request permissions: contents: write From 49283daa4f22db8cf2470072209002625055a8a1 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 7 Jul 2025 11:53:42 -0400 Subject: [PATCH 36/37] fix: updated nginx config to pass sub directories (#692) --- packages/web/infra/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/infra/default.conf b/packages/web/infra/default.conf index 7a5f1103..aff74785 100644 --- a/packages/web/infra/default.conf +++ b/packages/web/infra/default.conf @@ -6,7 +6,7 @@ server { index index.html index.htm; location / { - try_files $uri $uri/ =404; + try_files $uri $uri/ /index.html; } error_page 500 502 503 504 /50x.html; From 2e2b0074b15921fb66fff20ca465fa1dcfb66abd Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 7 Jul 2025 14:14:41 -0400 Subject: [PATCH 37/37] Assorted Monorepo fixes (#698) * add npmrc to root * fix: associated updates related to monorepo updates * removed deno plugin * removed deno plugin * updating ci --- .github/ISSUE_TEMPLATE/bug.yml | 4 +- .github/ISSUE_TEMPLATE/feature.yml | 2 +- .github/workflows/ci.yml | 6 +- .github/workflows/crowdin-download.yml | 24 +- .github/workflows/nightly.yml | 2 +- .github/workflows/pr.yml | 8 +- .github/workflows/release.yml | 2 +- .../workflows/update-stable-from-master.yml | 10 +- .vscode/settings.json | 5 +- README.md | 2 +- deno.lock | 863 +- packages/web/README.md | 4 +- packages/web/deno.json | 14 + packages/web/deno.lock | 7229 ---------------- packages/web/package.json | 103 +- packages/web/postcss.config.cjs | 2 +- packages/web/public/Logo.svg | 55 +- packages/web/public/Logo_Black.svg | 30 +- packages/web/public/Logo_White.svg | 32 +- packages/web/public/chirpy.svg | 65 +- packages/web/public/devices/diy.svg | 2234 ++++- .../devices/heltec-ht62-esp32c3-sx1262.svg | 2605 +++++- .../devices/heltec-mesh-node-t114-case.svg | 272 +- .../public/devices/heltec-mesh-node-t114.svg | 399 +- .../web/public/devices/heltec-v3-case.svg | 75 +- packages/web/public/devices/heltec-v3.svg | 1497 +++- .../devices/heltec-vision-master-e213.svg | 150 +- .../devices/heltec-vision-master-e290.svg | 222 +- .../devices/heltec-vision-master-t190.svg | 214 +- .../devices/heltec-wireless-paper-V1_0.svg | 511 +- .../public/devices/heltec-wireless-paper.svg | 511 +- .../devices/heltec-wireless-tracker-V1-0.svg | 2032 ++++- .../devices/heltec-wireless-tracker.svg | 2032 ++++- packages/web/public/devices/heltec-wsl-v3.svg | 1069 ++- packages/web/public/devices/nano-g2-ultra.svg | 217 +- packages/web/public/devices/pico.svg | 6328 +++++++------- packages/web/public/devices/promicro.svg | 2620 +++++- .../web/public/devices/rak-wismeshtap.svg | 265 +- packages/web/public/devices/rak11310.svg | 5013 ++++++----- packages/web/public/devices/rak2560.svg | 380 +- packages/web/public/devices/rak4631.svg | 7678 +++++++++-------- packages/web/public/devices/rak4631_case.svg | 323 +- packages/web/public/devices/rpipicow.svg | 2306 ++++- .../devices/seeed-sensecap-indicator.svg | 547 +- packages/web/public/devices/seeed-xiao-s3.svg | 1003 ++- packages/web/public/devices/station-g2.svg | 513 +- packages/web/public/devices/t-deck.svg | 698 +- packages/web/public/devices/t-echo.svg | 196 +- packages/web/public/devices/t-watch-s3.svg | 127 +- packages/web/public/devices/tbeam-s3-core.svg | 2515 +++++- packages/web/public/devices/tbeam.svg | 3448 +++++++- packages/web/public/devices/tlora-c6.svg | 494 +- .../web/public/devices/tlora-t3s3-epaper.svg | 295 +- packages/web/public/devices/tlora-t3s3-v1.svg | 1312 ++- .../web/public/devices/tlora-v2-1-1_6.svg | 1238 ++- .../web/public/devices/tlora-v2-1-1_8.svg | 1238 ++- .../web/public/devices/tracker-t1000-e.svg | 442 +- packages/web/public/devices/unknown.svg | 398 +- .../web/public/devices/wio-tracker-wm1110.svg | 3446 +++++++- .../web/public/devices/wm1110_dev_kit.svg | 4909 ++++++++++- packages/web/public/icon.svg | 55 +- packages/web/public/logo.svg | 55 +- packages/web/public/logo_black.svg | 30 +- packages/web/public/logo_white.svg | 32 +- packages/web/src/index.tsx | 1 - packages/web/vite.config.ts | 3 + 66 files changed, 53700 insertions(+), 16710 deletions(-) delete mode 100644 packages/web/deno.lock diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 75b6079d..6491a5fb 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -95,7 +95,7 @@ body: - type: input id: browser attributes: - label: Browser + label: Browser description: What browser are you using? Include version if possible. placeholder: e.g., Chrome 108, Firefox 107, Safari 16.2 validations: @@ -153,4 +153,4 @@ body: - type: markdown attributes: value: | - Thank you for helping improve our project by reporting this bug! \ No newline at end of file + Thank you for helping improve our project by reporting this bug! diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index c4c8ba9d..7448b340 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -62,4 +62,4 @@ body: - type: markdown attributes: value: | - Thank you for taking the time to fill out this feature request! \ No newline at end of file + Thank you for taking the time to fill out this feature request! diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17419933..3629d269 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,16 +29,16 @@ jobs: with: path: | ~/.cache/deno - packages/web/deno.lock + packages/web/deno.lock key: ${{ runner.os }}-deno-${{ hashFiles('packages/web/deno.lock') }} restore-keys: | ${{ runner.os }}-deno- - name: Run linter - run: deno task lint + run: deno lint - name: Check formatter - run: deno task format --check + run: deno fmt --check - name: Build Package run: deno task build diff --git a/.github/workflows/crowdin-download.yml b/.github/workflows/crowdin-download.yml index cbead21d..d2a9f83e 100644 --- a/.github/workflows/crowdin-download.yml +++ b/.github/workflows/crowdin-download.yml @@ -1,9 +1,9 @@ name: Crowdin Download Translations Action on: - schedule: # Every Sunday at midnight - - cron: '0 0 * * 0' - workflow_dispatch: # Allow manual triggering + schedule: # Every Sunday at midnight + - cron: "0 0 * * 0" + workflow_dispatch: # Allow manual triggering jobs: synchronize-with-crowdin: @@ -16,20 +16,20 @@ jobs: - name: Download translations with Crowdin uses: crowdin/github-action@v2 with: - base_url: 'https://meshtastic.crowdin.com/api/v2' - config: 'crowdin.yml' + base_url: "https://meshtastic.crowdin.com/api/v2" + config: "crowdin.yml" upload_sources: false upload_translations: false download_translations: true localization_branch_name: i18n_crowdin_translations - commit_message: 'chore(i18n): New Crowdin Translations by GitHub Action' + commit_message: "chore(i18n): New Crowdin Translations by GitHub Action" create_pull_request: true - pull_request_title: 'chore(i18n): New Crowdin Translations' - pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)' - pull_request_base_branch_name: 'main' - pull_request_labels: 'i18n' - crowdin_branch_name: 'main' + pull_request_title: "chore(i18n): New Crowdin Translations" + pull_request_body: "New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)" + pull_request_base_branch_name: "main" + pull_request_labels: "i18n" + crowdin_branch_name: "main" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} \ No newline at end of file + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 60517906..9846c80c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,4 +1,4 @@ -name: 'Nightly Release' +name: "Nightly Release" on: schedule: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index db505f84..459ca916 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -28,19 +28,19 @@ jobs: with: path: | ~/.cache/deno - packages/web/deno.lock + packages/web/deno.lock key: ${{ runner.os }}-deno-${{ hashFiles('packages/web/deno.lock') }} restore-keys: | ${{ runner.os }}-deno- - name: Run linter working-directory: packages/web - run: deno task lint + run: deno lint - name: Check formatter working-directory: packages/web - run: deno task format --check + run: deno fmt --check - name: Build Package working-directory: packages/web - run: deno task build \ No newline at end of file + run: deno task --filter web build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea282cbd..887dc64c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: - name: Install Dependencies working-directory: packages/web run: deno install - + - name: Run tests working-directory: packages/web run: deno task test diff --git a/.github/workflows/update-stable-from-master.yml b/.github/workflows/update-stable-from-master.yml index 601d113c..7510939a 100644 --- a/.github/workflows/update-stable-from-master.yml +++ b/.github/workflows/update-stable-from-master.yml @@ -2,14 +2,14 @@ name: Update Stable Branch from Main on Latest Release on: release: - types: [released] + types: [released] permissions: - contents: write + contents: write jobs: update-stable-branch: - name: Update Stable Branch from Main + name: Update Stable Branch from Main runs-on: ubuntu-latest steps: @@ -43,8 +43,8 @@ jobs: git checkout -b stable ${{ env.MAIN_SHA }} fi - - name: Reset stable branch to latest main + - name: Reset stable branch to latest main run: git reset --hard ${{ env.MAIN_SHA }} - name: Force push stable branch - run: git push origin stable --force \ No newline at end of file + run: git push origin stable --force diff --git a/.vscode/settings.json b/.vscode/settings.json index 9045fc0f..04d2f6e1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,8 @@ "deno.enable": true, "deno.suggest.imports.autoDiscover": true, "editor.formatOnSave": true, - "editor.defaultFormatter": "denoland.vscode-deno" + "editor.defaultFormatter": "denoland.vscode-deno", + "[typescript]": { + "editor.defaultFormatter": "denoland.vscode-deno" + } } diff --git a/README.md b/README.md index 521b7e65..442a7642 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ monorepo. Follow the installation instructions on their home page. ``` 2. **Install dependencies for all packages:** ```bash - deno task install:all + deno task install:all ``` This command installs all necessary dependencies for all packages within the monorepo. diff --git a/deno.lock b/deno.lock index 196e74da..c80a48bc 100644 --- a/deno.lock +++ b/deno.lock @@ -2,56 +2,57 @@ "version": "5", "specifiers": { "jsr:@meshtastic/protobufs@^2.7.0": "2.7.0", - "jsr:@std/path@^1.1.0": "1.1.0", - "npm:@bufbuild/protobuf@^2.2.3": "2.5.2", - "npm:@bufbuild/protobuf@^2.2.5": "2.5.2", - "npm:@hookform/resolvers@^5.1.1": "5.1.1_react-hook-form@7.58.1__react@19.1.0_react@19.1.0", + "jsr:@std/internal@^1.0.9": "1.0.9", + "jsr:@std/path@^1.1.0": "1.1.1", + "npm:@bufbuild/protobuf@^2.2.3": "2.6.0", + "npm:@bufbuild/protobuf@^2.6.0": "2.6.0", + "npm:@hookform/resolvers@^5.1.1": "5.1.1_react-hook-form@7.60.0__react@19.1.0_react@19.1.0", "npm:@jsr/meshtastic__core@2.6.4": "2.6.4", "npm:@jsr/meshtastic__js@2.6.0-0": "2.6.0-0", "npm:@jsr/meshtastic__transport-http@*": "0.2.1", "npm:@jsr/meshtastic__transport-web-bluetooth@*": "0.1.2", "npm:@jsr/meshtastic__transport-web-serial@*": "0.2.1", - "npm:@noble/curves@^1.9.0": "1.9.2", - "npm:@radix-ui/react-accordion@^1.2.8": "1.2.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-checkbox@^1.2.3": "1.3.2_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-dialog@^1.1.11": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-dropdown-menu@^2.1.12": "2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-label@^2.1.4": "2.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-menubar@^1.1.12": "1.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-popover@^1.1.11": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-scroll-area@^1.2.6": "1.2.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-select@^2.2.2": "2.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-separator@^1.1.4": "1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-slider@^1.3.2": "1.3.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-switch@^1.2.2": "1.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-tabs@^1.1.9": "1.1.12_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-toast@^1.2.11": "1.2.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-toggle-group@^1.1.9": "1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-tooltip@^1.2.4": "1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tailwindcss/postcss@^4.1.5": "4.1.10", - "npm:@tanstack/react-router-devtools@^1.120.16": "1.121.34_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/react-router@^1.120.15": "1.121.34_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-cli@^1.121.37": "1.121.37", - "npm:@tanstack/router-devtools@^1.120.15": "1.121.34_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-plugin@^1.120.15": "1.121.37_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@24.0.4_@types+node@22.15.33", + "npm:@noble/curves@^1.9.2": "1.9.2", + "npm:@radix-ui/react-accordion@^1.2.11": "1.2.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-checkbox@^1.3.2": "1.3.2_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-dialog@^1.1.14": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-dropdown-menu@^2.1.15": "2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-label@^2.1.7": "2.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-menubar@^1.1.15": "1.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-popover@^1.1.14": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-scroll-area@^1.2.9": "1.2.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-select@^2.2.5": "2.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-separator@^1.1.7": "1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-slider@^1.3.5": "1.3.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-switch@^1.2.5": "1.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-tabs@^1.1.12": "1.1.12_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-toast@^1.2.14": "1.2.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-toggle-group@^1.1.10": "1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@radix-ui/react-tooltip@^1.2.7": "1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tailwindcss/postcss@^4.1.11": "4.1.11", + "npm:@tanstack/react-router-devtools@^1.125.4": "1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/react-router@^1.125.4": "1.125.4_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/router-cli@^1.125.4": "1.125.4", + "npm:@tanstack/router-devtools@^1.125.4": "1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/router-plugin@^1.125.5": "1.125.5_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.16.0", "npm:@testing-library/jest-dom@^6.6.3": "6.6.3", "npm:@testing-library/react@^16.3.0": "16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:@testing-library/user-event@^14.6.1": "14.6.1_@testing-library+dom@10.4.0", "npm:@turf/turf@^7.2.0": "7.2.0", - "npm:@types/chrome@^0.0.318": "0.0.318", + "npm:@types/chrome@^0.0.329": "0.0.329", "npm:@types/js-cookie@^3.0.6": "3.0.6", - "npm:@types/node@^22.13.10": "22.15.33", - "npm:@types/node@^24.0.4": "24.0.4", - "npm:@types/react-dom@^19.1.3": "19.1.6_@types+react@19.1.8", - "npm:@types/react@^19.1.2": "19.1.8", - "npm:@types/serviceworker@^0.0.133": "0.0.133", + "npm:@types/node@^22.13.10": "22.16.0", + "npm:@types/node@^24.0.10": "24.0.10", + "npm:@types/react-dom@^19.1.6": "19.1.6_@types+react@19.1.8", + "npm:@types/react@^19.1.8": "19.1.8", + "npm:@types/serviceworker@^0.0.140": "0.0.140", "npm:@types/w3c-web-serial@*": "1.0.8", "npm:@types/w3c-web-serial@^1.0.7": "1.0.8", "npm:@types/w3c-web-serial@^1.0.8": "1.0.8", - "npm:@types/web-bluetooth@*": "0.0.21", + "npm:@types/web-bluetooth@*": "0.0.20", "npm:@types/web-bluetooth@^0.0.20": "0.0.20", "npm:@types/web-bluetooth@^0.0.21": "0.0.21", - "npm:@vitejs/plugin-react@^4.4.1": "4.6.0_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@babel+core@7.27.4_@types+node@24.0.4_@types+node@22.15.33", + "npm:@vitejs/plugin-react@^4.6.0": "4.6.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_@types+node@22.16.0", "npm:autoprefixer@^10.4.21": "10.4.21_postcss@8.5.6", "npm:base64-js@^1.5.1": "1.5.1", "npm:class-variance-authority@~0.7.1": "0.7.1", @@ -60,38 +61,37 @@ "npm:crc@^4.3.2": "4.3.2", "npm:crypto-random-string@5": "5.0.0", "npm:gzipper@^8.2.1": "8.2.1", - "npm:happy-dom@^17.4.6": "17.6.3", - "npm:i18next-browser-languagedetector@^8.1.0": "8.2.0", + "npm:happy-dom@^18.0.1": "18.0.1", + "npm:i18next-browser-languagedetector@^8.2.0": "8.2.0", "npm:i18next-http-backend@^3.0.2": "3.0.2", - "npm:i18next@^25.2.0": "25.2.1_typescript@5.8.3", - "npm:idb-keyval@^6.2.1": "6.2.2", + "npm:i18next@^25.3.1": "25.3.1_typescript@5.8.3", + "npm:idb-keyval@^6.2.2": "6.2.2", "npm:immer@^10.1.1": "10.1.1", "npm:js-cookie@^3.0.5": "3.0.5", - "npm:lucide-react@0.507": "0.507.0_react@19.1.0", - "npm:maplibre-gl@5.4.0": "5.4.0", - "npm:postcss@^8.5.3": "8.5.6", + "npm:lucide-react@0.525": "0.525.0_react@19.1.0", + "npm:maplibre-gl@5.6.1": "5.6.1", + "npm:postcss@^8.5.6": "8.5.6", "npm:react-dom@^19.1.0": "19.1.0_react@19.1.0", "npm:react-error-boundary@6": "6.0.0_react@19.1.0", - "npm:react-hook-form@^7.56.2": "7.58.1_react@19.1.0", - "npm:react-i18next@^15.5.1": "15.5.3_i18next@25.2.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3", - "npm:react-map-gl@8.0.4": "8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:react-hook-form@^7.60.0": "7.60.0_react@19.1.0", + "npm:react-i18next@^15.6.0": "15.6.0_i18next@25.3.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3", + "npm:react-map-gl@8.0.4": "8.0.4_maplibre-gl@5.6.1_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:react-qrcode-logo@3": "3.0.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:react@^19.1.0": "19.1.0", "npm:rfc4648@^1.5.4": "1.5.4", "npm:simple-git-hooks@^2.13.0": "2.13.0", "npm:ste-simple-events@^3.0.11": "3.0.11", - "npm:tailwind-merge@^3.2.0": "3.3.1", - "npm:tailwindcss-animate@^1.0.7": "1.0.7_tailwindcss@4.1.10", - "npm:tailwindcss@^4.1.5": "4.1.10", + "npm:tailwind-merge@^3.3.1": "3.3.1", + "npm:tailwindcss-animate@^1.0.7": "1.0.7_tailwindcss@4.1.11", + "npm:tailwindcss@^4.1.11": "4.1.11", "npm:tar@^7.4.3": "7.4.3", "npm:testing-library@^0.0.2": "0.0.2_@angular+common@6.1.10__@angular+core@6.1.10___rxjs@6.6.7___zone.js@0.8.29__rxjs@6.6.7_@angular+core@6.1.10__rxjs@6.6.7__zone.js@0.8.29", "npm:tslog@^4.9.3": "4.9.3", "npm:typescript@^5.8.3": "5.8.3", - "npm:vite@*": "7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33", - "npm:vite@7": "7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33", - "npm:vitest@^3.2.4": "3.2.4_@types+node@24.0.4_happy-dom@17.6.3_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@types+node@22.15.33", - "npm:zod@^3.25.67": "3.25.67", - "npm:zustand@5.0.5": "5.0.5_@types+react@19.1.8_immer@10.1.1_react@19.1.0" + "npm:vite@7": "7.0.2_@types+node@22.16.0_picomatch@4.0.2", + "npm:vitest@^3.2.4": "3.2.4_@types+node@22.16.0_happy-dom@18.0.1_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2", + "npm:zod@^3.25.75": "3.25.75", + "npm:zustand@5.0.6": "5.0.6_@types+react@19.1.8_immer@10.1.1_react@19.1.0" }, "jsr": { "@meshtastic/protobufs@2.7.0": { @@ -100,8 +100,14 @@ "npm:@bufbuild/protobuf@^2.2.3" ] }, - "@std/path@1.1.0": { - "integrity": "ddc94f8e3c275627281cbc23341df6b8bcc874d70374f75fec2533521e3d6886" + "@std/internal@1.0.9": { + "integrity": "bdfb97f83e4db7a13e8faab26fb1958d1b80cc64366501af78a0aee151696eb8" + }, + "@std/path@1.1.1": { + "integrity": "fe00026bd3a7e6a27f73709b83c607798be40e20c81dde655ce34052fd82ec76", + "dependencies": [ + "jsr:@std/internal" + ] } }, "npm": { @@ -142,11 +148,11 @@ "picocolors" ] }, - "@babel/compat-data@7.27.5": { - "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==" + "@babel/compat-data@7.28.0": { + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==" }, - "@babel/core@7.27.4": { - "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", + "@babel/core@7.28.0": { + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "dependencies": [ "@ampproject/remapping", "@babel/code-frame", @@ -165,8 +171,8 @@ "semver" ] }, - "@babel/generator@7.27.5": { - "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "@babel/generator@7.28.0": { + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "dependencies": [ "@babel/parser", "@babel/types", @@ -191,7 +197,7 @@ "semver" ] }, - "@babel/helper-create-class-features-plugin@7.27.1_@babel+core@7.27.4": { + "@babel/helper-create-class-features-plugin@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", "dependencies": [ "@babel/core", @@ -204,6 +210,9 @@ "semver" ] }, + "@babel/helper-globals@7.28.0": { + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==" + }, "@babel/helper-member-expression-to-functions@7.27.1": { "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", "dependencies": [ @@ -218,7 +227,7 @@ "@babel/types" ] }, - "@babel/helper-module-transforms@7.27.3_@babel+core@7.27.4": { + "@babel/helper-module-transforms@7.27.3_@babel+core@7.28.0": { "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dependencies": [ "@babel/core", @@ -236,7 +245,7 @@ "@babel/helper-plugin-utils@7.27.1": { "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==" }, - "@babel/helper-replace-supers@7.27.1_@babel+core@7.27.4": { + "@babel/helper-replace-supers@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", "dependencies": [ "@babel/core", @@ -268,28 +277,28 @@ "@babel/types" ] }, - "@babel/parser@7.27.5": { - "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", + "@babel/parser@7.28.0": { + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dependencies": [ "@babel/types" ], "bin": true }, - "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.27.4": { + "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-syntax-typescript@7.27.1_@babel+core@7.27.4": { + "@babel/plugin-syntax-typescript@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-modules-commonjs@7.27.1_@babel+core@7.27.4": { + "@babel/plugin-transform-modules-commonjs@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "dependencies": [ "@babel/core", @@ -297,22 +306,22 @@ "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-react-jsx-self@7.27.1_@babel+core@7.27.4": { + "@babel/plugin-transform-react-jsx-self@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-react-jsx-source@7.27.1_@babel+core@7.27.4": { + "@babel/plugin-transform-react-jsx-source@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-typescript@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==", + "@babel/plugin-transform-typescript@7.28.0_@babel+core@7.28.0": { + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", "dependencies": [ "@babel/core", "@babel/helper-annotate-as-pure", @@ -322,7 +331,7 @@ "@babel/plugin-syntax-typescript" ] }, - "@babel/preset-typescript@7.27.1_@babel+core@7.27.4": { + "@babel/preset-typescript@7.27.1_@babel+core@7.28.0": { "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", "dependencies": [ "@babel/core", @@ -344,195 +353,200 @@ "@babel/types" ] }, - "@babel/traverse@7.27.4": { - "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "@babel/traverse@7.28.0": { + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "dependencies": [ "@babel/code-frame", "@babel/generator", + "@babel/helper-globals", "@babel/parser", "@babel/template", "@babel/types", - "debug", - "globals" + "debug" ] }, - "@babel/types@7.27.6": { - "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", + "@babel/types@7.28.0": { + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "dependencies": [ "@babel/helper-string-parser", "@babel/helper-validator-identifier" ] }, - "@bufbuild/protobuf@2.5.2": { - "integrity": "sha512-foZ7qr0IsUBjzWIq+SuBLfdQCpJ1j8cTuNNT4owngTHoN5KsJb8L9t65fzz7SCeSWzescoOil/0ldqiL041ABg==" + "@bufbuild/protobuf@2.6.0": { + "integrity": "sha512-6cuonJVNOIL7lTj5zgo/Rc2bKAo4/GvN+rKCrUj7GdEHRzCk8zKOfFwUsL9nAVk5rSIsRmlgcpLzTRysopEeeg==" }, - "@emnapi/core@1.4.3": { - "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "@emnapi/core@1.4.4": { + "integrity": "sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==", "dependencies": [ "@emnapi/wasi-threads", "tslib@2.8.1" ] }, - "@emnapi/runtime@1.4.3": { - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "@emnapi/runtime@1.4.4": { + "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==", "dependencies": [ "tslib@2.8.1" ] }, - "@emnapi/wasi-threads@1.0.2": { - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "@emnapi/wasi-threads@1.0.3": { + "integrity": "sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==", "dependencies": [ "tslib@2.8.1" ] }, - "@esbuild/aix-ppc64@0.25.5": { - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "@esbuild/aix-ppc64@0.25.6": { + "integrity": "sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==", "os": ["aix"], "cpu": ["ppc64"] }, - "@esbuild/android-arm64@0.25.5": { - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "@esbuild/android-arm64@0.25.6": { + "integrity": "sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==", "os": ["android"], "cpu": ["arm64"] }, - "@esbuild/android-arm@0.25.5": { - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "@esbuild/android-arm@0.25.6": { + "integrity": "sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==", "os": ["android"], "cpu": ["arm"] }, - "@esbuild/android-x64@0.25.5": { - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "@esbuild/android-x64@0.25.6": { + "integrity": "sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==", "os": ["android"], "cpu": ["x64"] }, - "@esbuild/darwin-arm64@0.25.5": { - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "@esbuild/darwin-arm64@0.25.6": { + "integrity": "sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==", "os": ["darwin"], "cpu": ["arm64"] }, - "@esbuild/darwin-x64@0.25.5": { - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "@esbuild/darwin-x64@0.25.6": { + "integrity": "sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==", "os": ["darwin"], "cpu": ["x64"] }, - "@esbuild/freebsd-arm64@0.25.5": { - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "@esbuild/freebsd-arm64@0.25.6": { + "integrity": "sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@esbuild/freebsd-x64@0.25.5": { - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "@esbuild/freebsd-x64@0.25.6": { + "integrity": "sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==", "os": ["freebsd"], "cpu": ["x64"] }, - "@esbuild/linux-arm64@0.25.5": { - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "@esbuild/linux-arm64@0.25.6": { + "integrity": "sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@esbuild/linux-arm@0.25.5": { - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "@esbuild/linux-arm@0.25.6": { + "integrity": "sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==", "os": ["linux"], "cpu": ["arm"] }, - "@esbuild/linux-ia32@0.25.5": { - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "@esbuild/linux-ia32@0.25.6": { + "integrity": "sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==", "os": ["linux"], "cpu": ["ia32"] }, - "@esbuild/linux-loong64@0.25.5": { - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "@esbuild/linux-loong64@0.25.6": { + "integrity": "sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==", "os": ["linux"], "cpu": ["loong64"] }, - "@esbuild/linux-mips64el@0.25.5": { - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "@esbuild/linux-mips64el@0.25.6": { + "integrity": "sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==", "os": ["linux"], "cpu": ["mips64el"] }, - "@esbuild/linux-ppc64@0.25.5": { - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "@esbuild/linux-ppc64@0.25.6": { + "integrity": "sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==", "os": ["linux"], "cpu": ["ppc64"] }, - "@esbuild/linux-riscv64@0.25.5": { - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "@esbuild/linux-riscv64@0.25.6": { + "integrity": "sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==", "os": ["linux"], "cpu": ["riscv64"] }, - "@esbuild/linux-s390x@0.25.5": { - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "@esbuild/linux-s390x@0.25.6": { + "integrity": "sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==", "os": ["linux"], "cpu": ["s390x"] }, - "@esbuild/linux-x64@0.25.5": { - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "@esbuild/linux-x64@0.25.6": { + "integrity": "sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==", "os": ["linux"], "cpu": ["x64"] }, - "@esbuild/netbsd-arm64@0.25.5": { - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "@esbuild/netbsd-arm64@0.25.6": { + "integrity": "sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==", "os": ["netbsd"], "cpu": ["arm64"] }, - "@esbuild/netbsd-x64@0.25.5": { - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "@esbuild/netbsd-x64@0.25.6": { + "integrity": "sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==", "os": ["netbsd"], "cpu": ["x64"] }, - "@esbuild/openbsd-arm64@0.25.5": { - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "@esbuild/openbsd-arm64@0.25.6": { + "integrity": "sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==", "os": ["openbsd"], "cpu": ["arm64"] }, - "@esbuild/openbsd-x64@0.25.5": { - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "@esbuild/openbsd-x64@0.25.6": { + "integrity": "sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==", "os": ["openbsd"], "cpu": ["x64"] }, - "@esbuild/sunos-x64@0.25.5": { - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "@esbuild/openharmony-arm64@0.25.6": { + "integrity": "sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/sunos-x64@0.25.6": { + "integrity": "sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==", "os": ["sunos"], "cpu": ["x64"] }, - "@esbuild/win32-arm64@0.25.5": { - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "@esbuild/win32-arm64@0.25.6": { + "integrity": "sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==", "os": ["win32"], "cpu": ["arm64"] }, - "@esbuild/win32-ia32@0.25.5": { - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "@esbuild/win32-ia32@0.25.6": { + "integrity": "sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==", "os": ["win32"], "cpu": ["ia32"] }, - "@esbuild/win32-x64@0.25.5": { - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "@esbuild/win32-x64@0.25.6": { + "integrity": "sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==", "os": ["win32"], "cpu": ["x64"] }, - "@floating-ui/core@1.7.1": { - "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", + "@floating-ui/core@1.7.2": { + "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", "dependencies": [ "@floating-ui/utils" ] }, - "@floating-ui/dom@1.7.1": { - "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", + "@floating-ui/dom@1.7.2": { + "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", "dependencies": [ "@floating-ui/core", "@floating-ui/utils" ] }, - "@floating-ui/react-dom@2.1.3_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", + "@floating-ui/react-dom@2.1.4_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==", "dependencies": [ "@floating-ui/dom", "react", "react-dom" ] }, - "@floating-ui/utils@0.2.9": { - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" + "@floating-ui/utils@0.2.10": { + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==" }, "@gfx/zopfli@1.0.15": { "integrity": "sha512-7mBgpi7UD82fsff5ThQKet0uBTl4BYerQuc+/qA1ELTwWEiIedRTcD3JgiUu9wwZ2kytW8JOb165rSdAt8PfcQ==", @@ -540,7 +554,7 @@ "base64-js" ] }, - "@hookform/resolvers@5.1.1_react-hook-form@7.58.1__react@19.1.0_react@19.1.0": { + "@hookform/resolvers@5.1.1_react-hook-form@7.60.0__react@19.1.0_react@19.1.0": { "integrity": "sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg==", "dependencies": [ "@standard-schema/utils", @@ -553,10 +567,9 @@ "minipass" ] }, - "@jridgewell/gen-mapping@0.3.8": { - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "@jridgewell/gen-mapping@0.3.12": { + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dependencies": [ - "@jridgewell/set-array", "@jridgewell/sourcemap-codec", "@jridgewell/trace-mapping" ] @@ -564,14 +577,11 @@ "@jridgewell/resolve-uri@3.1.2": { "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" }, - "@jridgewell/set-array@1.2.1": { - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" - }, - "@jridgewell/sourcemap-codec@1.5.0": { - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "@jridgewell/sourcemap-codec@1.5.4": { + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==" }, - "@jridgewell/trace-mapping@0.3.25": { - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "@jridgewell/trace-mapping@0.3.29": { + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dependencies": [ "@jridgewell/resolve-uri", "@jridgewell/sourcemap-codec" @@ -1454,111 +1464,111 @@ "@rolldown/pluginutils@1.0.0-beta.19": { "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==" }, - "@rollup/rollup-android-arm-eabi@4.44.0": { - "integrity": "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==", + "@rollup/rollup-android-arm-eabi@4.44.2": { + "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", "os": ["android"], "cpu": ["arm"] }, - "@rollup/rollup-android-arm64@4.44.0": { - "integrity": "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==", + "@rollup/rollup-android-arm64@4.44.2": { + "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", "os": ["android"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-arm64@4.44.0": { - "integrity": "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==", + "@rollup/rollup-darwin-arm64@4.44.2": { + "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", "os": ["darwin"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-x64@4.44.0": { - "integrity": "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==", + "@rollup/rollup-darwin-x64@4.44.2": { + "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", "os": ["darwin"], "cpu": ["x64"] }, - "@rollup/rollup-freebsd-arm64@4.44.0": { - "integrity": "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==", + "@rollup/rollup-freebsd-arm64@4.44.2": { + "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@rollup/rollup-freebsd-x64@4.44.0": { - "integrity": "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==", + "@rollup/rollup-freebsd-x64@4.44.2": { + "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", "os": ["freebsd"], "cpu": ["x64"] }, - "@rollup/rollup-linux-arm-gnueabihf@4.44.0": { - "integrity": "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==", + "@rollup/rollup-linux-arm-gnueabihf@4.44.2": { + "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm-musleabihf@4.44.0": { - "integrity": "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==", + "@rollup/rollup-linux-arm-musleabihf@4.44.2": { + "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm64-gnu@4.44.0": { - "integrity": "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==", + "@rollup/rollup-linux-arm64-gnu@4.44.2": { + "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-arm64-musl@4.44.0": { - "integrity": "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==", + "@rollup/rollup-linux-arm64-musl@4.44.2": { + "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-loongarch64-gnu@4.44.0": { - "integrity": "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==", + "@rollup/rollup-linux-loongarch64-gnu@4.44.2": { + "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", "os": ["linux"], "cpu": ["loong64"] }, - "@rollup/rollup-linux-powerpc64le-gnu@4.44.0": { - "integrity": "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==", + "@rollup/rollup-linux-powerpc64le-gnu@4.44.2": { + "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", "os": ["linux"], "cpu": ["ppc64"] }, - "@rollup/rollup-linux-riscv64-gnu@4.44.0": { - "integrity": "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==", + "@rollup/rollup-linux-riscv64-gnu@4.44.2": { + "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-riscv64-musl@4.44.0": { - "integrity": "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==", + "@rollup/rollup-linux-riscv64-musl@4.44.2": { + "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-s390x-gnu@4.44.0": { - "integrity": "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==", + "@rollup/rollup-linux-s390x-gnu@4.44.2": { + "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", "os": ["linux"], "cpu": ["s390x"] }, - "@rollup/rollup-linux-x64-gnu@4.44.0": { - "integrity": "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==", + "@rollup/rollup-linux-x64-gnu@4.44.2": { + "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-linux-x64-musl@4.44.0": { - "integrity": "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==", + "@rollup/rollup-linux-x64-musl@4.44.2": { + "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-win32-arm64-msvc@4.44.0": { - "integrity": "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==", + "@rollup/rollup-win32-arm64-msvc@4.44.2": { + "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", "os": ["win32"], "cpu": ["arm64"] }, - "@rollup/rollup-win32-ia32-msvc@4.44.0": { - "integrity": "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==", + "@rollup/rollup-win32-ia32-msvc@4.44.2": { + "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", "os": ["win32"], "cpu": ["ia32"] }, - "@rollup/rollup-win32-x64-msvc@4.44.0": { - "integrity": "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==", + "@rollup/rollup-win32-x64-msvc@4.44.2": { + "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", "os": ["win32"], "cpu": ["x64"] }, "@standard-schema/utils@0.3.0": { "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==" }, - "@tailwindcss/node@4.1.10": { - "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", + "@tailwindcss/node@4.1.11": { + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", "dependencies": [ "@ampproject/remapping", "enhanced-resolve", @@ -1569,53 +1579,53 @@ "tailwindcss" ] }, - "@tailwindcss/oxide-android-arm64@4.1.10": { - "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", + "@tailwindcss/oxide-android-arm64@4.1.11": { + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", "os": ["android"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-darwin-arm64@4.1.10": { - "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", + "@tailwindcss/oxide-darwin-arm64@4.1.11": { + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", "os": ["darwin"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-darwin-x64@4.1.10": { - "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", + "@tailwindcss/oxide-darwin-x64@4.1.11": { + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", "os": ["darwin"], "cpu": ["x64"] }, - "@tailwindcss/oxide-freebsd-x64@4.1.10": { - "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", + "@tailwindcss/oxide-freebsd-x64@4.1.11": { + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", "os": ["freebsd"], "cpu": ["x64"] }, - "@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10": { - "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", + "@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11": { + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", "os": ["linux"], "cpu": ["arm"] }, - "@tailwindcss/oxide-linux-arm64-gnu@4.1.10": { - "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", + "@tailwindcss/oxide-linux-arm64-gnu@4.1.11": { + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-linux-arm64-musl@4.1.10": { - "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", + "@tailwindcss/oxide-linux-arm64-musl@4.1.11": { + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", "os": ["linux"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-linux-x64-gnu@4.1.10": { - "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", + "@tailwindcss/oxide-linux-x64-gnu@4.1.11": { + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", "os": ["linux"], "cpu": ["x64"] }, - "@tailwindcss/oxide-linux-x64-musl@4.1.10": { - "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", + "@tailwindcss/oxide-linux-x64-musl@4.1.11": { + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", "os": ["linux"], "cpu": ["x64"] }, - "@tailwindcss/oxide-wasm32-wasi@4.1.10": { - "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", + "@tailwindcss/oxide-wasm32-wasi@4.1.11": { + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", "dependencies": [ "@emnapi/core", "@emnapi/runtime", @@ -1626,18 +1636,18 @@ ], "cpu": ["wasm32"] }, - "@tailwindcss/oxide-win32-arm64-msvc@4.1.10": { - "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", + "@tailwindcss/oxide-win32-arm64-msvc@4.1.11": { + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", "os": ["win32"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-win32-x64-msvc@4.1.10": { - "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", + "@tailwindcss/oxide-win32-x64-msvc@4.1.11": { + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", "os": ["win32"], "cpu": ["x64"] }, - "@tailwindcss/oxide@4.1.10": { - "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", + "@tailwindcss/oxide@4.1.11": { + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", "dependencies": [ "detect-libc", "tar" @@ -1658,8 +1668,8 @@ ], "scripts": true }, - "@tailwindcss/postcss@4.1.10": { - "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==", + "@tailwindcss/postcss@4.1.11": { + "integrity": "sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA==", "dependencies": [ "@alloc/quick-lru", "@tailwindcss/node", @@ -1671,8 +1681,8 @@ "@tanstack/history@1.121.34": { "integrity": "sha512-YL8dGi5ZU+xvtav2boRlw4zrRghkY6hvdcmHhA0RGSJ/CBgzv+cbADW9eYJLx74XMZvIQ1pp6VMbrpXnnM5gHA==" }, - "@tanstack/react-router-devtools@1.121.34_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-rqbgqTT5QaxeEX5oEI3K/9kDRRhCq3daszjZIWEWa9KKA8Fo4cE9F5OIQeXKdFu7QrIlHurlE7HB2uLkjgVviw==", + "@tanstack/react-router-devtools@1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-eRg6Ht6bLno+Eo2Gps3cfjp++Mvy0brc6qs81At4beKZsCkS7jlmqHgrq6pXdH3l2bAQ/Dhr8J9zXvzxvRxf/g==", "dependencies": [ "@tanstack/react-router", "@tanstack/router-devtools-core", @@ -1680,12 +1690,13 @@ "react-dom" ] }, - "@tanstack/react-router@1.121.34_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-nQYUXh459/YX9tDOGUqBb8yCiUw4JjcCf1o9wtb9fMxy3hnP0iQNU2TeV1A1N4KCGKXV3ZzkhpBb6sJe3kd43Q==", + "@tanstack/react-router@1.125.4_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-IIlDiFCR+RN/17dWtYKMYiJvH38tmtgTyciHkeZvr8vSWhThAeuwjzKneF4mQl3B//YHYcrFm7rZM59c24As/A==", "dependencies": [ "@tanstack/history", "@tanstack/react-store", "@tanstack/router-core", + "isbot", "jsesc", "react", "react-dom", @@ -1693,8 +1704,8 @@ "tiny-warning" ] }, - "@tanstack/react-store@0.7.1_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-qUTEKdId6QPWGiWyKAPf/gkN29scEsz6EUSJ0C3HgLMgaqTAyBsQ2sMCfGVcqb+kkhEXAdjleCgH6LAPD6f2sA==", + "@tanstack/react-store@0.7.3_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-3Dnqtbw9P2P0gw8uUM8WP2fFfg8XMDSZCTsywRPZe/XqqYW8PGkXKZTvP0AHkE4mpqP9Y43GpOg9vwO44azu6Q==", "dependencies": [ "@tanstack/store", "react", @@ -1702,8 +1713,8 @@ "use-sync-external-store" ] }, - "@tanstack/router-cli@1.121.37": { - "integrity": "sha512-Jc/YIBPBGgKt10wqquWMR3dntbUWSlhXaGCYFRb31SM+zRl+NSyOIhEO5zAm0oP4l605yyejs9gGj8BC9idn0Q==", + "@tanstack/router-cli@1.125.4": { + "integrity": "sha512-09DGnwDKsRdLmbAwstN2biJ7P37PeD/Fv2uDDIOfc+AlBw6gfq8byy0zIYFXmQCjSBmHwmS9A4XOmfzaDkfQng==", "dependencies": [ "@tanstack/router-generator", "chokidar", @@ -1711,16 +1722,19 @@ ], "bin": true }, - "@tanstack/router-core@1.121.34": { - "integrity": "sha512-CRH9dC8uLfFOKUGTbtOcMPv+weNVt2xs+me34KLX0Yja2yHG99oAUCBwamXsVQPpfjLFPYeJuKyo98+Mg+Ppeg==", + "@tanstack/router-core@1.125.4": { + "integrity": "sha512-tdgGI0Kwt3Lgs9ceLbG32NPh4I2H1T9t2TKjcS+I78sifm5rjTWV8lfqVRNrvMPk5ek60vXPOL2AHAUg6ohwsA==", "dependencies": [ "@tanstack/history", "@tanstack/store", - "tiny-invariant" + "cookie-es", + "jsesc", + "tiny-invariant", + "tiny-warning" ] }, - "@tanstack/router-devtools-core@1.121.34_@tanstack+router-core@1.121.34_solid-js@1.9.7__seroval@1.3.2_tiny-invariant@1.3.3": { - "integrity": "sha512-WAFYxJ7qViKxqkFmf+VsrtMT4TfYqdfWTBRhVU/6qi0k/+7TO2EHjl8/aGBhg6q0/IwO9wyGvcbDhJxm0DwWag==", + "@tanstack/router-devtools-core@1.125.4_@tanstack+router-core@1.125.4_solid-js@1.9.7__seroval@1.3.2_tiny-invariant@1.3.3": { + "integrity": "sha512-5QbCQCcJcN/M0NF2TARKqauJ8QeRuk7kyHQMCqOoSJWWGUVcDHEmcbg1ZCJevfPVZPgnUjV9mqDfCPTYWT8/+w==", "dependencies": [ "@tanstack/router-core", "clsx", @@ -1729,8 +1743,8 @@ "tiny-invariant" ] }, - "@tanstack/router-devtools@1.121.34_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-si51q0B/rcUDPn4I9uULy117yVryaNsC/sn7fgwxPbGREfQZT45TmjzTqAYPm3q0lbZumysEGRVhTkZuriwTjg==", + "@tanstack/router-devtools@1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-VpCxC80C+t+HNt8xuRGoXDwV+0c1LFDNzOdL/dPlYSuTZWLd8zwOEi49oMaNSLeGJFLwgQx7FLP020UvQO6pMg==", "dependencies": [ "@tanstack/react-router", "@tanstack/react-router-devtools", @@ -1740,8 +1754,8 @@ "react-dom" ] }, - "@tanstack/router-generator@1.121.37": { - "integrity": "sha512-d7IqEDf962uJFNPMWXfPr+kUpS3Cv72azZhBNMMVmZUox/h3VDGgQ6OUnWXHwnno4xqDoS/mx9huTUnItoewaw==", + "@tanstack/router-generator@1.125.4": { + "integrity": "sha512-jF71znMvpZxmkQF0MxfjKKyvXtft9NWRCVcLhb+6d/8nrVGNiEw+dsXn/CLpeRQLk7Mg/fsp/WipBql1dd3Qaw==", "dependencies": [ "@tanstack/router-core", "@tanstack/router-utils", @@ -1753,8 +1767,8 @@ "zod" ] }, - "@tanstack/router-plugin@1.121.37_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@24.0.4": { - "integrity": "sha512-zrolQ1J53xDUdxdO6MLfvnpVINnkIfOnEDVeX3kwHKBGQ5zyGdbolVcVVrJIRYQS0SJoWesn8cf8j+z+u8nZtg==", + "@tanstack/router-plugin@1.125.5_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.16.0": { + "integrity": "sha512-blik4+pgwv0PEGYTtkVy6USQBwbPVex1WOBBfRudOaBf8vnGe7lBoEHZi6fora8QlmdTsEVhqX6IHDXuf3pWaQ==", "dependencies": [ "@babel/core", "@babel/plugin-syntax-jsx", @@ -1770,40 +1784,15 @@ "babel-dead-code-elimination", "chokidar", "unplugin", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2", + "vite", "zod" ], "optionalPeers": [ "@tanstack/react-router", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2" + "vite" ] }, - "@tanstack/router-plugin@1.121.37_@tanstack+react-router@1.121.34__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@24.0.4_@types+node@22.15.33": { - "integrity": "sha512-zrolQ1J53xDUdxdO6MLfvnpVINnkIfOnEDVeX3kwHKBGQ5zyGdbolVcVVrJIRYQS0SJoWesn8cf8j+z+u8nZtg==", - "dependencies": [ - "@babel/core", - "@babel/plugin-syntax-jsx", - "@babel/plugin-syntax-typescript", - "@babel/template", - "@babel/traverse", - "@babel/types", - "@tanstack/react-router", - "@tanstack/router-core", - "@tanstack/router-generator", - "@tanstack/router-utils", - "@tanstack/virtual-file-routes", - "babel-dead-code-elimination", - "chokidar", - "unplugin", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33", - "zod" - ], - "optionalPeers": [ - "@tanstack/react-router", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33" - ] - }, - "@tanstack/router-utils@1.121.21_@babel+core@7.27.4": { + "@tanstack/router-utils@1.121.21_@babel+core@7.28.0": { "integrity": "sha512-u7ubq1xPBtNiU7Fm+EOWlVWdgFLzuKOa1thhqdscVn8R4dNMUd1VoOjZ6AKmLw201VaUhFtlX+u0pjzI6szX7A==", "dependencies": [ "@babel/core", @@ -1814,8 +1803,8 @@ "diff" ] }, - "@tanstack/store@0.7.1": { - "integrity": "sha512-PjUQKXEXhLYj2X5/6c1Xn/0/qKY0IVFxTJweopRfF26xfjVyb14yALydJrHupDh3/d+1WKmfEgZPBVCmDkzzwg==" + "@tanstack/store@0.7.2": { + "integrity": "sha512-RP80Z30BYiPX2Pyo0Nyw4s1SJFH2jyM6f9i3HfX4pA+gm5jsnYryscdq2aIQLnL4TaGuQMO+zXmN9nh1Qck+Pg==" }, "@tanstack/virtual-file-routes@1.121.21": { "integrity": "sha512-3nuYsTyaq6ZN7jRZ9z6Gj3GXZqBOqOT0yzd/WZ33ZFfv4yVNIvsa5Lw+M1j3sgyEAxKMqGu/FaNi7FCjr3yOdw==" @@ -3250,8 +3239,8 @@ "@types/deep-eql" ] }, - "@types/chrome@0.0.318": { - "integrity": "sha512-rrtyYQ1t+g7EyG0FejE+UXQBjSGUHGh0RIdXwUT/laPo9T724NOIgXA94ns6ewmNauwijYa5ck3+dBxWnHcynQ==", + "@types/chrome@0.0.329": { + "integrity": "sha512-jAZX4QMnAa1bTSWoQ5/EhhiY1t+1B7a5ZCY5ZEs61tWiQfxXAkfBSxCkQWhGxJoiq/4b4vtcmYEebNEmlLKecg==", "dependencies": [ "@types/filesystem", "@types/har-format" @@ -3301,14 +3290,20 @@ "@types/pbf" ] }, - "@types/node@22.15.33": { - "integrity": "sha512-wzoocdnnpSxZ+6CjW4ADCK1jVmd1S/J3ArNWfn8FDDQtRm8dkDg7TA+mvek2wNrfCgwuZxqEOiB9B1XCJ6+dbw==", + "@types/node@20.19.4": { + "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", + "dependencies": [ + "undici-types@6.21.0" + ] + }, + "@types/node@22.16.0": { + "integrity": "sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==", "dependencies": [ "undici-types@6.21.0" ] }, - "@types/node@24.0.4": { - "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==", + "@types/node@24.0.10": { + "integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==", "dependencies": [ "undici-types@7.8.0" ] @@ -3328,8 +3323,8 @@ "csstype" ] }, - "@types/serviceworker@0.0.133": { - "integrity": "sha512-lEyAbLUMztFbps2GVZ5mKIXl5+BZiGfOOA8JxN6KTiT91Ct31lSAHISKUl2+iOwmrUwNvWeI9rbsFxFqDZCghQ==" + "@types/serviceworker@0.0.140": { + "integrity": "sha512-9YBn/87nAamFtRCKEFZh2F+3Hs0UQzrxPgDbiqTgIS+F0LxbcVavgKtLhqSgSVF+OYtQM+fw8r3VXs7P1QpiXg==" }, "@types/supercluster@7.1.3": { "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", @@ -3346,6 +3341,9 @@ "@types/web-bluetooth@0.0.21": { "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==" }, + "@types/whatwg-mimetype@3.0.2": { + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==" + }, "@vis.gl/react-mapbox@8.0.4_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-NFk0vsWcNzSs0YCsVdt2100Zli9QWR+pje8DacpLkkGEAXFaJsFtI1oKD0Hatiate4/iAIW39SQHhgfhbeEPfQ==", "dependencies": [ @@ -3353,7 +3351,7 @@ "react-dom" ] }, - "@vis.gl/react-maplibre@8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "@vis.gl/react-maplibre@8.0.4_maplibre-gl@5.6.1_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-HwZyfLjEu+y1mUFvwDAkVxinGm8fEegaWN+O8np/WZ2Sqe5Lv6OXFpV6GWz9LOEvBYMbGuGk1FQdejo+4HCJ5w==", "dependencies": [ "@maplibre/maplibre-gl-style-spec@19.3.3", @@ -3365,19 +3363,7 @@ "maplibre-gl" ] }, - "@vitejs/plugin-react@4.6.0_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@babel+core@7.27.4_@types+node@24.0.4": { - "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", - "dependencies": [ - "@babel/core", - "@babel/plugin-transform-react-jsx-self", - "@babel/plugin-transform-react-jsx-source", - "@rolldown/pluginutils", - "@types/babel__core", - "react-refresh", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2" - ] - }, - "@vitejs/plugin-react@4.6.0_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@babel+core@7.27.4_@types+node@24.0.4_@types+node@22.15.33": { + "@vitejs/plugin-react@4.6.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_@types+node@22.16.0": { "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", "dependencies": [ "@babel/core", @@ -3386,7 +3372,7 @@ "@rolldown/pluginutils", "@types/babel__core", "react-refresh", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33" + "vite" ] }, "@vitest/expect@3.2.4": { @@ -3399,28 +3385,16 @@ "tinyrainbow" ] }, - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@types+node@24.0.4": { - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", - "dependencies": [ - "@vitest/spy", - "estree-walker", - "magic-string", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2" - ], - "optionalPeers": [ - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2" - ] - }, - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@types+node@24.0.4_@types+node@22.15.33": { + "@vitest/mocker@3.2.4_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@types+node@22.16.0": { "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dependencies": [ "@vitest/spy", "estree-walker", "magic-string", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33" + "vite" ], "optionalPeers": [ - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33" + "vite" ] }, "@vitest/pretty-format@3.2.4": { @@ -3581,8 +3555,8 @@ "cac@6.7.14": { "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==" }, - "caniuse-lite@1.0.30001726": { - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==" + "caniuse-lite@1.0.30001727": { + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==" }, "chai@5.2.0": { "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", @@ -3684,6 +3658,9 @@ "convert-source-map@2.0.0": { "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, + "cookie-es@1.2.2": { + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==" + }, "core-util-is@1.0.3": { "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, @@ -3765,8 +3742,8 @@ "earcut@3.0.1": { "integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==" }, - "electron-to-chromium@1.5.174": { - "integrity": "sha512-HE43yYdUUiJVjewV2A9EP8o89Kb4AqMKplMQP2IxEPUws1Etu/ZkdsgUDabUZ/WmbP4ZbvJDOcunvbBUPPIfmw==" + "electron-to-chromium@1.5.179": { + "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==" }, "emoji-regex@8.0.0": { "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" @@ -3787,8 +3764,8 @@ "es-module-lexer@1.7.0": { "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==" }, - "esbuild@0.25.5": { - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "esbuild@0.25.6": { + "integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==", "optionalDependencies": [ "@esbuild/aix-ppc64", "@esbuild/android-arm", @@ -3811,6 +3788,7 @@ "@esbuild/netbsd-x64", "@esbuild/openbsd-arm64", "@esbuild/openbsd-x64", + "@esbuild/openharmony-arm64", "@esbuild/sunos-x64", "@esbuild/win32-arm64", "@esbuild/win32-ia32", @@ -3832,8 +3810,8 @@ "@types/estree" ] }, - "expect-type@1.2.1": { - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==" + "expect-type@1.2.2": { + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==" }, "extend-shallow@2.0.1": { "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", @@ -3927,9 +3905,6 @@ "which" ] }, - "globals@11.12.0": { - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, "goober@2.1.16_csstype@3.1.3": { "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", "dependencies": [ @@ -3948,10 +3923,11 @@ ], "bin": true }, - "happy-dom@17.6.3": { - "integrity": "sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==", + "happy-dom@18.0.1": { + "integrity": "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==", "dependencies": [ - "webidl-conversions@7.0.0", + "@types/node@20.19.4", + "@types/whatwg-mimetype", "whatwg-mimetype" ] }, @@ -3976,8 +3952,8 @@ "cross-fetch" ] }, - "i18next@25.2.1_typescript@5.8.3": { - "integrity": "sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==", + "i18next@25.3.1_typescript@5.8.3": { + "integrity": "sha512-S4CPAx8LfMOnURnnJa8jFWvur+UX/LWcl6+61p9VV7SK2m0445JeBJ6tLD0D5SR0H29G4PYfWkEhivKG5p4RDg==", "dependencies": [ "@babel/runtime", "typescript" @@ -4046,6 +4022,9 @@ "isarray@1.0.0": { "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "isbot@5.1.28": { + "integrity": "sha512-qrOp4g3xj8YNse4biorv6O5ZShwsJM0trsoda4y7j/Su7ZtTTfVXFzbKkpgcSoDrHS8FcTuUwcU04YimZlZOxw==" + }, "isexe@3.1.1": { "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" }, @@ -4172,8 +4151,8 @@ "yallist@3.1.1" ] }, - "lucide-react@0.507.0_react@19.1.0": { - "integrity": "sha512-XfgE6gvAHwAtnbUvWiTTHx4S3VGR+cUJHEc0vrh9Ogu672I1Tue2+Cp/8JJqpytgcBHAB1FVI297W4XGNwc2dQ==", + "lucide-react@0.525.0_react@19.1.0": { + "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", "dependencies": [ "react" ] @@ -4188,8 +4167,8 @@ "@jridgewell/sourcemap-codec" ] }, - "maplibre-gl@5.4.0": { - "integrity": "sha512-ZVrtdFIhFAqt53H2k5Ssqn7QIKNI19fW+He5tr4loxZxWZffp1aZYY9ImNncAJaALU/NYlV6Eul7UVB56/N7WQ==", + "maplibre-gl@5.6.1": { + "integrity": "sha512-TTSfoTaF7RqKUR9wR5qDxCHH2J1XfZ1E85luiLOx0h8r50T/LnwAwwfV0WVNh9o8dA7rwt57Ucivf1emyeukXg==", "dependencies": [ "@mapbox/geojson-rewind", "@mapbox/jsonlint-lines-primitives", @@ -4333,8 +4312,8 @@ "potpack@2.0.0": { "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==" }, - "prettier@3.6.1": { - "integrity": "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==", + "prettier@3.6.2": { + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "bin": true }, "pretty-format@27.5.1": { @@ -4357,8 +4336,8 @@ "protocol-buffers-schema@3.6.0": { "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" }, - "qrcode-generator@1.5.1": { - "integrity": "sha512-u0zerMlMtKBgkDlDzWXG/7F7jo2En1d7bivC7V33HGqP62XxGiHGnbCJNkSCMxGfNlhXGBGEIamNMHbZ4P4mLg==" + "qrcode-generator@1.5.2": { + "integrity": "sha512-pItrW0Z9HnDBnFmgiNrY1uxRdri32Uh9EjNYLPVC2zZ3ZRIIEqBoDgm4DkvDwNNDHTK7FNkmr8zAa77BYc9xNw==" }, "quickselect@1.1.1": { "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" @@ -4395,14 +4374,14 @@ "react" ] }, - "react-hook-form@7.58.1_react@19.1.0": { - "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==", + "react-hook-form@7.60.0_react@19.1.0": { + "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", "dependencies": [ "react" ] }, - "react-i18next@15.5.3_i18next@25.2.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3": { - "integrity": "sha512-ypYmOKOnjqPEJZO4m1BI0kS8kWqkBNsKYyhVUfij0gvjy9xJNoG/VcGkxq5dRlVwzmrmY1BQMAmpbbUBLwC4Kw==", + "react-i18next@15.6.0_i18next@25.3.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3": { + "integrity": "sha512-W135dB0rDfiFmbMipC17nOhGdttO5mzH8BivY+2ybsQBbXvxWIwl3cmeH3T9d+YPBSJu/ouyJKFJTtkK7rJofw==", "dependencies": [ "@babel/runtime", "html-parse-stringify", @@ -4417,7 +4396,7 @@ "react-is@17.0.2": { "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "react-map-gl@8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "react-map-gl@8.0.4_maplibre-gl@5.6.1_react@19.1.0_react-dom@19.1.0__react@19.1.0": { "integrity": "sha512-SHdpvFIvswsZBg6BCPcwY/nbKuCo3sJM1Cj7Sd+gA3gFRFOixD+KtZ2XSuUWq2WySL2emYEXEgrLZoXsV4Ut4Q==", "dependencies": [ "@vis.gl/react-mapbox", @@ -4548,8 +4527,8 @@ "robust-predicates@3.0.2": { "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" }, - "rollup@4.44.0": { - "integrity": "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==", + "rollup@4.44.2": { + "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", "dependencies": [ "@types/estree" ], @@ -4758,14 +4737,14 @@ "tailwind-merge@3.3.1": { "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==" }, - "tailwindcss-animate@1.0.7_tailwindcss@4.1.10": { + "tailwindcss-animate@1.0.7_tailwindcss@4.1.11": { "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", "dependencies": [ "tailwindcss" ] }, - "tailwindcss@4.1.10": { - "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==" + "tailwindcss@4.1.11": { + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==" }, "tapable@2.2.2": { "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==" @@ -4959,32 +4938,21 @@ "util-deprecate@1.0.2": { "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "vite-node@3.2.4_@types+node@24.0.4": { + "vite-node@3.2.4_@types+node@22.16.0": { "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dependencies": [ "cac", "debug", "es-module-lexer", "pathe", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2" + "vite" ], "bin": true }, - "vite-node@3.2.4_@types+node@24.0.4_@types+node@22.15.33": { - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "vite@7.0.2_@types+node@22.16.0_picomatch@4.0.2": { + "integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==", "dependencies": [ - "cac", - "debug", - "es-module-lexer", - "pathe", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33" - ], - "bin": true - }, - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2": { - "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", - "dependencies": [ - "@types/node@24.0.4", + "@types/node@22.16.0", "esbuild", "fdir", "picomatch@4.0.2", @@ -4996,36 +4964,17 @@ "fsevents" ], "optionalPeers": [ - "@types/node@24.0.4" + "@types/node@22.16.0" ], "bin": true }, - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33": { - "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", - "dependencies": [ - "@types/node@22.15.33", - "esbuild", - "fdir", - "picomatch@4.0.2", - "postcss", - "rollup", - "tinyglobby" - ], - "optionalDependencies": [ - "fsevents" - ], - "optionalPeers": [ - "@types/node@22.15.33" - ], - "bin": true - }, - "vitest@3.2.4_@types+node@24.0.4_happy-dom@17.6.3_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2": { + "vitest@3.2.4_@types+node@22.16.0_happy-dom@18.0.1_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2": { "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dependencies": [ "@types/chai", - "@types/node@24.0.4", + "@types/node@22.16.0", "@vitest/expect", - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@types+node@24.0.4", + "@vitest/mocker", "@vitest/pretty-format", "@vitest/runner", "@vitest/snapshot", @@ -5044,47 +4993,12 @@ "tinyglobby", "tinypool", "tinyrainbow", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2", - "vite-node@3.2.4_@types+node@24.0.4", + "vite", + "vite-node", "why-is-node-running" ], "optionalPeers": [ - "@types/node@24.0.4", - "happy-dom" - ], - "bin": true - }, - "vitest@3.2.4_@types+node@24.0.4_happy-dom@17.6.3_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@types+node@22.15.33": { - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", - "dependencies": [ - "@types/chai", - "@types/node@22.15.33", - "@vitest/expect", - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@24.0.4__picomatch@4.0.2_@types+node@24.0.4_@types+node@22.15.33", - "@vitest/pretty-format", - "@vitest/runner", - "@vitest/snapshot", - "@vitest/spy", - "@vitest/utils", - "chai", - "debug", - "expect-type", - "happy-dom", - "magic-string", - "pathe", - "picomatch@4.0.2", - "std-env", - "tinybench", - "tinyexec", - "tinyglobby", - "tinypool", - "tinyrainbow", - "vite@7.0.0_@types+node@24.0.4_picomatch@4.0.2_@types+node@22.15.33", - "vite-node@3.2.4_@types+node@24.0.4_@types+node@22.15.33", - "why-is-node-running" - ], - "optionalPeers": [ - "@types/node@22.15.33", + "@types/node@22.16.0", "happy-dom" ], "bin": true @@ -5103,9 +5017,6 @@ "webidl-conversions@3.0.1": { "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "webidl-conversions@7.0.0": { - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" - }, "webpack-virtual-modules@0.6.2": { "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==" }, @@ -5116,7 +5027,7 @@ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": [ "tr46", - "webidl-conversions@3.0.1" + "webidl-conversions" ] }, "which@4.0.0": { @@ -5172,14 +5083,14 @@ "yargs-parser" ] }, - "zod@3.25.67": { - "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==" + "zod@3.25.75": { + "integrity": "sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg==" }, "zone.js@0.8.29": { "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" }, - "zustand@5.0.5_@types+react@19.1.8_immer@10.1.1_react@19.1.0": { - "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==", + "zustand@5.0.6_@types+react@19.1.8_immer@10.1.1_react@19.1.0": { + "integrity": "sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A==", "dependencies": [ "@types/react", "immer", @@ -5224,49 +5135,49 @@ ], "packageJson": { "dependencies": [ - "npm:@bufbuild/protobuf@^2.2.5", + "npm:@bufbuild/protobuf@^2.6.0", "npm:@hookform/resolvers@^5.1.1", "npm:@jsr/meshtastic__core@2.6.4", "npm:@jsr/meshtastic__js@2.6.0-0", "npm:@jsr/meshtastic__transport-http@*", "npm:@jsr/meshtastic__transport-web-bluetooth@*", "npm:@jsr/meshtastic__transport-web-serial@*", - "npm:@noble/curves@^1.9.0", - "npm:@radix-ui/react-accordion@^1.2.8", - "npm:@radix-ui/react-checkbox@^1.2.3", - "npm:@radix-ui/react-dialog@^1.1.11", - "npm:@radix-ui/react-dropdown-menu@^2.1.12", - "npm:@radix-ui/react-label@^2.1.4", - "npm:@radix-ui/react-menubar@^1.1.12", - "npm:@radix-ui/react-popover@^1.1.11", - "npm:@radix-ui/react-scroll-area@^1.2.6", - "npm:@radix-ui/react-select@^2.2.2", - "npm:@radix-ui/react-separator@^1.1.4", - "npm:@radix-ui/react-slider@^1.3.2", - "npm:@radix-ui/react-switch@^1.2.2", - "npm:@radix-ui/react-tabs@^1.1.9", - "npm:@radix-ui/react-toast@^1.2.11", - "npm:@radix-ui/react-toggle-group@^1.1.9", - "npm:@radix-ui/react-tooltip@^1.2.4", - "npm:@tailwindcss/postcss@^4.1.5", - "npm:@tanstack/react-router-devtools@^1.120.16", - "npm:@tanstack/react-router@^1.120.15", - "npm:@tanstack/router-cli@^1.121.37", - "npm:@tanstack/router-devtools@^1.120.15", - "npm:@tanstack/router-plugin@^1.120.15", + "npm:@noble/curves@^1.9.2", + "npm:@radix-ui/react-accordion@^1.2.11", + "npm:@radix-ui/react-checkbox@^1.3.2", + "npm:@radix-ui/react-dialog@^1.1.14", + "npm:@radix-ui/react-dropdown-menu@^2.1.15", + "npm:@radix-ui/react-label@^2.1.7", + "npm:@radix-ui/react-menubar@^1.1.15", + "npm:@radix-ui/react-popover@^1.1.14", + "npm:@radix-ui/react-scroll-area@^1.2.9", + "npm:@radix-ui/react-select@^2.2.5", + "npm:@radix-ui/react-separator@^1.1.7", + "npm:@radix-ui/react-slider@^1.3.5", + "npm:@radix-ui/react-switch@^1.2.5", + "npm:@radix-ui/react-tabs@^1.1.12", + "npm:@radix-ui/react-toast@^1.2.14", + "npm:@radix-ui/react-toggle-group@^1.1.10", + "npm:@radix-ui/react-tooltip@^1.2.7", + "npm:@tailwindcss/postcss@^4.1.11", + "npm:@tanstack/react-router-devtools@^1.125.4", + "npm:@tanstack/react-router@^1.125.4", + "npm:@tanstack/router-cli@^1.125.4", + "npm:@tanstack/router-devtools@^1.125.4", + "npm:@tanstack/router-plugin@^1.125.5", "npm:@testing-library/jest-dom@^6.6.3", "npm:@testing-library/react@^16.3.0", "npm:@testing-library/user-event@^14.6.1", "npm:@turf/turf@^7.2.0", - "npm:@types/chrome@^0.0.318", + "npm:@types/chrome@^0.0.329", "npm:@types/js-cookie@^3.0.6", - "npm:@types/node@^24.0.4", - "npm:@types/react-dom@^19.1.3", - "npm:@types/react@^19.1.2", - "npm:@types/serviceworker@^0.0.133", + "npm:@types/node@^24.0.10", + "npm:@types/react-dom@^19.1.6", + "npm:@types/react@^19.1.8", + "npm:@types/serviceworker@^0.0.140", "npm:@types/w3c-web-serial@^1.0.8", "npm:@types/web-bluetooth@^0.0.21", - "npm:@vitejs/plugin-react@^4.4.1", + "npm:@vitejs/plugin-react@^4.6.0", "npm:autoprefixer@^10.4.21", "npm:base64-js@^1.5.1", "npm:class-variance-authority@~0.7.1", @@ -5274,35 +5185,35 @@ "npm:cmdk@^1.1.1", "npm:crypto-random-string@5", "npm:gzipper@^8.2.1", - "npm:happy-dom@^17.4.6", - "npm:i18next-browser-languagedetector@^8.1.0", + "npm:happy-dom@^18.0.1", + "npm:i18next-browser-languagedetector@^8.2.0", "npm:i18next-http-backend@^3.0.2", - "npm:i18next@^25.2.0", - "npm:idb-keyval@^6.2.1", + "npm:i18next@^25.3.1", + "npm:idb-keyval@^6.2.2", "npm:immer@^10.1.1", "npm:js-cookie@^3.0.5", - "npm:lucide-react@0.507", - "npm:maplibre-gl@5.4.0", - "npm:postcss@^8.5.3", + "npm:lucide-react@0.525", + "npm:maplibre-gl@5.6.1", + "npm:postcss@^8.5.6", "npm:react-dom@^19.1.0", "npm:react-error-boundary@6", - "npm:react-hook-form@^7.56.2", - "npm:react-i18next@^15.5.1", + "npm:react-hook-form@^7.60.0", + "npm:react-i18next@^15.6.0", "npm:react-map-gl@8.0.4", "npm:react-qrcode-logo@3", "npm:react@^19.1.0", "npm:rfc4648@^1.5.4", "npm:simple-git-hooks@^2.13.0", - "npm:tailwind-merge@^3.2.0", + "npm:tailwind-merge@^3.3.1", "npm:tailwindcss-animate@^1.0.7", - "npm:tailwindcss@^4.1.5", + "npm:tailwindcss@^4.1.11", "npm:tar@^7.4.3", "npm:testing-library@^0.0.2", "npm:typescript@^5.8.3", "npm:vite@7", "npm:vitest@^3.2.4", - "npm:zod@^3.25.67", - "npm:zustand@5.0.5" + "npm:zod@^3.25.75", + "npm:zustand@5.0.6" ] } } diff --git a/packages/web/README.md b/packages/web/README.md index c1be319b..b64adf57 100644 --- a/packages/web/README.md +++ b/packages/web/README.md @@ -60,8 +60,8 @@ Our release process follows these guidelines: - **Pre-releases:** A pre-release is typically issued mid-month for testing and early adoption. - **Nightly Builds:** An experimental Docker image containing the latest - cutting-edge features and fixes is automatically built nightly from the - `main` branch. + cutting-edge features and fixes is automatically built nightly from the `main` + branch. ### Nightly Builds diff --git a/packages/web/deno.json b/packages/web/deno.json index 49630543..a3da671b 100644 --- a/packages/web/deno.json +++ b/packages/web/deno.json @@ -8,6 +8,20 @@ "@layouts/": "./src/layouts/", "@std/path": "jsr:@std/path@^1.1.0" }, + "tasks": { + "build": "vite build", + "build:analyze": "BUNDLE_ANALYZE=true deno task build", + "lint": "deno lint src/", + "lint:fix": "deno lint --fix src/", + "format": "deno fmt src/", + "dev": "deno task dev:ui", + "dev:ui": "VITE_APP_VERSION=development deno run -A npm:vite dev", + "test": "deno run -A npm:vitest", + "check": "deno check", + "preview": "deno run -A npm:vite preview", + "generate:routes": "deno run -A npm:@tanstack/router-cli generate --outDir src/ routes --rootRoutePath /", + "package": "gzipper c -i html,js,css,png,ico,svg,json,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ ." + }, "include": ["src", "./vite-env.d.ts"], "compilerOptions": { "lib": [ diff --git a/packages/web/deno.lock b/packages/web/deno.lock deleted file mode 100644 index 117a1d36..00000000 --- a/packages/web/deno.lock +++ /dev/null @@ -1,7229 +0,0 @@ -{ - "version": "5", - "specifiers": { - "jsr:@std/path@^1.1.0": "1.1.0", - "npm:@bufbuild/protobuf@^2.2.5": "2.5.2", - "npm:@hookform/resolvers@^5.1.1": "5.1.1_react-hook-form@7.58.1__react@19.1.0_react@19.1.0", - "npm:@jsr/meshtastic__core@2.6.4": "2.6.4", - "npm:@jsr/meshtastic__js@2.6.0-0": "2.6.0-0", - "npm:@jsr/meshtastic__transport-http@*": "0.2.1", - "npm:@jsr/meshtastic__transport-web-bluetooth@*": "0.1.2", - "npm:@jsr/meshtastic__transport-web-serial@*": "0.2.1", - "npm:@noble/curves@^1.9.0": "1.9.2", - "npm:@radix-ui/react-accordion@^1.2.8": "1.2.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-checkbox@^1.2.3": "1.3.2_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-dialog@^1.1.11": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-dropdown-menu@^2.1.12": "2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-label@^2.1.4": "2.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-menubar@^1.1.12": "1.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-popover@^1.1.11": "1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-scroll-area@^1.2.6": "1.2.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-select@^2.2.2": "2.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-separator@^1.1.4": "1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-slider@^1.3.2": "1.3.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-switch@^1.2.2": "1.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-tabs@^1.1.9": "1.1.12_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-toast@^1.2.11": "1.2.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-toggle-group@^1.1.9": "1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@radix-ui/react-tooltip@^1.2.4": "1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tailwindcss/postcss@^4.1.5": "4.1.10", - "npm:@tanstack/react-router-devtools@^1.120.16": "1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/react-router@^1.120.15": "1.121.27_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-cli@*": "1.121.37", - "npm:@tanstack/router-cli@^1.121.37": "1.121.37", - "npm:@tanstack/router-devtools@^1.120.15": "1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-plugin@^1.120.15": "1.121.37_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.32_@types+node@22.15.15", - "npm:@testing-library/jest-dom@^6.6.3": "6.6.3", - "npm:@testing-library/react@^16.3.0": "16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@testing-library/user-event@^14.6.1": "14.6.1_@testing-library+dom@10.4.0", - "npm:@turf/turf@^7.2.0": "7.2.0", - "npm:@types/chrome@^0.0.318": "0.0.318", - "npm:@types/js-cookie@^3.0.6": "3.0.6", - "npm:@types/node@*": "22.15.15", - "npm:@types/node@^22.15.3": "22.15.32", - "npm:@types/react-dom@^19.1.3": "19.1.6_@types+react@19.1.8", - "npm:@types/react@^19.1.2": "19.1.8", - "npm:@types/serviceworker@^0.0.133": "0.0.133", - "npm:@types/w3c-web-serial@*": "1.0.8", - "npm:@types/w3c-web-serial@^1.0.8": "1.0.8", - "npm:@types/web-bluetooth@*": "0.0.21", - "npm:@types/web-bluetooth@^0.0.21": "0.0.21", - "npm:@vitejs/plugin-react@^4.4.1": "4.6.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_@types+node@22.15.32_@types+node@22.15.15", - "npm:autoprefixer@^10.4.21": "10.4.21_postcss@8.5.6", - "npm:base64-js@^1.5.1": "1.5.1", - "npm:class-variance-authority@~0.7.1": "0.7.1", - "npm:clsx@^2.1.1": "2.1.1", - "npm:cmdk@^1.1.1": "1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8", - "npm:crypto-random-string@5": "5.0.0", - "npm:gzipper@8.2.1": "8.2.1", - "npm:gzipper@^8.2.1": "8.2.1", - "npm:happy-dom@^17.4.6": "17.6.3", - "npm:i18next-browser-languagedetector@^8.1.0": "8.2.0", - "npm:i18next-http-backend@^3.0.2": "3.0.2", - "npm:i18next@^25.2.0": "25.2.1_typescript@5.8.3", - "npm:idb-keyval@^6.2.1": "6.2.2", - "npm:immer@^10.1.1": "10.1.1", - "npm:js-cookie@^3.0.5": "3.0.5", - "npm:lucide-react@0.507": "0.507.0_react@19.1.0", - "npm:maplibre-gl@5.4.0": "5.4.0", - "npm:postcss@^8.5.3": "8.5.6", - "npm:react-dom@^19.1.0": "19.1.0_react@19.1.0", - "npm:react-error-boundary@6": "6.0.0_react@19.1.0", - "npm:react-hook-form@^7.56.2": "7.58.1_react@19.1.0", - "npm:react-i18next@^15.5.1": "15.5.3_i18next@25.2.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3", - "npm:react-map-gl@8.0.4": "8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:react-qrcode-logo@3": "3.0.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:react@^19.1.0": "19.1.0", - "npm:rfc4648@^1.5.4": "1.5.4", - "npm:simple-git-hooks@^2.13.0": "2.13.0", - "npm:tailwind-merge@^3.2.0": "3.3.1", - "npm:tailwindcss-animate@^1.0.7": "1.0.7_tailwindcss@4.1.10", - "npm:tailwindcss@^4.1.5": "4.1.10", - "npm:tar@^7.4.3": "7.4.3", - "npm:testing-library@^0.0.2": "0.0.2_@angular+common@6.1.10__@angular+core@6.1.10___rxjs@6.6.7___zone.js@0.8.29__rxjs@6.6.7_@angular+core@6.1.10__rxjs@6.6.7__zone.js@0.8.29", - "npm:typescript@^5.8.3": "5.8.3", - "npm:vite-plugin-pwa@1": "1.0.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.4__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.32_@types+node@22.15.15", - "npm:vite@*": "7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15", - "npm:vite@7": "7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15", - "npm:vitest@*": "3.2.4_@types+node@22.15.32_happy-dom@17.6.3_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.15", - "npm:vitest@^3.2.4": "3.2.4_@types+node@22.15.32_happy-dom@17.6.3_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.15", - "npm:zod@^3.25.67": "3.25.67", - "npm:zustand@5.0.5": "5.0.5_@types+react@19.1.8_immer@10.1.1_react@19.1.0" - }, - "jsr": { - "@std/path@1.1.0": { - "integrity": "ddc94f8e3c275627281cbc23341df6b8bcc874d70374f75fec2533521e3d6886" - } - }, - "npm": { - "@adobe/css-tools@4.4.3": { - "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==" - }, - "@alloc/quick-lru@5.2.0": { - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==" - }, - "@ampproject/remapping@2.3.0": { - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": [ - "@jridgewell/gen-mapping", - "@jridgewell/trace-mapping" - ] - }, - "@angular/common@6.1.10_@angular+core@6.1.10__rxjs@6.6.7__zone.js@0.8.29_rxjs@6.6.7": { - "integrity": "sha512-73xxTSYJNKfiJ7C1Ajg+sz5l8y+blb/vNgHYg7O3yem5zLBnfPpidJ1UGg4W4d2Y+jwUVJbZKh8SKJarqAJVUQ==", - "dependencies": [ - "@angular/core", - "rxjs", - "tslib@1.14.1" - ] - }, - "@angular/core@6.1.10_rxjs@6.6.7_zone.js@0.8.29": { - "integrity": "sha512-61l3rIQTVdT45eOf6/fBJIeVmV10mcrxqS4N/1OWkuDT29YSJTZSxGcv8QjAyyutuhcqWWpO6gVRkN07rWmkPg==", - "dependencies": [ - "rxjs", - "tslib@1.14.1", - "zone.js" - ] - }, - "@apideck/better-ajv-errors@0.3.6_ajv@8.17.1": { - "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", - "dependencies": [ - "ajv", - "json-schema", - "jsonpointer", - "leven" - ] - }, - "@babel/code-frame@7.27.1": { - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dependencies": [ - "@babel/helper-validator-identifier", - "js-tokens@4.0.0", - "picocolors" - ] - }, - "@babel/compat-data@7.27.5": { - "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==" - }, - "@babel/core@7.27.4": { - "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", - "dependencies": [ - "@ampproject/remapping", - "@babel/code-frame", - "@babel/generator", - "@babel/helper-compilation-targets", - "@babel/helper-module-transforms", - "@babel/helpers", - "@babel/parser", - "@babel/template", - "@babel/traverse", - "@babel/types", - "convert-source-map", - "debug", - "gensync", - "json5", - "semver" - ] - }, - "@babel/generator@7.27.5": { - "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", - "dependencies": [ - "@babel/parser", - "@babel/types", - "@jridgewell/gen-mapping", - "@jridgewell/trace-mapping", - "jsesc@3.1.0" - ] - }, - "@babel/helper-annotate-as-pure@7.27.3": { - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dependencies": [ - "@babel/types" - ] - }, - "@babel/helper-compilation-targets@7.27.2": { - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dependencies": [ - "@babel/compat-data", - "@babel/helper-validator-option", - "browserslist", - "lru-cache", - "semver" - ] - }, - "@babel/helper-create-class-features-plugin@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-member-expression-to-functions", - "@babel/helper-optimise-call-expression", - "@babel/helper-replace-supers", - "@babel/helper-skip-transparent-expression-wrappers", - "@babel/traverse", - "semver" - ] - }, - "@babel/helper-create-regexp-features-plugin@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "regexpu-core", - "semver" - ] - }, - "@babel/helper-define-polyfill-provider@0.6.4_@babel+core@7.27.4": { - "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", - "dependencies": [ - "@babel/core", - "@babel/helper-compilation-targets", - "@babel/helper-plugin-utils", - "debug", - "lodash.debounce", - "resolve" - ] - }, - "@babel/helper-member-expression-to-functions@7.27.1": { - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", - "dependencies": [ - "@babel/traverse", - "@babel/types" - ] - }, - "@babel/helper-module-imports@7.27.1": { - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dependencies": [ - "@babel/traverse", - "@babel/types" - ] - }, - "@babel/helper-module-transforms@7.27.3_@babel+core@7.27.4": { - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-imports", - "@babel/helper-validator-identifier", - "@babel/traverse" - ] - }, - "@babel/helper-optimise-call-expression@7.27.1": { - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dependencies": [ - "@babel/types" - ] - }, - "@babel/helper-plugin-utils@7.27.1": { - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==" - }, - "@babel/helper-remap-async-to-generator@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-wrap-function", - "@babel/traverse" - ] - }, - "@babel/helper-replace-supers@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", - "dependencies": [ - "@babel/core", - "@babel/helper-member-expression-to-functions", - "@babel/helper-optimise-call-expression", - "@babel/traverse" - ] - }, - "@babel/helper-skip-transparent-expression-wrappers@7.27.1": { - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dependencies": [ - "@babel/traverse", - "@babel/types" - ] - }, - "@babel/helper-string-parser@7.27.1": { - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" - }, - "@babel/helper-validator-identifier@7.27.1": { - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==" - }, - "@babel/helper-validator-option@7.27.1": { - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==" - }, - "@babel/helper-wrap-function@7.27.1": { - "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", - "dependencies": [ - "@babel/template", - "@babel/traverse", - "@babel/types" - ] - }, - "@babel/helpers@7.27.6": { - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", - "dependencies": [ - "@babel/template", - "@babel/types" - ] - }, - "@babel/parser@7.27.5": { - "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", - "dependencies": [ - "@babel/types" - ], - "bin": true - }, - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/traverse" - ] - }, - "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-skip-transparent-expression-wrappers", - "@babel/plugin-transform-optional-chaining" - ] - }, - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/traverse" - ] - }, - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2_@babel+core@7.27.4": { - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dependencies": [ - "@babel/core" - ] - }, - "@babel/plugin-syntax-import-assertions@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-syntax-import-attributes@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-syntax-typescript@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-syntax-unicode-sets-regex@7.18.6_@babel+core@7.27.4": { - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-arrow-functions@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-async-generator-functions@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-remap-async-to-generator", - "@babel/traverse" - ] - }, - "@babel/plugin-transform-async-to-generator@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-imports", - "@babel/helper-plugin-utils", - "@babel/helper-remap-async-to-generator" - ] - }, - "@babel/plugin-transform-block-scoped-functions@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-block-scoping@7.27.5_@babel+core@7.27.4": { - "integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-class-properties@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-class-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-class-static-block@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-class-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-classes@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-compilation-targets", - "@babel/helper-plugin-utils", - "@babel/helper-replace-supers", - "@babel/traverse", - "globals" - ] - }, - "@babel/plugin-transform-computed-properties@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/template" - ] - }, - "@babel/plugin-transform-destructuring@7.27.3_@babel+core@7.27.4": { - "integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-dotall-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-duplicate-keys@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-dynamic-import@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-exponentiation-operator@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-export-namespace-from@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-for-of@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-skip-transparent-expression-wrappers" - ] - }, - "@babel/plugin-transform-function-name@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-compilation-targets", - "@babel/helper-plugin-utils", - "@babel/traverse" - ] - }, - "@babel/plugin-transform-json-strings@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-literals@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-logical-assignment-operators@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-member-expression-literals@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-modules-amd@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-transforms", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-modules-commonjs@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-transforms", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-modules-systemjs@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-transforms", - "@babel/helper-plugin-utils", - "@babel/helper-validator-identifier", - "@babel/traverse" - ] - }, - "@babel/plugin-transform-modules-umd@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-transforms", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-named-capturing-groups-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-new-target@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-nullish-coalescing-operator@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-numeric-separator@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-object-rest-spread@7.27.3_@babel+core@7.27.4": { - "integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-compilation-targets", - "@babel/helper-plugin-utils", - "@babel/plugin-transform-destructuring", - "@babel/plugin-transform-parameters" - ] - }, - "@babel/plugin-transform-object-super@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-replace-supers" - ] - }, - "@babel/plugin-transform-optional-catch-binding@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-optional-chaining@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-skip-transparent-expression-wrappers" - ] - }, - "@babel/plugin-transform-parameters@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-private-methods@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-class-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-private-property-in-object@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-create-class-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-property-literals@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-react-jsx-self@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-react-jsx-source@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-regenerator@7.27.5_@babel+core@7.27.4": { - "integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-regexp-modifiers@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-reserved-words@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-shorthand-properties@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-spread@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-skip-transparent-expression-wrappers" - ] - }, - "@babel/plugin-transform-sticky-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-template-literals@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-typeof-symbol@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-typescript@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==", - "dependencies": [ - "@babel/core", - "@babel/helper-annotate-as-pure", - "@babel/helper-create-class-features-plugin", - "@babel/helper-plugin-utils", - "@babel/helper-skip-transparent-expression-wrappers", - "@babel/plugin-syntax-typescript" - ] - }, - "@babel/plugin-transform-unicode-escapes@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-unicode-property-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-unicode-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/plugin-transform-unicode-sets-regex@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", - "dependencies": [ - "@babel/core", - "@babel/helper-create-regexp-features-plugin", - "@babel/helper-plugin-utils" - ] - }, - "@babel/preset-env@7.27.2_@babel+core@7.27.4": { - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", - "dependencies": [ - "@babel/compat-data", - "@babel/core", - "@babel/helper-compilation-targets", - "@babel/helper-plugin-utils", - "@babel/helper-validator-option", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key", - "@babel/plugin-bugfix-safari-class-field-initializer-scope", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly", - "@babel/plugin-proposal-private-property-in-object", - "@babel/plugin-syntax-import-assertions", - "@babel/plugin-syntax-import-attributes", - "@babel/plugin-syntax-unicode-sets-regex", - "@babel/plugin-transform-arrow-functions", - "@babel/plugin-transform-async-generator-functions", - "@babel/plugin-transform-async-to-generator", - "@babel/plugin-transform-block-scoped-functions", - "@babel/plugin-transform-block-scoping", - "@babel/plugin-transform-class-properties", - "@babel/plugin-transform-class-static-block", - "@babel/plugin-transform-classes", - "@babel/plugin-transform-computed-properties", - "@babel/plugin-transform-destructuring", - "@babel/plugin-transform-dotall-regex", - "@babel/plugin-transform-duplicate-keys", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex", - "@babel/plugin-transform-dynamic-import", - "@babel/plugin-transform-exponentiation-operator", - "@babel/plugin-transform-export-namespace-from", - "@babel/plugin-transform-for-of", - "@babel/plugin-transform-function-name", - "@babel/plugin-transform-json-strings", - "@babel/plugin-transform-literals", - "@babel/plugin-transform-logical-assignment-operators", - "@babel/plugin-transform-member-expression-literals", - "@babel/plugin-transform-modules-amd", - "@babel/plugin-transform-modules-commonjs", - "@babel/plugin-transform-modules-systemjs", - "@babel/plugin-transform-modules-umd", - "@babel/plugin-transform-named-capturing-groups-regex", - "@babel/plugin-transform-new-target", - "@babel/plugin-transform-nullish-coalescing-operator", - "@babel/plugin-transform-numeric-separator", - "@babel/plugin-transform-object-rest-spread", - "@babel/plugin-transform-object-super", - "@babel/plugin-transform-optional-catch-binding", - "@babel/plugin-transform-optional-chaining", - "@babel/plugin-transform-parameters", - "@babel/plugin-transform-private-methods", - "@babel/plugin-transform-private-property-in-object", - "@babel/plugin-transform-property-literals", - "@babel/plugin-transform-regenerator", - "@babel/plugin-transform-regexp-modifiers", - "@babel/plugin-transform-reserved-words", - "@babel/plugin-transform-shorthand-properties", - "@babel/plugin-transform-spread", - "@babel/plugin-transform-sticky-regex", - "@babel/plugin-transform-template-literals", - "@babel/plugin-transform-typeof-symbol", - "@babel/plugin-transform-unicode-escapes", - "@babel/plugin-transform-unicode-property-regex", - "@babel/plugin-transform-unicode-regex", - "@babel/plugin-transform-unicode-sets-regex", - "@babel/preset-modules", - "babel-plugin-polyfill-corejs2", - "babel-plugin-polyfill-corejs3", - "babel-plugin-polyfill-regenerator", - "core-js-compat", - "semver" - ] - }, - "@babel/preset-modules@0.1.6-no-external-plugins_@babel+core@7.27.4": { - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/types", - "esutils" - ] - }, - "@babel/preset-typescript@7.27.1_@babel+core@7.27.4": { - "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-plugin-utils", - "@babel/helper-validator-option", - "@babel/plugin-syntax-jsx", - "@babel/plugin-transform-modules-commonjs", - "@babel/plugin-transform-typescript" - ] - }, - "@babel/runtime@7.27.6": { - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==" - }, - "@babel/template@7.27.2": { - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dependencies": [ - "@babel/code-frame", - "@babel/parser", - "@babel/types" - ] - }, - "@babel/traverse@7.27.4": { - "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", - "dependencies": [ - "@babel/code-frame", - "@babel/generator", - "@babel/parser", - "@babel/template", - "@babel/types", - "debug", - "globals" - ] - }, - "@babel/types@7.27.6": { - "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", - "dependencies": [ - "@babel/helper-string-parser", - "@babel/helper-validator-identifier" - ] - }, - "@bufbuild/protobuf@2.5.2": { - "integrity": "sha512-foZ7qr0IsUBjzWIq+SuBLfdQCpJ1j8cTuNNT4owngTHoN5KsJb8L9t65fzz7SCeSWzescoOil/0ldqiL041ABg==" - }, - "@emnapi/core@1.4.3": { - "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", - "dependencies": [ - "@emnapi/wasi-threads", - "tslib@2.8.1" - ] - }, - "@emnapi/runtime@1.4.3": { - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", - "dependencies": [ - "tslib@2.8.1" - ] - }, - "@emnapi/wasi-threads@1.0.2": { - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", - "dependencies": [ - "tslib@2.8.1" - ] - }, - "@esbuild/aix-ppc64@0.25.5": { - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", - "os": ["aix"], - "cpu": ["ppc64"] - }, - "@esbuild/android-arm64@0.25.5": { - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", - "os": ["android"], - "cpu": ["arm64"] - }, - "@esbuild/android-arm@0.25.5": { - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", - "os": ["android"], - "cpu": ["arm"] - }, - "@esbuild/android-x64@0.25.5": { - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", - "os": ["android"], - "cpu": ["x64"] - }, - "@esbuild/darwin-arm64@0.25.5": { - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", - "os": ["darwin"], - "cpu": ["arm64"] - }, - "@esbuild/darwin-x64@0.25.5": { - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", - "os": ["darwin"], - "cpu": ["x64"] - }, - "@esbuild/freebsd-arm64@0.25.5": { - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", - "os": ["freebsd"], - "cpu": ["arm64"] - }, - "@esbuild/freebsd-x64@0.25.5": { - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", - "os": ["freebsd"], - "cpu": ["x64"] - }, - "@esbuild/linux-arm64@0.25.5": { - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@esbuild/linux-arm@0.25.5": { - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", - "os": ["linux"], - "cpu": ["arm"] - }, - "@esbuild/linux-ia32@0.25.5": { - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", - "os": ["linux"], - "cpu": ["ia32"] - }, - "@esbuild/linux-loong64@0.25.5": { - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", - "os": ["linux"], - "cpu": ["loong64"] - }, - "@esbuild/linux-mips64el@0.25.5": { - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", - "os": ["linux"], - "cpu": ["mips64el"] - }, - "@esbuild/linux-ppc64@0.25.5": { - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", - "os": ["linux"], - "cpu": ["ppc64"] - }, - "@esbuild/linux-riscv64@0.25.5": { - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", - "os": ["linux"], - "cpu": ["riscv64"] - }, - "@esbuild/linux-s390x@0.25.5": { - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", - "os": ["linux"], - "cpu": ["s390x"] - }, - "@esbuild/linux-x64@0.25.5": { - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@esbuild/netbsd-arm64@0.25.5": { - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", - "os": ["netbsd"], - "cpu": ["arm64"] - }, - "@esbuild/netbsd-x64@0.25.5": { - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", - "os": ["netbsd"], - "cpu": ["x64"] - }, - "@esbuild/openbsd-arm64@0.25.5": { - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", - "os": ["openbsd"], - "cpu": ["arm64"] - }, - "@esbuild/openbsd-x64@0.25.5": { - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", - "os": ["openbsd"], - "cpu": ["x64"] - }, - "@esbuild/sunos-x64@0.25.5": { - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", - "os": ["sunos"], - "cpu": ["x64"] - }, - "@esbuild/win32-arm64@0.25.5": { - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", - "os": ["win32"], - "cpu": ["arm64"] - }, - "@esbuild/win32-ia32@0.25.5": { - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", - "os": ["win32"], - "cpu": ["ia32"] - }, - "@esbuild/win32-x64@0.25.5": { - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", - "os": ["win32"], - "cpu": ["x64"] - }, - "@floating-ui/core@1.7.1": { - "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", - "dependencies": [ - "@floating-ui/utils" - ] - }, - "@floating-ui/dom@1.7.1": { - "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", - "dependencies": [ - "@floating-ui/core", - "@floating-ui/utils" - ] - }, - "@floating-ui/react-dom@2.1.3_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", - "dependencies": [ - "@floating-ui/dom", - "react", - "react-dom" - ] - }, - "@floating-ui/utils@0.2.9": { - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" - }, - "@gfx/zopfli@1.0.15": { - "integrity": "sha512-7mBgpi7UD82fsff5ThQKet0uBTl4BYerQuc+/qA1ELTwWEiIedRTcD3JgiUu9wwZ2kytW8JOb165rSdAt8PfcQ==", - "dependencies": [ - "base64-js" - ] - }, - "@hookform/resolvers@5.1.1_react-hook-form@7.58.1__react@19.1.0_react@19.1.0": { - "integrity": "sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg==", - "dependencies": [ - "@standard-schema/utils", - "react-hook-form" - ] - }, - "@isaacs/fs-minipass@4.0.1": { - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dependencies": [ - "minipass" - ] - }, - "@jridgewell/gen-mapping@0.3.8": { - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dependencies": [ - "@jridgewell/set-array", - "@jridgewell/sourcemap-codec", - "@jridgewell/trace-mapping" - ] - }, - "@jridgewell/resolve-uri@3.1.2": { - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" - }, - "@jridgewell/set-array@1.2.1": { - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" - }, - "@jridgewell/source-map@0.3.6": { - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dependencies": [ - "@jridgewell/gen-mapping", - "@jridgewell/trace-mapping" - ] - }, - "@jridgewell/sourcemap-codec@1.5.0": { - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "@jridgewell/trace-mapping@0.3.25": { - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": [ - "@jridgewell/resolve-uri", - "@jridgewell/sourcemap-codec" - ] - }, - "@jsr/meshtastic__core@2.6.4": { - "integrity": "sha512-1Kz5DK6peFxluHOJR38vFwfgeJzMXTz+3p6TvibjILVhSQC2U1nu8aJbn6w5zhRqS+j79OmtrRvdzL6VNsTkkQ==", - "dependencies": [ - "@bufbuild/protobuf", - "@jsr/meshtastic__protobufs", - "crc", - "ste-simple-events", - "tslog" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__core/2.6.4.tgz" - }, - "@jsr/meshtastic__js@2.6.0-0": { - "integrity": "sha512-+xpZpxK6oUIVOuEs7C+LyxRr2druvc7UNNNTK9Rl8ioXj63Jz1uQXlYe2Gj0xjnRAiSQLR7QVaPef21BR/YTxA==", - "dependencies": [ - "@bufbuild/protobuf", - "@jsr/meshtastic__protobufs", - "crc", - "ste-simple-events", - "tslog" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__js/2.6.0-0.tgz" - }, - "@jsr/meshtastic__protobufs@2.6.2": { - "integrity": "sha512-bIENtFnUEru28GrAeSdiBS9skp0hN/3HZunMbF/IjvUrXOlx2fptKVj3b+pzjOWnLBZxllrByV/W+XDmrxqJ6g==", - "dependencies": [ - "@bufbuild/protobuf" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__protobufs/2.6.2.tgz" - }, - "@jsr/meshtastic__transport-http@0.2.1": { - "integrity": "sha512-lmQKr3aIINKvtGROU4HchmSVqbZSbkIHqajowRRC8IAjsnR0zNTyxz210QyY4pFUF9hpcW3GRjwq5h/VO2JuGg==", - "dependencies": [ - "@jsr/meshtastic__core" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-http/0.2.1.tgz" - }, - "@jsr/meshtastic__transport-web-bluetooth@0.1.2": { - "integrity": "sha512-Z+5pv9RXNgY0/crKExOH3pZ6LT0HIXFmnBL7NX5AO2knOFRn+4lmxQEhhmiTTlkUfqyEfAvbjuY5u4mq9TPTdQ==", - "dependencies": [ - "@jsr/meshtastic__core" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-bluetooth/0.1.2.tgz" - }, - "@jsr/meshtastic__transport-web-serial@0.2.1": { - "integrity": "sha512-yumjEGLkAuJYOC3aWKvZzbQqi/LnqaKfNpVCY7Ki7oLtAshNiZrBLiwiFhN7+ZR9FfMdJThyBMqREBDRRWTO1Q==", - "dependencies": [ - "@jsr/meshtastic__core" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/meshtastic__transport-web-serial/0.2.1.tgz" - }, - "@mapbox/geojson-rewind@0.5.2": { - "integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==", - "dependencies": [ - "get-stream", - "minimist" - ], - "bin": true - }, - "@mapbox/jsonlint-lines-primitives@2.0.2": { - "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==" - }, - "@mapbox/point-geometry@0.1.0": { - "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==" - }, - "@mapbox/tiny-sdf@2.0.6": { - "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==" - }, - "@mapbox/unitbezier@0.0.1": { - "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==" - }, - "@mapbox/vector-tile@1.3.1": { - "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==", - "dependencies": [ - "@mapbox/point-geometry" - ] - }, - "@mapbox/whoots-js@3.1.0": { - "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==" - }, - "@maplibre/maplibre-gl-style-spec@19.3.3": { - "integrity": "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==", - "dependencies": [ - "@mapbox/jsonlint-lines-primitives", - "@mapbox/unitbezier", - "json-stringify-pretty-compact@3.0.0", - "minimist", - "rw", - "sort-object" - ], - "bin": true - }, - "@maplibre/maplibre-gl-style-spec@23.3.0": { - "integrity": "sha512-IGJtuBbaGzOUgODdBRg66p8stnwj9iDXkgbYKoYcNiiQmaez5WVRfXm4b03MCDwmZyX93csbfHFWEJJYHnn5oA==", - "dependencies": [ - "@mapbox/jsonlint-lines-primitives", - "@mapbox/unitbezier", - "json-stringify-pretty-compact@4.0.0", - "minimist", - "quickselect@3.0.0", - "rw", - "tinyqueue@3.0.0" - ], - "bin": true - }, - "@napi-rs/wasm-runtime@0.2.11": { - "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", - "dependencies": [ - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util" - ] - }, - "@noble/curves@1.9.2": { - "integrity": "sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==", - "dependencies": [ - "@noble/hashes" - ] - }, - "@noble/hashes@1.8.0": { - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==" - }, - "@radix-ui/number@1.1.1": { - "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==" - }, - "@radix-ui/primitive@1.1.2": { - "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==" - }, - "@radix-ui/react-accordion@1.2.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-collapsible", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-id", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-arrow@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", - "dependencies": [ - "@radix-ui/react-primitive", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-checkbox@1.3.2_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-use-previous", - "@radix-ui/react-use-size", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-collapsible@1.1.11_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-id", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-use-layout-effect", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-collection@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-primitive", - "@radix-ui/react-slot", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-compose-refs@1.1.2_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-context@1.1.2_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-dialog@1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-dismissable-layer", - "@radix-ui/react-focus-guards", - "@radix-ui/react-focus-scope", - "@radix-ui/react-id", - "@radix-ui/react-portal", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-slot", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "aria-hidden", - "react", - "react-dom", - "react-remove-scroll" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-direction@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-dismissable-layer@1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-primitive", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-escape-keydown", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-dropdown-menu@2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-id", - "@radix-ui/react-menu", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-focus-guards@1.1.2_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-focus-scope@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@radix-ui/react-primitive", - "@radix-ui/react-use-callback-ref", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-id@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", - "dependencies": [ - "@radix-ui/react-use-layout-effect", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-label@2.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", - "dependencies": [ - "@radix-ui/react-primitive", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-menu@2.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-dismissable-layer", - "@radix-ui/react-focus-guards", - "@radix-ui/react-focus-scope", - "@radix-ui/react-id", - "@radix-ui/react-popper", - "@radix-ui/react-portal", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-roving-focus", - "@radix-ui/react-slot", - "@radix-ui/react-use-callback-ref", - "@types/react", - "@types/react-dom", - "aria-hidden", - "react", - "react-dom", - "react-remove-scroll" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-menubar@1.1.15_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-Z71C7LGD+YDYo3TV81paUs8f3Zbmkvg6VLRQpKYfzioOE6n7fOhA3ApK/V/2Odolxjoc4ENk8AYCjohCNayd5A==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-id", - "@radix-ui/react-menu", - "@radix-ui/react-primitive", - "@radix-ui/react-roving-focus", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-popover@1.1.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-dismissable-layer", - "@radix-ui/react-focus-guards", - "@radix-ui/react-focus-scope", - "@radix-ui/react-id", - "@radix-ui/react-popper", - "@radix-ui/react-portal", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-slot", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "aria-hidden", - "react", - "react-dom", - "react-remove-scroll" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-popper@1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", - "dependencies": [ - "@floating-ui/react-dom", - "@radix-ui/react-arrow", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-primitive", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-layout-effect", - "@radix-ui/react-use-rect", - "@radix-ui/react-use-size", - "@radix-ui/rect", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-portal@1.1.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", - "dependencies": [ - "@radix-ui/react-primitive", - "@radix-ui/react-use-layout-effect", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-presence@1.1.4_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@radix-ui/react-use-layout-effect", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-primitive@2.1.3_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "dependencies": [ - "@radix-ui/react-slot", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-roving-focus@1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-id", - "@radix-ui/react-primitive", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-scroll-area@1.2.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==", - "dependencies": [ - "@radix-ui/number", - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-layout-effect", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-select@2.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", - "dependencies": [ - "@radix-ui/number", - "@radix-ui/primitive", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-dismissable-layer", - "@radix-ui/react-focus-guards", - "@radix-ui/react-focus-scope", - "@radix-ui/react-id", - "@radix-ui/react-popper", - "@radix-ui/react-portal", - "@radix-ui/react-primitive", - "@radix-ui/react-slot", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-use-layout-effect", - "@radix-ui/react-use-previous", - "@radix-ui/react-visually-hidden", - "@types/react", - "@types/react-dom", - "aria-hidden", - "react", - "react-dom", - "react-remove-scroll" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-separator@1.1.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", - "dependencies": [ - "@radix-ui/react-primitive", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-slider@1.3.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==", - "dependencies": [ - "@radix-ui/number", - "@radix-ui/primitive", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-use-layout-effect", - "@radix-ui/react-use-previous", - "@radix-ui/react-use-size", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-slot@1.2.3_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-switch@1.2.5_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-use-previous", - "@radix-ui/react-use-size", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-tabs@1.1.12_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-id", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-roving-focus", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-toast@1.2.14_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-collection", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-dismissable-layer", - "@radix-ui/react-portal", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-use-callback-ref", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-use-layout-effect", - "@radix-ui/react-visually-hidden", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-toggle-group@1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-kiU694Km3WFLTC75DdqgM/3Jauf3rD9wxeS9XtyWFKsBUeZA337lC+6uUazT7I1DhanZ5gyD5Stf8uf2dbQxOQ==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-context", - "@radix-ui/react-direction", - "@radix-ui/react-primitive", - "@radix-ui/react-roving-focus", - "@radix-ui/react-toggle", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-toggle@1.1.9_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-ZoFkBBz9zv9GWer7wIjvdRxmh2wyc2oKWw6C6CseWd6/yq1DK/l5lJ+wnsmFwJZbBYqr02mrf8A2q/CVCuM3ZA==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-primitive", - "@radix-ui/react-use-controllable-state", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-tooltip@1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", - "dependencies": [ - "@radix-ui/primitive", - "@radix-ui/react-compose-refs", - "@radix-ui/react-context", - "@radix-ui/react-dismissable-layer", - "@radix-ui/react-id", - "@radix-ui/react-popper", - "@radix-ui/react-portal", - "@radix-ui/react-presence", - "@radix-ui/react-primitive", - "@radix-ui/react-slot", - "@radix-ui/react-use-controllable-state", - "@radix-ui/react-visually-hidden", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/react-use-callback-ref@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-controllable-state@1.2.2_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "dependencies": [ - "@radix-ui/react-use-effect-event", - "@radix-ui/react-use-layout-effect", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-effect-event@0.0.2_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", - "dependencies": [ - "@radix-ui/react-use-layout-effect", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-escape-keydown@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", - "dependencies": [ - "@radix-ui/react-use-callback-ref", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-layout-effect@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-previous@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", - "dependencies": [ - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-rect@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", - "dependencies": [ - "@radix-ui/rect", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-use-size@1.1.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", - "dependencies": [ - "@radix-ui/react-use-layout-effect", - "@types/react", - "react" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "@radix-ui/react-visually-hidden@1.2.3_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", - "dependencies": [ - "@radix-ui/react-primitive", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@radix-ui/rect@1.1.1": { - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==" - }, - "@rolldown/pluginutils@1.0.0-beta.19": { - "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==" - }, - "@rollup/plugin-babel@5.3.1_@babel+core@7.27.4_rollup@2.79.2": { - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", - "dependencies": [ - "@babel/core", - "@babel/helper-module-imports", - "@rollup/pluginutils@3.1.0_rollup@2.79.2", - "rollup@2.79.2" - ] - }, - "@rollup/plugin-node-resolve@15.3.1_rollup@2.79.2": { - "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", - "dependencies": [ - "@rollup/pluginutils@5.2.0_rollup@2.79.2", - "@types/resolve", - "deepmerge", - "is-module", - "resolve", - "rollup@2.79.2" - ], - "optionalPeers": [ - "rollup@2.79.2" - ] - }, - "@rollup/plugin-replace@2.4.2_rollup@2.79.2": { - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", - "dependencies": [ - "@rollup/pluginutils@3.1.0_rollup@2.79.2", - "magic-string@0.25.9", - "rollup@2.79.2" - ] - }, - "@rollup/plugin-terser@0.4.4_rollup@2.79.2": { - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "dependencies": [ - "rollup@2.79.2", - "serialize-javascript", - "smob", - "terser" - ], - "optionalPeers": [ - "rollup@2.79.2" - ] - }, - "@rollup/pluginutils@3.1.0_rollup@2.79.2": { - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dependencies": [ - "@types/estree@0.0.39", - "estree-walker@1.0.1", - "picomatch@2.3.1", - "rollup@2.79.2" - ] - }, - "@rollup/pluginutils@5.2.0_rollup@2.79.2": { - "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", - "dependencies": [ - "@types/estree@1.0.8", - "estree-walker@2.0.2", - "picomatch@4.0.2", - "rollup@2.79.2" - ], - "optionalPeers": [ - "rollup@2.79.2" - ] - }, - "@rollup/rollup-android-arm-eabi@4.44.0": { - "integrity": "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==", - "os": ["android"], - "cpu": ["arm"] - }, - "@rollup/rollup-android-arm64@4.44.0": { - "integrity": "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==", - "os": ["android"], - "cpu": ["arm64"] - }, - "@rollup/rollup-darwin-arm64@4.44.0": { - "integrity": "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==", - "os": ["darwin"], - "cpu": ["arm64"] - }, - "@rollup/rollup-darwin-x64@4.44.0": { - "integrity": "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==", - "os": ["darwin"], - "cpu": ["x64"] - }, - "@rollup/rollup-freebsd-arm64@4.44.0": { - "integrity": "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==", - "os": ["freebsd"], - "cpu": ["arm64"] - }, - "@rollup/rollup-freebsd-x64@4.44.0": { - "integrity": "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==", - "os": ["freebsd"], - "cpu": ["x64"] - }, - "@rollup/rollup-linux-arm-gnueabihf@4.44.0": { - "integrity": "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==", - "os": ["linux"], - "cpu": ["arm"] - }, - "@rollup/rollup-linux-arm-musleabihf@4.44.0": { - "integrity": "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==", - "os": ["linux"], - "cpu": ["arm"] - }, - "@rollup/rollup-linux-arm64-gnu@4.44.0": { - "integrity": "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@rollup/rollup-linux-arm64-musl@4.44.0": { - "integrity": "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@rollup/rollup-linux-loongarch64-gnu@4.44.0": { - "integrity": "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==", - "os": ["linux"], - "cpu": ["loong64"] - }, - "@rollup/rollup-linux-powerpc64le-gnu@4.44.0": { - "integrity": "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==", - "os": ["linux"], - "cpu": ["ppc64"] - }, - "@rollup/rollup-linux-riscv64-gnu@4.44.0": { - "integrity": "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==", - "os": ["linux"], - "cpu": ["riscv64"] - }, - "@rollup/rollup-linux-riscv64-musl@4.44.0": { - "integrity": "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==", - "os": ["linux"], - "cpu": ["riscv64"] - }, - "@rollup/rollup-linux-s390x-gnu@4.44.0": { - "integrity": "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==", - "os": ["linux"], - "cpu": ["s390x"] - }, - "@rollup/rollup-linux-x64-gnu@4.44.0": { - "integrity": "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@rollup/rollup-linux-x64-musl@4.44.0": { - "integrity": "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@rollup/rollup-win32-arm64-msvc@4.44.0": { - "integrity": "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==", - "os": ["win32"], - "cpu": ["arm64"] - }, - "@rollup/rollup-win32-ia32-msvc@4.44.0": { - "integrity": "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==", - "os": ["win32"], - "cpu": ["ia32"] - }, - "@rollup/rollup-win32-x64-msvc@4.44.0": { - "integrity": "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==", - "os": ["win32"], - "cpu": ["x64"] - }, - "@standard-schema/utils@0.3.0": { - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==" - }, - "@surma/rollup-plugin-off-main-thread@2.2.3": { - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", - "dependencies": [ - "ejs", - "json5", - "magic-string@0.25.9", - "string.prototype.matchall" - ] - }, - "@tailwindcss/node@4.1.10": { - "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", - "dependencies": [ - "@ampproject/remapping", - "enhanced-resolve", - "jiti", - "lightningcss", - "magic-string@0.30.17", - "source-map-js", - "tailwindcss" - ] - }, - "@tailwindcss/oxide-android-arm64@4.1.10": { - "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", - "os": ["android"], - "cpu": ["arm64"] - }, - "@tailwindcss/oxide-darwin-arm64@4.1.10": { - "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", - "os": ["darwin"], - "cpu": ["arm64"] - }, - "@tailwindcss/oxide-darwin-x64@4.1.10": { - "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", - "os": ["darwin"], - "cpu": ["x64"] - }, - "@tailwindcss/oxide-freebsd-x64@4.1.10": { - "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", - "os": ["freebsd"], - "cpu": ["x64"] - }, - "@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10": { - "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", - "os": ["linux"], - "cpu": ["arm"] - }, - "@tailwindcss/oxide-linux-arm64-gnu@4.1.10": { - "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@tailwindcss/oxide-linux-arm64-musl@4.1.10": { - "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "@tailwindcss/oxide-linux-x64-gnu@4.1.10": { - "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@tailwindcss/oxide-linux-x64-musl@4.1.10": { - "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", - "os": ["linux"], - "cpu": ["x64"] - }, - "@tailwindcss/oxide-wasm32-wasi@4.1.10": { - "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", - "dependencies": [ - "@emnapi/core", - "@emnapi/runtime", - "@emnapi/wasi-threads", - "@napi-rs/wasm-runtime", - "@tybys/wasm-util", - "tslib@2.8.1" - ], - "cpu": ["wasm32"] - }, - "@tailwindcss/oxide-win32-arm64-msvc@4.1.10": { - "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", - "os": ["win32"], - "cpu": ["arm64"] - }, - "@tailwindcss/oxide-win32-x64-msvc@4.1.10": { - "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", - "os": ["win32"], - "cpu": ["x64"] - }, - "@tailwindcss/oxide@4.1.10": { - "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", - "dependencies": [ - "detect-libc", - "tar" - ], - "optionalDependencies": [ - "@tailwindcss/oxide-android-arm64", - "@tailwindcss/oxide-darwin-arm64", - "@tailwindcss/oxide-darwin-x64", - "@tailwindcss/oxide-freebsd-x64", - "@tailwindcss/oxide-linux-arm-gnueabihf", - "@tailwindcss/oxide-linux-arm64-gnu", - "@tailwindcss/oxide-linux-arm64-musl", - "@tailwindcss/oxide-linux-x64-gnu", - "@tailwindcss/oxide-linux-x64-musl", - "@tailwindcss/oxide-wasm32-wasi", - "@tailwindcss/oxide-win32-arm64-msvc", - "@tailwindcss/oxide-win32-x64-msvc" - ], - "scripts": true - }, - "@tailwindcss/postcss@4.1.10": { - "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==", - "dependencies": [ - "@alloc/quick-lru", - "@tailwindcss/node", - "@tailwindcss/oxide", - "postcss", - "tailwindcss" - ] - }, - "@tanstack/history@1.121.21": { - "integrity": "sha512-8BFGA7fpElicM1aEfZRDoEiWgMrNb/fVuJjSKv+nYtbp7jdtqt57fROi/uDGf6PLlgJbMoT3GWxqveZisOUEKA==" - }, - "@tanstack/history@1.121.34": { - "integrity": "sha512-YL8dGi5ZU+xvtav2boRlw4zrRghkY6hvdcmHhA0RGSJ/CBgzv+cbADW9eYJLx74XMZvIQ1pp6VMbrpXnnM5gHA==" - }, - "@tanstack/react-router-devtools@1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-hPOI1FGVWSf9U70eW7NevF/i68Id44KLTM7YjKtDcQi+MWEoxqvXiyXrl/HUAm1IBqLNwO5ktnEdcDuAG/efDg==", - "dependencies": [ - "@tanstack/react-router", - "@tanstack/router-devtools-core", - "react", - "react-dom" - ] - }, - "@tanstack/react-router@1.121.27_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-zuLy8IC5fF52fzTTG61nMW2pMoK8LW4kSpeW21deb4gx/kMFKDOaYTe/soT63CO9/x0X6TYcbfjRj67038J0pQ==", - "dependencies": [ - "@tanstack/history@1.121.21", - "@tanstack/react-store", - "@tanstack/router-core@1.121.27", - "jsesc@3.1.0", - "react", - "react-dom", - "tiny-invariant", - "tiny-warning" - ] - }, - "@tanstack/react-store@0.7.1_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-qUTEKdId6QPWGiWyKAPf/gkN29scEsz6EUSJ0C3HgLMgaqTAyBsQ2sMCfGVcqb+kkhEXAdjleCgH6LAPD6f2sA==", - "dependencies": [ - "@tanstack/store", - "react", - "react-dom", - "use-sync-external-store" - ] - }, - "@tanstack/router-cli@1.121.37": { - "integrity": "sha512-Jc/YIBPBGgKt10wqquWMR3dntbUWSlhXaGCYFRb31SM+zRl+NSyOIhEO5zAm0oP4l605yyejs9gGj8BC9idn0Q==", - "dependencies": [ - "@tanstack/router-generator", - "chokidar", - "yargs" - ], - "bin": true - }, - "@tanstack/router-core@1.121.27": { - "integrity": "sha512-6lCQ3p7KhJ8Qy33TPRM6wIkQ1XKaikD5qqx3K2fPr3YtyDNefKQValbSAkb2CBB+hlDodfHNyxemE9alnQr55A==", - "dependencies": [ - "@tanstack/history@1.121.21", - "@tanstack/store", - "tiny-invariant" - ] - }, - "@tanstack/router-core@1.121.34": { - "integrity": "sha512-CRH9dC8uLfFOKUGTbtOcMPv+weNVt2xs+me34KLX0Yja2yHG99oAUCBwamXsVQPpfjLFPYeJuKyo98+Mg+Ppeg==", - "dependencies": [ - "@tanstack/history@1.121.34", - "@tanstack/store", - "tiny-invariant" - ] - }, - "@tanstack/router-devtools-core@1.121.27_@tanstack+router-core@1.121.27_solid-js@1.9.7__seroval@1.3.2_tiny-invariant@1.3.3": { - "integrity": "sha512-taeINd8CSIg+0916myI52HbQxjqfgxqHp68Ha6uxjXAHhHQKg/hBFCWpDs4Dwxi290mhT8j2oeXNyDaGMvVumQ==", - "dependencies": [ - "@tanstack/router-core@1.121.27", - "clsx", - "goober", - "solid-js", - "tiny-invariant" - ] - }, - "@tanstack/router-devtools@1.121.27_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-hQ+8CwMYXCk+FmDPSG5YavWNmY2WuHvEGsbmu1KkwyZ8pwj0RUYCArzGpKx8c0GT7Y29eWmU+U0DNzmEKQILpA==", - "dependencies": [ - "@tanstack/react-router", - "@tanstack/react-router-devtools", - "clsx", - "goober", - "react", - "react-dom" - ] - }, - "@tanstack/router-generator@1.121.37": { - "integrity": "sha512-d7IqEDf962uJFNPMWXfPr+kUpS3Cv72azZhBNMMVmZUox/h3VDGgQ6OUnWXHwnno4xqDoS/mx9huTUnItoewaw==", - "dependencies": [ - "@tanstack/router-core@1.121.34", - "@tanstack/router-utils", - "@tanstack/virtual-file-routes", - "prettier", - "recast", - "source-map@0.7.4", - "tsx", - "zod" - ] - }, - "@tanstack/router-plugin@1.121.37_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.32": { - "integrity": "sha512-zrolQ1J53xDUdxdO6MLfvnpVINnkIfOnEDVeX3kwHKBGQ5zyGdbolVcVVrJIRYQS0SJoWesn8cf8j+z+u8nZtg==", - "dependencies": [ - "@babel/core", - "@babel/plugin-syntax-jsx", - "@babel/plugin-syntax-typescript", - "@babel/template", - "@babel/traverse", - "@babel/types", - "@tanstack/react-router", - "@tanstack/router-core@1.121.34", - "@tanstack/router-generator", - "@tanstack/router-utils", - "@tanstack/virtual-file-routes", - "babel-dead-code-elimination", - "chokidar", - "unplugin", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2", - "zod" - ], - "optionalPeers": [ - "@tanstack/react-router", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2" - ] - }, - "@tanstack/router-plugin@1.121.37_@tanstack+react-router@1.121.27__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.15.32_@types+node@22.15.15": { - "integrity": "sha512-zrolQ1J53xDUdxdO6MLfvnpVINnkIfOnEDVeX3kwHKBGQ5zyGdbolVcVVrJIRYQS0SJoWesn8cf8j+z+u8nZtg==", - "dependencies": [ - "@babel/core", - "@babel/plugin-syntax-jsx", - "@babel/plugin-syntax-typescript", - "@babel/template", - "@babel/traverse", - "@babel/types", - "@tanstack/react-router", - "@tanstack/router-core@1.121.34", - "@tanstack/router-generator", - "@tanstack/router-utils", - "@tanstack/virtual-file-routes", - "babel-dead-code-elimination", - "chokidar", - "unplugin", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15", - "zod" - ], - "optionalPeers": [ - "@tanstack/react-router", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15" - ] - }, - "@tanstack/router-utils@1.121.21_@babel+core@7.27.4": { - "integrity": "sha512-u7ubq1xPBtNiU7Fm+EOWlVWdgFLzuKOa1thhqdscVn8R4dNMUd1VoOjZ6AKmLw201VaUhFtlX+u0pjzI6szX7A==", - "dependencies": [ - "@babel/core", - "@babel/generator", - "@babel/parser", - "@babel/preset-typescript", - "ansis", - "diff" - ] - }, - "@tanstack/store@0.7.1": { - "integrity": "sha512-PjUQKXEXhLYj2X5/6c1Xn/0/qKY0IVFxTJweopRfF26xfjVyb14yALydJrHupDh3/d+1WKmfEgZPBVCmDkzzwg==" - }, - "@tanstack/virtual-file-routes@1.121.21": { - "integrity": "sha512-3nuYsTyaq6ZN7jRZ9z6Gj3GXZqBOqOT0yzd/WZ33ZFfv4yVNIvsa5Lw+M1j3sgyEAxKMqGu/FaNi7FCjr3yOdw==" - }, - "@testing-library/dom@10.4.0": { - "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", - "dependencies": [ - "@babel/code-frame", - "@babel/runtime", - "@types/aria-query", - "aria-query@5.3.0", - "chalk@4.1.2", - "dom-accessibility-api@0.5.16", - "lz-string", - "pretty-format" - ] - }, - "@testing-library/jest-dom@6.6.3": { - "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", - "dependencies": [ - "@adobe/css-tools", - "aria-query@5.3.2", - "chalk@3.0.0", - "css.escape", - "dom-accessibility-api@0.6.3", - "lodash", - "redent" - ] - }, - "@testing-library/react@16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", - "dependencies": [ - "@babel/runtime", - "@testing-library/dom", - "@types/react", - "@types/react-dom", - "react", - "react-dom" - ], - "optionalPeers": [ - "@types/react", - "@types/react-dom" - ] - }, - "@testing-library/user-event@14.6.1_@testing-library+dom@10.4.0": { - "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", - "dependencies": [ - "@testing-library/dom" - ] - }, - "@turf/along@7.2.0": { - "integrity": "sha512-Cf+d2LozABdb0TJoIcJwFKB+qisJY4nMUW9z6PAuZ9UCH7AR//hy2Z06vwYCKFZKP4a7DRPkOMBadQABCyoYuw==", - "dependencies": [ - "@turf/bearing", - "@turf/destination", - "@turf/distance", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/angle@7.2.0": { - "integrity": "sha512-b28rs1NO8Dt/MXadFhnpqH7GnEWRsl+xF5JeFtg9+eM/+l/zGrdliPYMZtAj12xn33w22J1X4TRprAI0rruvVQ==", - "dependencies": [ - "@turf/bearing", - "@turf/helpers", - "@turf/invariant", - "@turf/rhumb-bearing", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/area@7.2.0": { - "integrity": "sha512-zuTTdQ4eoTI9nSSjerIy4QwgvxqwJVciQJ8tOPuMHbXJ9N/dNjI7bU8tasjhxas/Cx3NE9NxVHtNpYHL0FSzoA==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/bbox-clip@7.2.0": { - "integrity": "sha512-q6RXTpqeUQAYLAieUL1n3J6ukRGsNVDOqcYtfzaJbPW+0VsAf+1cI16sN700t0sekbeU1DH/RRVAHhpf8+36wA==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/bbox-polygon@7.2.0": { - "integrity": "sha512-Aj4G1GAAy26fmOqMjUk0Z+Lcax5VQ9g1xYDbHLQWXvfTsaueBT+RzdH6XPnZ/seEEnZkio2IxE8V5af/osupgA==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/bbox@7.2.0": { - "integrity": "sha512-wzHEjCXlYZiDludDbXkpBSmv8Zu6tPGLmJ1sXQ6qDwpLE1Ew3mcWqt8AaxfTP5QwDNQa3sf2vvgTEzNbPQkCiA==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/bearing@7.2.0": { - "integrity": "sha512-Jm0Xt3GgHjRrWvBtAGvgfnADLm+4exud2pRlmCYx8zfiKuNXQFkrcTZcOiJOgTfG20Agq28iSh15uta47jSIbg==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/bezier-spline@7.2.0": { - "integrity": "sha512-7BPkc3ufYB9KLvcaTpTsnpXzh9DZoENxCS0Ms9XUwuRXw45TpevwUpOsa3atO76iKQ5puHntqFO4zs8IUxBaaA==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-clockwise@7.2.0": { - "integrity": "sha512-0fJeFSARxy6ealGBM4Gmgpa1o8msQF87p2Dx5V6uSqzT8VPDegX1NSWl4b7QgXczYa9qv7IAABttdWP0K7Q7eQ==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-concave@7.2.0": { - "integrity": "sha512-v3dTN04dfO6VqctQj1a+pjDHb6+/Ev90oAR2QjJuAntY4ubhhr7vKeJdk/w+tWNSMKULnYwfe65Du3EOu3/TeA==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-contains@7.2.0": { - "integrity": "sha512-dgRQm4uVO5XuLee4PLVH7CFQZKdefUBMIXTPITm2oRIDmPLJKHDOFKQTNkGJ73mDKKBR2lmt6eVH3br6OYrEYg==", - "dependencies": [ - "@turf/bbox", - "@turf/boolean-point-in-polygon", - "@turf/boolean-point-on-line", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-crosses@7.2.0": { - "integrity": "sha512-9GyM4UUWFKQOoNhHVSfJBf5XbPy8Fxfz9djjJNAnm/IOl8NmFUSwFPAjKlpiMcr6yuaAoc9R/1KokS9/eLqPvA==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/helpers", - "@turf/invariant", - "@turf/line-intersect", - "@turf/polygon-to-line", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-disjoint@7.2.0": { - "integrity": "sha512-xdz+pYKkLMuqkNeJ6EF/3OdAiJdiHhcHCV0ykX33NIuALKIEpKik0+NdxxNsZsivOW6keKwr61SI+gcVtHYcnQ==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/helpers", - "@turf/line-intersect", - "@turf/meta", - "@turf/polygon-to-line", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-equal@7.2.0": { - "integrity": "sha512-TmjKYLsxXqEmdDtFq3QgX4aSogiISp3/doeEtDOs3NNSR8susOtBEZkmvwO6DLW+g/rgoQJIBR6iVoWiRqkBxw==", - "dependencies": [ - "@turf/clean-coords", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "geojson-equality-ts", - "tslib@2.8.1" - ] - }, - "@turf/boolean-intersects@7.2.0": { - "integrity": "sha512-GLRyLQgK3F14drkK5Qi9Mv7Z9VT1bgQUd9a3DB3DACTZWDSwfh8YZUFn/HBwRkK8dDdgNEXaavggQHcPi1k9ow==", - "dependencies": [ - "@turf/boolean-disjoint", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-overlap@7.2.0": { - "integrity": "sha512-ieM5qIE4anO+gUHIOvEN7CjyowF+kQ6v20/oNYJCp63TVS6eGMkwgd+I4uMzBXfVW66nVHIXjODdUelU+Xyctw==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@turf/line-intersect", - "@turf/line-overlap", - "@turf/meta", - "@types/geojson", - "geojson-equality-ts", - "tslib@2.8.1" - ] - }, - "@turf/boolean-parallel@7.2.0": { - "integrity": "sha512-iOtuzzff8nmwv05ROkSvyeGLMrfdGkIi+3hyQ+DH4IVyV37vQbqR5oOJ0Nt3Qq1Tjrq9fvF8G3OMdAv3W2kY9w==", - "dependencies": [ - "@turf/clean-coords", - "@turf/helpers", - "@turf/line-segment", - "@turf/rhumb-bearing", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-point-in-polygon@7.2.0": { - "integrity": "sha512-lvEOjxeXIp+wPXgl9kJA97dqzMfNexjqHou+XHVcfxQgolctoJiRYmcVCWGpiZ9CBf/CJha1KmD1qQoRIsjLaA==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "point-in-polygon-hao", - "tslib@2.8.1" - ] - }, - "@turf/boolean-point-on-line@7.2.0": { - "integrity": "sha512-H/bXX8+2VYeSyH8JWrOsu8OGmeA9KVZfM7M6U5/fSqGsRHXo9MyYJ94k39A9kcKSwI0aWiMXVD2UFmiWy8423Q==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-touches@7.2.0": { - "integrity": "sha512-8qb1CO+cwFATGRGFgTRjzL9aibfsbI91pdiRl7KIEkVdeN/H9k8FDrUA1neY7Yq48IaciuwqjbbojQ16FD9b0w==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/boolean-point-on-line", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/boolean-valid@7.2.0": { - "integrity": "sha512-xb7gdHN8VV6ivPJh6rPpgxmAEGReiRxqY+QZoEZVGpW2dXcmU1BdY6FA6G/cwvggXAXxJBREoANtEDgp/0ySbA==", - "dependencies": [ - "@turf/bbox", - "@turf/boolean-crosses", - "@turf/boolean-disjoint", - "@turf/boolean-overlap", - "@turf/boolean-point-in-polygon", - "@turf/boolean-point-on-line", - "@turf/helpers", - "@turf/invariant", - "@turf/line-intersect", - "@types/geojson", - "geojson-polygon-self-intersections", - "tslib@2.8.1" - ] - }, - "@turf/boolean-within@7.2.0": { - "integrity": "sha512-zB3AiF59zQZ27Dp1iyhp9mVAKOFHat8RDH45TZhLY8EaqdEPdmLGvwMFCKfLryQcUDQvmzP8xWbtUR82QM5C4g==", - "dependencies": [ - "@turf/bbox", - "@turf/boolean-point-in-polygon", - "@turf/boolean-point-on-line", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/buffer@7.2.0": { - "integrity": "sha512-QH1FTr5Mk4z1kpQNztMD8XBOZfpOXPOtlsxaSAj2kDIf5+LquA6HtJjZrjUngnGtzG5+XwcfyRL4ImvLnFjm5Q==", - "dependencies": [ - "@turf/bbox", - "@turf/center", - "@turf/helpers", - "@turf/jsts", - "@turf/meta", - "@turf/projection", - "@types/geojson", - "d3-geo" - ] - }, - "@turf/center-mean@7.2.0": { - "integrity": "sha512-NaW6IowAooTJ35O198Jw3U4diZ6UZCCeJY+4E+WMLpks3FCxMDSHEfO2QjyOXQMGWZnVxVelqI5x9DdniDbQ+A==", - "dependencies": [ - "@turf/bbox", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/center-median@7.2.0": { - "integrity": "sha512-/CgVyHNG4zAoZpvkl7qBCe4w7giWNVtLyTU5PoIfg1vWM4VpYw+N7kcBBH46bbzvVBn0vhmZr586r543EwdC/A==", - "dependencies": [ - "@turf/center-mean", - "@turf/centroid", - "@turf/distance", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/center-of-mass@7.2.0": { - "integrity": "sha512-ij3pmG61WQPHGTQvOziPOdIgwTMegkYTwIc71Gl7xn4C0vWH6KLDSshCphds9xdWSXt2GbHpUs3tr4XGntHkEQ==", - "dependencies": [ - "@turf/centroid", - "@turf/convex", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/center@7.2.0": { - "integrity": "sha512-UTNp9abQ2kuyRg5gCIGDNwwEQeF3NbpYsd1Q0KW9lwWuzbLVNn0sOwbxjpNF4J2HtMOs5YVOcqNvYyuoa2XrXw==", - "dependencies": [ - "@turf/bbox", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/centroid@7.2.0": { - "integrity": "sha512-yJqDSw25T7P48au5KjvYqbDVZ7qVnipziVfZ9aSo7P2/jTE7d4BP21w0/XLi3T/9bry/t9PR1GDDDQljN4KfDw==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/circle@7.2.0": { - "integrity": "sha512-1AbqBYtXhstrHmnW6jhLwsv7TtmT0mW58Hvl1uZXEDM1NCVXIR50yDipIeQPjrCuJ/Zdg/91gU8+4GuDCAxBGA==", - "dependencies": [ - "@turf/destination", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/clean-coords@7.2.0": { - "integrity": "sha512-+5+J1+D7wW7O/RDXn46IfCHuX1gIV1pIAQNSA7lcDbr3HQITZj334C4mOGZLEcGbsiXtlHWZiBtm785Vg8i+QQ==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/clone@7.2.0": { - "integrity": "sha512-JlGUT+/5qoU5jqZmf6NMFIoLDY3O7jKd53Up+zbpJ2vzUp6QdwdNzwrsCeONhynWM13F0MVtPXH4AtdkrgFk4g==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/clusters-dbscan@7.2.0": { - "integrity": "sha512-VWVUuDreev56g3/BMlnq/81yzczqaz+NVTypN5CigGgP67e+u/CnijphiuhKjtjDd/MzGjXgEWBJc26Y6LYKAw==", - "dependencies": [ - "@turf/clone", - "@turf/distance", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "rbush@3.0.1", - "tslib@2.8.1" - ] - }, - "@turf/clusters-kmeans@7.2.0": { - "integrity": "sha512-BxQdK8jc8Mwm9yoClCYkktm4W004uiQGqb/i/6Y7a8xqgJITWDgTu/cy//wOxAWPk4xfe6MThjnqkszWW8JdyQ==", - "dependencies": [ - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "skmeans", - "tslib@2.8.1" - ] - }, - "@turf/clusters@7.2.0": { - "integrity": "sha512-sKOrIKHHtXAuTKNm2USnEct+6/MrgyzMW42deZ2YG2RRKWGaaxHMFU2Yw71Yk4DqStOqTIBQpIOdrRuSOwbuQw==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/collect@7.2.0": { - "integrity": "sha512-zRVGDlYS8Bx/Zz4vnEUyRg4dmqHhkDbW/nIUIJh657YqaMj1SFi4Iv2i9NbcurlUBDJFkpuOhCvvEvAdskJ8UA==", - "dependencies": [ - "@turf/bbox", - "@turf/boolean-point-in-polygon", - "@turf/helpers", - "@types/geojson", - "rbush@3.0.1", - "tslib@2.8.1" - ] - }, - "@turf/combine@7.2.0": { - "integrity": "sha512-VEjm3IvnbMt3IgeRIhCDhhQDbLqCU1/5uN1+j1u6fyA095pCizPThGp4f/COSzC3t1s/iiV+fHuDsB6DihHffQ==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/concave@7.2.0": { - "integrity": "sha512-cpaDDlumK762kdadexw5ZAB6g/h2pJdihZ+e65lbQVe3WukJHAANnIEeKsdFCuIyNKrwTz2gWu5ws+OpjP48Yw==", - "dependencies": [ - "@turf/clone", - "@turf/distance", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/tin", - "@types/geojson", - "topojson-client", - "topojson-server", - "tslib@2.8.1" - ] - }, - "@turf/convex@7.2.0": { - "integrity": "sha512-HsgHm+zHRE8yPCE/jBUtWFyaaBmpXcSlyHd5/xsMhSZRImFzRzBibaONWQo7xbKZMISC3Nc6BtUjDi/jEVbqyA==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "concaveman", - "tslib@2.8.1" - ] - }, - "@turf/destination@7.2.0": { - "integrity": "sha512-8DUxtOO0Fvrh1xclIUj3d9C5WS20D21F5E+j+X9Q+ju6fcM4huOqTg5ckV1DN2Pg8caABEc5HEZJnGch/5YnYQ==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/difference@7.2.0": { - "integrity": "sha512-NHKD1v3s8RX+9lOpvHJg6xRuJOKiY3qxHhz5/FmE0VgGqnCkE7OObqWZ5SsXG+Ckh0aafs5qKhmDdDV/gGi6JA==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "polyclip-ts", - "tslib@2.8.1" - ] - }, - "@turf/dissolve@7.2.0": { - "integrity": "sha512-gPG5TE3mAYuZqBut8tPYCKwi4hhx5Cq0ALoQMB9X0hrVtFIKrihrsj98XQM/5pL/UIpAxQfwisQvy6XaOFaoPA==", - "dependencies": [ - "@turf/flatten", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "polyclip-ts", - "tslib@2.8.1" - ] - }, - "@turf/distance-weight@7.2.0": { - "integrity": "sha512-NeoyV0fXDH+7nIoNtLjAoH9XL0AS1pmTIyDxEE6LryoDTsqjnuR0YQxIkLCCWDqECoqaOmmBqpeWONjX5BwWCg==", - "dependencies": [ - "@turf/centroid", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/distance@7.2.0": { - "integrity": "sha512-HBjjXIgEcD/wJYjv7/6OZj5yoky2oUvTtVeIAqO3lL80XRvoYmVg6vkOIu6NswkerwLDDNT9kl7+BFLJoHbh6Q==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/ellipse@7.2.0": { - "integrity": "sha512-/Y75S5hE2+xjnTw4dXpQ5r/Y2HPM4xrwkPRCCQRpuuboKdEvm42azYmh7isPnMnBTVcmGb9UmGKj0HHAbiwt1g==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@turf/rhumb-destination", - "@turf/transform-rotate", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/envelope@7.2.0": { - "integrity": "sha512-xOMtDeNKHwUuDfzQeoSNmdabsP0/IgVDeyzitDe/8j9wTeW+MrKzVbGz7627PT3h6gsO+2nUv5asfKtUbmTyHA==", - "dependencies": [ - "@turf/bbox", - "@turf/bbox-polygon", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/explode@7.2.0": { - "integrity": "sha512-jyMXg93J1OI7/65SsLE1k9dfQD3JbcPNMi4/O3QR2Qb3BAs2039oFaSjtW+YqhMqVC4V3ZeKebMcJ8h9sK1n+A==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/flatten@7.2.0": { - "integrity": "sha512-q38Qsqr4l7mxp780zSdn0gp/WLBX+sa+gV6qIbDQ1HKCrrPK8QQJmNx7gk1xxEXVot6tq/WyAPysCQdX+kLmMA==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/flip@7.2.0": { - "integrity": "sha512-X0TQ0U/UYh4tyXdLO5itP1sO2HOvfrZC0fYSWmTfLDM14jEPkEK8PblofznfBygL+pIFtOS2is8FuVcp5XxYpQ==", - "dependencies": [ - "@turf/clone", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/geojson-rbush@7.2.0": { - "integrity": "sha512-ST8fLv+EwxVkDgsmhHggM0sPk2SfOHTZJkdgMXVFT7gB9o4lF8qk4y4lwvCCGIfFQAp2yv/PN5EaGMEKutk6xw==", - "dependencies": [ - "@turf/bbox", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "rbush@3.0.1" - ] - }, - "@turf/great-circle@7.2.0": { - "integrity": "sha512-n30OiADyOKHhor0aXNgYfXQYXO3UtsOKmhQsY1D89/Oh1nCIXG/1ZPlLL9ZoaRXXBTUBjh99a+K8029NQbGDhw==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson" - ] - }, - "@turf/helpers@7.2.0": { - "integrity": "sha512-cXo7bKNZoa7aC7ydLmUR02oB3IgDe7MxiPuRz3cCtYQHn+BJ6h1tihmamYDWWUlPHgSNF0i3ATc4WmDECZafKw==", - "dependencies": [ - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/hex-grid@7.2.0": { - "integrity": "sha512-Yo2yUGxrTCQfmcVsSjDt0G3Veg8YD26WRd7etVPD9eirNNgXrIyZkbYA7zVV/qLeRWVmYIKRXg1USWl7ORQOGA==", - "dependencies": [ - "@turf/distance", - "@turf/helpers", - "@turf/intersect", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/interpolate@7.2.0": { - "integrity": "sha512-Ifgjm1SEo6XujuSAU6lpRMvoJ1SYTreil1Rf5WsaXj16BQJCedht/4FtWCTNhSWTwEz2motQ1WNrjTCuPG94xA==", - "dependencies": [ - "@turf/bbox", - "@turf/centroid", - "@turf/clone", - "@turf/distance", - "@turf/helpers", - "@turf/hex-grid", - "@turf/invariant", - "@turf/meta", - "@turf/point-grid", - "@turf/square-grid", - "@turf/triangle-grid", - "@types/geojson" - ] - }, - "@turf/intersect@7.2.0": { - "integrity": "sha512-81GMzKS9pKqLPa61qSlFxLFeAC8XbwyCQ9Qv4z6o5skWk1qmMUbEHeMqaGUTEzk+q2XyhZ0sju1FV4iLevQ/aw==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "polyclip-ts", - "tslib@2.8.1" - ] - }, - "@turf/invariant@7.2.0": { - "integrity": "sha512-kV4u8e7Gkpq+kPbAKNC21CmyrXzlbBgFjO1PhrHPgEdNqXqDawoZ3i6ivE3ULJj2rSesCjduUaC/wyvH/sNr2Q==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/isobands@7.2.0": { - "integrity": "sha512-lYoHeRieFzpBp29Jh19QcDIb0E+dzo/K5uwZuNga4wxr6heNU0AfkD4ByAHYIXHtvmp4m/JpSKq/2N6h/zvBkg==", - "dependencies": [ - "@turf/area", - "@turf/bbox", - "@turf/boolean-point-in-polygon", - "@turf/explode", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "marchingsquares", - "tslib@2.8.1" - ] - }, - "@turf/isolines@7.2.0": { - "integrity": "sha512-4ZXKxvA/JKkxAXixXhN3UVza5FABsdYgOWXyYm3L5ryTPJVOYTVSSd9A+CAVlv9dZc3YdlsqMqLTXNOOre/kwg==", - "dependencies": [ - "@turf/bbox", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "marchingsquares", - "tslib@2.8.1" - ] - }, - "@turf/jsts@2.7.2": { - "integrity": "sha512-zAezGlwWHPyU0zxwcX2wQY3RkRpwuoBmhhNE9HY9kWhFDkCxZ3aWK5URKwa/SWKJbj9aztO+8vtdiBA28KVJFg==", - "dependencies": [ - "jsts" - ] - }, - "@turf/kinks@7.2.0": { - "integrity": "sha512-BtxDxGewJR0Q5WR9HKBSxZhirFX+GEH1rD7/EvgDsHS8e1Y5/vNQQUmXdURjdPa4StzaUBsWRU5T3A356gLbPA==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/length@7.2.0": { - "integrity": "sha512-LBmYN+iCgVtWNLsckVnpQIJENqIIPO63mogazMp23lrDGfWXu07zZQ9ZinJVO5xYurXNhc/QI2xxoqt2Xw90Ig==", - "dependencies": [ - "@turf/distance", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/line-arc@7.2.0": { - "integrity": "sha512-kfWzA5oYrTpslTg5fN50G04zSypiYQzjZv3FLjbZkk6kta5fo4JkERKjTeA8x4XNojb+pfmjMBB0yIh2w2dDRw==", - "dependencies": [ - "@turf/circle", - "@turf/destination", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/line-chunk@7.2.0": { - "integrity": "sha512-1ODyL5gETtWSL85MPI0lgp/78vl95M39gpeBxePXyDIqx8geDP9kXfAzctuKdxBoR4JmOVM3NT7Fz7h+IEkC+g==", - "dependencies": [ - "@turf/helpers", - "@turf/length", - "@turf/line-slice-along", - "@turf/meta", - "@types/geojson" - ] - }, - "@turf/line-intersect@7.2.0": { - "integrity": "sha512-GhCJVEkc8EmggNi85EuVLoXF5T5jNVxmhIetwppiVyJzMrwkYAkZSYB3IBFYGUUB9qiNFnTwungVSsBV/S8ZiA==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "sweepline-intersections", - "tslib@2.8.1" - ] - }, - "@turf/line-offset@7.2.0": { - "integrity": "sha512-1+OkYueDCbnEWzbfBh3taVr+3SyM2bal5jfnSEuDiLA6jnlScgr8tn3INo+zwrUkPFZPPAejL1swVyO5TjUahw==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson" - ] - }, - "@turf/line-overlap@7.2.0": { - "integrity": "sha512-NNn7/jg53+N10q2Kyt66bEDqN3101iW/1zA5FW7J6UbKApDFkByh+18YZq1of71kS6oUYplP86WkDp16LFpqqw==", - "dependencies": [ - "@turf/boolean-point-on-line", - "@turf/geojson-rbush", - "@turf/helpers", - "@turf/invariant", - "@turf/line-segment", - "@turf/meta", - "@turf/nearest-point-on-line", - "@types/geojson", - "fast-deep-equal", - "tslib@2.8.1" - ] - }, - "@turf/line-segment@7.2.0": { - "integrity": "sha512-E162rmTF9XjVN4rINJCd15AdQGCBlNqeWN3V0YI1vOUpZFNT2ii4SqEMCcH2d+5EheHLL8BWVwZoOsvHZbvaWA==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/line-slice-along@7.2.0": { - "integrity": "sha512-4/gPgP0j5Rp+1prbhXqn7kIH/uZTmSgiubUnn67F8nb9zE+MhbRglhSlRYEZxAVkB7VrGwjyolCwvrROhjHp2A==", - "dependencies": [ - "@turf/bearing", - "@turf/destination", - "@turf/distance", - "@turf/helpers", - "@types/geojson" - ] - }, - "@turf/line-slice@7.2.0": { - "integrity": "sha512-bHotzZIaU1GPV3RMwttYpDrmcvb3X2i1g/WUttPZWtKrEo2VVAkoYdeZ2aFwtogERYS4quFdJ/TDzAtquBC8WQ==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@turf/nearest-point-on-line", - "@types/geojson" - ] - }, - "@turf/line-split@7.2.0": { - "integrity": "sha512-yJTZR+c8CwoKqdW/aIs+iLbuFwAa3Yan+EOADFQuXXIUGps3bJUXx/38rmowNoZbHyP1np1+OtrotyHu5uBsfQ==", - "dependencies": [ - "@turf/bbox", - "@turf/geojson-rbush", - "@turf/helpers", - "@turf/invariant", - "@turf/line-intersect", - "@turf/line-segment", - "@turf/meta", - "@turf/nearest-point-on-line", - "@turf/square", - "@turf/truncate", - "@types/geojson" - ] - }, - "@turf/line-to-polygon@7.2.0": { - "integrity": "sha512-iKpJqc7EYc5NvlD4KaqrKKO6mXR7YWO/YwtW60E2FnsF/blnsy9OfAOcilYHgH3S/V/TT0VedC7DW7Kgjy2EIA==", - "dependencies": [ - "@turf/bbox", - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/mask@7.2.0": { - "integrity": "sha512-ulJ6dQqXC0wrjIoqFViXuMUdIPX5Q6GPViZ3kGfeVijvlLM7kTFBsZiPQwALSr5nTQg4Ppf3FD0Jmg8IErPrgA==", - "dependencies": [ - "@turf/clone", - "@turf/helpers", - "@types/geojson", - "polyclip-ts", - "tslib@2.8.1" - ] - }, - "@turf/meta@7.2.0": { - "integrity": "sha512-igzTdHsQc8TV1RhPuOLVo74Px/hyPrVgVOTgjWQZzt3J9BVseCdpfY/0cJBdlSRI4S/yTmmHl7gAqjhpYH5Yaw==", - "dependencies": [ - "@turf/helpers", - "@types/geojson" - ] - }, - "@turf/midpoint@7.2.0": { - "integrity": "sha512-AMn5S9aSrbXdE+Q4Rj+T5nLdpfpn+mfzqIaEKkYI021HC0vb22HyhQHsQbSeX+AWcS4CjD1hFsYVcgKI+5qCfw==", - "dependencies": [ - "@turf/bearing", - "@turf/destination", - "@turf/distance", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/moran-index@7.2.0": { - "integrity": "sha512-Aexh1EmXVPJhApr9grrd120vbalIthcIsQ3OAN2Tqwf+eExHXArJEJqGBo9IZiQbIpFJeftt/OvUvlI8BeO1bA==", - "dependencies": [ - "@turf/distance-weight", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/nearest-neighbor-analysis@7.2.0": { - "integrity": "sha512-LmP/crXb7gilgsL0wL9hsygqc537W/a1W5r9XBKJT4SKdqjoXX5APJatJfd3nwXbRIqwDH0cDA9/YyFjBPlKnA==", - "dependencies": [ - "@turf/area", - "@turf/bbox", - "@turf/bbox-polygon", - "@turf/centroid", - "@turf/distance", - "@turf/helpers", - "@turf/meta", - "@turf/nearest-point", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/nearest-point-on-line@7.2.0": { - "integrity": "sha512-UOhAeoDPVewBQV+PWg1YTMQcYpJsIqfW5+EuZ5vJl60XwUa0+kqB/eVfSLNXmHENjKKIlEt9Oy9HIDF4VeWmXA==", - "dependencies": [ - "@turf/distance", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/nearest-point-to-line@7.2.0": { - "integrity": "sha512-EorU7Qj30A7nAjh++KF/eTPDlzwuuV4neBz7tmSTB21HKuXZAR0upJsx6M2X1CSyGEgNsbFB0ivNKIvymRTKBw==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/point-to-line-distance", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/nearest-point@7.2.0": { - "integrity": "sha512-0wmsqXZ8CGw4QKeZmS+NdjYTqCMC+HXZvM3XAQIU6k6laNLqjad2oS4nDrtcRs/nWDvcj1CR+Io7OiQ6sbpn5Q==", - "dependencies": [ - "@turf/clone", - "@turf/distance", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/planepoint@7.2.0": { - "integrity": "sha512-8Vno01tvi5gThUEKBQ46CmlEKDAwVpkl7stOPFvJYlA1oywjAL4PsmgwjXgleZuFtXQUPBNgv5a42Pf438XP4g==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/point-grid@7.2.0": { - "integrity": "sha512-ai7lwBV2FREPW3XiUNohT4opC1hd6+F56qZe20xYhCTkTD9diWjXHiNudQPSmVAUjgMzQGasblQQqvOdL+bJ3Q==", - "dependencies": [ - "@turf/boolean-within", - "@turf/distance", - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/point-on-feature@7.2.0": { - "integrity": "sha512-ksoYoLO9WtJ/qI8VI9ltF+2ZjLWrAjZNsCsu8F7nyGeCh4I8opjf4qVLytFG44XA2qI5yc6iXDpyv0sshvP82Q==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/center", - "@turf/explode", - "@turf/helpers", - "@turf/nearest-point", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/point-to-line-distance@7.2.0": { - "integrity": "sha512-fB9Rdnb5w5+t76Gho2dYDkGe20eRrFk8CXi4v1+l1PC8YyLXO+x+l3TrtT8HzL/dVaZeepO6WUIsIw3ditTOPg==", - "dependencies": [ - "@turf/bearing", - "@turf/distance", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/nearest-point-on-line", - "@turf/projection", - "@turf/rhumb-bearing", - "@turf/rhumb-distance", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/point-to-polygon-distance@7.2.0": { - "integrity": "sha512-w+WYuINgTiFjoZemQwOaQSje/8Kq+uqJOynvx7+gleQPHyWQ3VtTodtV4LwzVzXz8Sf7Mngx1Jcp2SNai5CJYA==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/point-to-line-distance", - "@turf/polygon-to-line", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/points-within-polygon@7.2.0": { - "integrity": "sha512-jRKp8/mWNMzA+hKlQhxci97H5nOio9tp14R2SzpvkOt+cswxl+NqTEi1hDd2XetA7tjU0TSoNjEgVY8FfA0S6w==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/polygon-smooth@7.2.0": { - "integrity": "sha512-KCp9wF2IEynvGXVhySR8oQ2razKP0zwg99K+fuClP21pSKCFjAPaihPEYq6e8uI/1J7ibjL5++6EMl+LrUTrLg==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/polygon-tangents@7.2.0": { - "integrity": "sha512-AHUUPmOjiQDrtP/ODXukHBlUG0C/9I1je7zz50OTfl2ZDOdEqFJQC3RyNELwq07grTXZvg5TS5wYx/Y7nsm47g==", - "dependencies": [ - "@turf/bbox", - "@turf/boolean-within", - "@turf/explode", - "@turf/helpers", - "@turf/invariant", - "@turf/nearest-point", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/polygon-to-line@7.2.0": { - "integrity": "sha512-9jeTN3LiJ933I5sd4K0kwkcivOYXXm1emk0dHorwXeSFSHF+nlYesEW3Hd889wb9lZd7/SVLMUeX/h39mX+vCA==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/polygonize@7.2.0": { - "integrity": "sha512-U9v+lBhUPDv+nsg/VcScdiqCB59afO6CHDGrwIl2+5i6Ve+/KQKjpTV/R+NqoC1iMXAEq3brY6HY8Ukp/pUWng==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/envelope", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/projection@7.2.0": { - "integrity": "sha512-/qke5vJScv8Mu7a+fU3RSChBRijE6EVuFHU3RYihMuYm04Vw8dBMIs0enEpoq0ke/IjSbleIrGQNZIMRX9EwZQ==", - "dependencies": [ - "@turf/clone", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/quadrat-analysis@7.2.0": { - "integrity": "sha512-fDQh3+ldYNxUqS6QYlvJ7GZLlCeDZR6tD3ikdYtOsSemwW1n/4gm2xcgWJqy3Y0uszBwxc13IGGY7NGEjHA+0w==", - "dependencies": [ - "@turf/area", - "@turf/bbox", - "@turf/bbox-polygon", - "@turf/centroid", - "@turf/helpers", - "@turf/invariant", - "@turf/point-grid", - "@turf/random", - "@turf/square-grid", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/random@7.2.0": { - "integrity": "sha512-fNXs5mOeXsrirliw84S8UCNkpm4RMNbefPNsuCTfZEXhcr1MuHMzq4JWKb4FweMdN1Yx2l/xcytkO0s71cJ50w==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/rectangle-grid@7.2.0": { - "integrity": "sha512-f0o5ifvy0Ml/nHDJzMNcuSk4h11aa3BfvQNnYQhLpuTQu03j/ICZNlzKTLxwjcUqvxADUifty7Z9CX5W6zky4A==", - "dependencies": [ - "@turf/boolean-intersects", - "@turf/distance", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/rewind@7.2.0": { - "integrity": "sha512-SZpRAZiZsE22+HVz6pEID+ST25vOdpAMGk5NO1JeqzhpMALIkIGnkG+xnun2CfYHz7wv8/Z0ADiAvei9rkcQYA==", - "dependencies": [ - "@turf/boolean-clockwise", - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/rhumb-bearing@7.2.0": { - "integrity": "sha512-jbdexlrR8X2ZauUciHx3tRwG+BXoMXke4B8p8/IgDlAfIrVdzAxSQN89FMzIKnjJ/kdLjo9bFGvb92bu31Etug==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/rhumb-destination@7.2.0": { - "integrity": "sha512-U9OLgLAHlH4Wfx3fBZf3jvnkDjdTcfRan5eI7VPV1+fQWkOteATpzkiRjCvSYK575GljVwWBjkKca8LziGWitQ==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/rhumb-distance@7.2.0": { - "integrity": "sha512-NsijTPON1yOc9tirRPEQQuJ5aQi7pREsqchQquaYKbHNWsexZjcDi4wnw2kM3Si4XjmgynT+2f7aXH7FHarHzw==", - "dependencies": [ - "@turf/helpers", - "@turf/invariant", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/sample@7.2.0": { - "integrity": "sha512-f+ZbcbQJ9glQ/F26re8LadxO0ORafy298EJZe6XtbctRTJrNus6UNAsl8+GYXFqMnXM22tbTAznnJX3ZiWNorA==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/sector@7.2.0": { - "integrity": "sha512-zL06MjbbMG4DdpiNz+Q9Ax8jsCekt3R76uxeWShulAGkyDB5smdBOUDoRwxn05UX7l4kKv4Ucq2imQXhxKFd1w==", - "dependencies": [ - "@turf/circle", - "@turf/helpers", - "@turf/invariant", - "@turf/line-arc", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/shortest-path@7.2.0": { - "integrity": "sha512-6fpx8feZ2jMSaeRaFdqFShGWkNb+veUOeyLFSHA/aRD9n/e9F2pWZoRbQWKbKTpcKFJ2FnDEqCZnh/GrcAsqWA==", - "dependencies": [ - "@turf/bbox", - "@turf/bbox-polygon", - "@turf/boolean-point-in-polygon", - "@turf/clean-coords", - "@turf/distance", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/transform-scale", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/simplify@7.2.0": { - "integrity": "sha512-9YHIfSc8BXQfi5IvEMbCeQYqNch0UawIGwbboJaoV8rodhtk6kKV2wrpXdGqk/6Thg6/RWvChJFKVVTjVrULyQ==", - "dependencies": [ - "@turf/clean-coords", - "@turf/clone", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/square-grid@7.2.0": { - "integrity": "sha512-EmzGXa90hz+tiCOs9wX+Lak6pH0Vghb7QuX6KZej+pmWi3Yz7vdvQLmy/wuN048+wSkD5c8WUo/kTeNDe7GnmA==", - "dependencies": [ - "@turf/helpers", - "@turf/rectangle-grid", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/square@7.2.0": { - "integrity": "sha512-9pMoAGFvqzCDOlO9IRSSBCGXKbl8EwMx6xRRBMKdZgpS0mZgfm9xiptMmx/t1m4qqHIlb/N+3MUF7iMBx6upcA==", - "dependencies": [ - "@turf/distance", - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/standard-deviational-ellipse@7.2.0": { - "integrity": "sha512-+uC0pR2nRjm90JvMXe/2xOCZsYV2II1ZZ2zmWcBWv6bcFXBspcxk2QfCC3k0bj6jDapELzoQgnn3cG5lbdQV2w==", - "dependencies": [ - "@turf/center-mean", - "@turf/ellipse", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/points-within-polygon", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/tag@7.2.0": { - "integrity": "sha512-TAFvsbp5TCBqXue8ui+CtcLsPZ6NPC88L8Ad6Hb/R6VAi21qe0U42WJHQYXzWmtThoTNwxi+oKSeFbRDsr0FIA==", - "dependencies": [ - "@turf/boolean-point-in-polygon", - "@turf/clone", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/tesselate@7.2.0": { - "integrity": "sha512-zHGcG85aOJJu1seCm+CYTJ3UempX4Xtyt669vFG6Hbr/Hc7ii6STQ2ysFr7lJwFtU9uyYhphVrrgwIqwglvI/Q==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "earcut@2.2.4", - "tslib@2.8.1" - ] - }, - "@turf/tin@7.2.0": { - "integrity": "sha512-y24Vt3oeE6ZXvyLJamP0Ke02rPlDGE9gF7OFADnR0mT+2uectb0UTIBC3kKzON80TEAlA3GXpKFkCW5Fo/O/Kg==", - "dependencies": [ - "@turf/helpers", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/transform-rotate@7.2.0": { - "integrity": "sha512-EMCj0Zqy3cF9d3mGRqDlYnX2ZBXe3LgT+piDR0EuF5c5sjuKErcFcaBIsn/lg1gp4xCNZFinkZ3dsFfgGHf6fw==", - "dependencies": [ - "@turf/centroid", - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/rhumb-bearing", - "@turf/rhumb-destination", - "@turf/rhumb-distance", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/transform-scale@7.2.0": { - "integrity": "sha512-HYB+pw938eeI8s1/zSWFy6hq+t38fuUaBb0jJsZB1K9zQ1WjEYpPvKF/0//80zNPlyxLv3cOkeBucso3hzI07A==", - "dependencies": [ - "@turf/bbox", - "@turf/center", - "@turf/centroid", - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/rhumb-bearing", - "@turf/rhumb-destination", - "@turf/rhumb-distance", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/transform-translate@7.2.0": { - "integrity": "sha512-zAglR8MKCqkzDTjGMIQgbg/f+Q3XcKVzr9cELw5l9CrS1a0VTSDtBZLDm0kWx0ankwtam7ZmI2jXyuQWT8Gbug==", - "dependencies": [ - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@turf/meta", - "@turf/rhumb-destination", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/triangle-grid@7.2.0": { - "integrity": "sha512-4gcAqWKh9hg6PC5nNSb9VWyLgl821cwf9yR9yEzQhEFfwYL/pZONBWCO1cwVF23vSYMSMm+/TwqxH4emxaArfw==", - "dependencies": [ - "@turf/distance", - "@turf/helpers", - "@turf/intersect", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/truncate@7.2.0": { - "integrity": "sha512-jyFzxYbPugK4XjV5V/k6Xr3taBjjvo210IbPHJXw0Zh7Y6sF+hGxeRVtSuZ9VP/6oRyqAOHKUrze+OOkPqBgUg==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/turf@7.2.0": { - "integrity": "sha512-G1kKBu4hYgoNoRJgnpJohNuS7bLnoWHZ2G/4wUMym5xOSiYah6carzdTEsMoTsauyi7ilByWHx5UHwbjjCVcBw==", - "dependencies": [ - "@turf/along", - "@turf/angle", - "@turf/area", - "@turf/bbox", - "@turf/bbox-clip", - "@turf/bbox-polygon", - "@turf/bearing", - "@turf/bezier-spline", - "@turf/boolean-clockwise", - "@turf/boolean-concave", - "@turf/boolean-contains", - "@turf/boolean-crosses", - "@turf/boolean-disjoint", - "@turf/boolean-equal", - "@turf/boolean-intersects", - "@turf/boolean-overlap", - "@turf/boolean-parallel", - "@turf/boolean-point-in-polygon", - "@turf/boolean-point-on-line", - "@turf/boolean-touches", - "@turf/boolean-valid", - "@turf/boolean-within", - "@turf/buffer", - "@turf/center", - "@turf/center-mean", - "@turf/center-median", - "@turf/center-of-mass", - "@turf/centroid", - "@turf/circle", - "@turf/clean-coords", - "@turf/clone", - "@turf/clusters", - "@turf/clusters-dbscan", - "@turf/clusters-kmeans", - "@turf/collect", - "@turf/combine", - "@turf/concave", - "@turf/convex", - "@turf/destination", - "@turf/difference", - "@turf/dissolve", - "@turf/distance", - "@turf/distance-weight", - "@turf/ellipse", - "@turf/envelope", - "@turf/explode", - "@turf/flatten", - "@turf/flip", - "@turf/geojson-rbush", - "@turf/great-circle", - "@turf/helpers", - "@turf/hex-grid", - "@turf/interpolate", - "@turf/intersect", - "@turf/invariant", - "@turf/isobands", - "@turf/isolines", - "@turf/kinks", - "@turf/length", - "@turf/line-arc", - "@turf/line-chunk", - "@turf/line-intersect", - "@turf/line-offset", - "@turf/line-overlap", - "@turf/line-segment", - "@turf/line-slice", - "@turf/line-slice-along", - "@turf/line-split", - "@turf/line-to-polygon", - "@turf/mask", - "@turf/meta", - "@turf/midpoint", - "@turf/moran-index", - "@turf/nearest-neighbor-analysis", - "@turf/nearest-point", - "@turf/nearest-point-on-line", - "@turf/nearest-point-to-line", - "@turf/planepoint", - "@turf/point-grid", - "@turf/point-on-feature", - "@turf/point-to-line-distance", - "@turf/point-to-polygon-distance", - "@turf/points-within-polygon", - "@turf/polygon-smooth", - "@turf/polygon-tangents", - "@turf/polygon-to-line", - "@turf/polygonize", - "@turf/projection", - "@turf/quadrat-analysis", - "@turf/random", - "@turf/rectangle-grid", - "@turf/rewind", - "@turf/rhumb-bearing", - "@turf/rhumb-destination", - "@turf/rhumb-distance", - "@turf/sample", - "@turf/sector", - "@turf/shortest-path", - "@turf/simplify", - "@turf/square", - "@turf/square-grid", - "@turf/standard-deviational-ellipse", - "@turf/tag", - "@turf/tesselate", - "@turf/tin", - "@turf/transform-rotate", - "@turf/transform-scale", - "@turf/transform-translate", - "@turf/triangle-grid", - "@turf/truncate", - "@turf/union", - "@turf/unkink-polygon", - "@turf/voronoi", - "@types/geojson", - "tslib@2.8.1" - ] - }, - "@turf/union@7.2.0": { - "integrity": "sha512-Xex/cfKSmH0RZRWSJl4RLlhSmEALVewywiEXcu0aIxNbuZGTcpNoI0h4oLFrE/fUd0iBGFg/EGLXRL3zTfpg6g==", - "dependencies": [ - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "polyclip-ts", - "tslib@2.8.1" - ] - }, - "@turf/unkink-polygon@7.2.0": { - "integrity": "sha512-dFPfzlIgkEr15z6oXVxTSWshWi51HeITGVFtl1GAKGMtiXJx1uMqnfRsvljqEjaQu/4AzG1QAp3b+EkSklQSiQ==", - "dependencies": [ - "@turf/area", - "@turf/boolean-point-in-polygon", - "@turf/helpers", - "@turf/meta", - "@types/geojson", - "rbush@3.0.1", - "tslib@2.8.1" - ] - }, - "@turf/voronoi@7.2.0": { - "integrity": "sha512-3K6N0LtJsWTXxPb/5N2qD9e8f4q8+tjTbGV3lE3v8x06iCnNlnuJnqM5NZNPpvgvCatecBkhClO3/3RndE61Fw==", - "dependencies": [ - "@turf/clone", - "@turf/helpers", - "@turf/invariant", - "@types/d3-voronoi", - "@types/geojson", - "d3-voronoi", - "tslib@2.8.1" - ] - }, - "@tybys/wasm-util@0.9.0": { - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dependencies": [ - "tslib@2.8.1" - ] - }, - "@types/aria-query@5.0.4": { - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" - }, - "@types/babel__core@7.20.5": { - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dependencies": [ - "@babel/parser", - "@babel/types", - "@types/babel__generator", - "@types/babel__template", - "@types/babel__traverse" - ] - }, - "@types/babel__generator@7.27.0": { - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dependencies": [ - "@babel/types" - ] - }, - "@types/babel__template@7.4.4": { - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dependencies": [ - "@babel/parser", - "@babel/types" - ] - }, - "@types/babel__traverse@7.20.7": { - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dependencies": [ - "@babel/types" - ] - }, - "@types/chai@5.2.2": { - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", - "dependencies": [ - "@types/deep-eql" - ] - }, - "@types/chrome@0.0.318": { - "integrity": "sha512-rrtyYQ1t+g7EyG0FejE+UXQBjSGUHGh0RIdXwUT/laPo9T724NOIgXA94ns6ewmNauwijYa5ck3+dBxWnHcynQ==", - "dependencies": [ - "@types/filesystem", - "@types/har-format" - ] - }, - "@types/d3-voronoi@1.1.12": { - "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==" - }, - "@types/deep-eql@4.0.2": { - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==" - }, - "@types/estree@0.0.39": { - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" - }, - "@types/estree@1.0.8": { - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" - }, - "@types/filesystem@0.0.36": { - "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==", - "dependencies": [ - "@types/filewriter" - ] - }, - "@types/filewriter@0.0.33": { - "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==" - }, - "@types/geojson-vt@3.2.5": { - "integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==", - "dependencies": [ - "@types/geojson" - ] - }, - "@types/geojson@7946.0.16": { - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==" - }, - "@types/har-format@1.2.16": { - "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==" - }, - "@types/js-cookie@3.0.6": { - "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==" - }, - "@types/mapbox__point-geometry@0.1.4": { - "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==" - }, - "@types/mapbox__vector-tile@1.3.4": { - "integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==", - "dependencies": [ - "@types/geojson", - "@types/mapbox__point-geometry", - "@types/pbf" - ] - }, - "@types/node@22.15.15": { - "integrity": "sha512-R5muMcZob3/Jjchn5LcO8jdKwSCbzqmPB6ruBxMcf9kbxtniZHP327s6C37iOfuw8mbKK3cAQa7sEl7afLrQ8A==", - "dependencies": [ - "undici-types" - ] - }, - "@types/node@22.15.32": { - "integrity": "sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==", - "dependencies": [ - "undici-types" - ] - }, - "@types/pbf@3.0.5": { - "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" - }, - "@types/react-dom@19.1.6_@types+react@19.1.8": { - "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", - "dependencies": [ - "@types/react" - ] - }, - "@types/react@19.1.8": { - "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", - "dependencies": [ - "csstype" - ] - }, - "@types/resolve@1.20.2": { - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==" - }, - "@types/serviceworker@0.0.133": { - "integrity": "sha512-lEyAbLUMztFbps2GVZ5mKIXl5+BZiGfOOA8JxN6KTiT91Ct31lSAHISKUl2+iOwmrUwNvWeI9rbsFxFqDZCghQ==" - }, - "@types/supercluster@7.1.3": { - "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", - "dependencies": [ - "@types/geojson" - ] - }, - "@types/trusted-types@2.0.7": { - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" - }, - "@types/w3c-web-serial@1.0.8": { - "integrity": "sha512-QQOT+bxQJhRGXoZDZGLs3ksLud1dMNnMiSQtBA0w8KXvLpXX4oM4TZb6J0GgJ8UbCaHo5s9/4VQT8uXy9JER2A==" - }, - "@types/web-bluetooth@0.0.21": { - "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==" - }, - "@vis.gl/react-mapbox@8.0.4_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-NFk0vsWcNzSs0YCsVdt2100Zli9QWR+pje8DacpLkkGEAXFaJsFtI1oKD0Hatiate4/iAIW39SQHhgfhbeEPfQ==", - "dependencies": [ - "react", - "react-dom" - ] - }, - "@vis.gl/react-maplibre@8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-HwZyfLjEu+y1mUFvwDAkVxinGm8fEegaWN+O8np/WZ2Sqe5Lv6OXFpV6GWz9LOEvBYMbGuGk1FQdejo+4HCJ5w==", - "dependencies": [ - "@maplibre/maplibre-gl-style-spec@19.3.3", - "maplibre-gl", - "react", - "react-dom" - ], - "optionalPeers": [ - "maplibre-gl" - ] - }, - "@vitejs/plugin-react@4.6.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_@types+node@22.15.32": { - "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", - "dependencies": [ - "@babel/core", - "@babel/plugin-transform-react-jsx-self", - "@babel/plugin-transform-react-jsx-source", - "@rolldown/pluginutils", - "@types/babel__core", - "react-refresh", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2" - ] - }, - "@vitejs/plugin-react@4.6.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@babel+core@7.27.4_@types+node@22.15.32_@types+node@22.15.15": { - "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", - "dependencies": [ - "@babel/core", - "@babel/plugin-transform-react-jsx-self", - "@babel/plugin-transform-react-jsx-source", - "@rolldown/pluginutils", - "@types/babel__core", - "react-refresh", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15" - ] - }, - "@vitest/expect@3.2.4": { - "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", - "dependencies": [ - "@types/chai", - "@vitest/spy", - "@vitest/utils", - "chai", - "tinyrainbow" - ] - }, - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32": { - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", - "dependencies": [ - "@vitest/spy", - "estree-walker@3.0.3", - "magic-string@0.30.17", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2" - ], - "optionalPeers": [ - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2" - ] - }, - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32_@types+node@22.15.15": { - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", - "dependencies": [ - "@vitest/spy", - "estree-walker@3.0.3", - "magic-string@0.30.17", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15" - ], - "optionalPeers": [ - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15" - ] - }, - "@vitest/pretty-format@3.2.4": { - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", - "dependencies": [ - "tinyrainbow" - ] - }, - "@vitest/runner@3.2.4": { - "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", - "dependencies": [ - "@vitest/utils", - "pathe", - "strip-literal" - ] - }, - "@vitest/snapshot@3.2.4": { - "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", - "dependencies": [ - "@vitest/pretty-format", - "magic-string@0.30.17", - "pathe" - ] - }, - "@vitest/spy@3.2.4": { - "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", - "dependencies": [ - "tinyspy" - ] - }, - "@vitest/utils@3.2.4": { - "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", - "dependencies": [ - "@vitest/pretty-format", - "loupe", - "tinyrainbow" - ] - }, - "acorn@8.15.0": { - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "bin": true - }, - "ajv@8.17.1": { - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": [ - "fast-deep-equal", - "fast-uri", - "json-schema-traverse", - "require-from-string" - ] - }, - "ansi-regex@5.0.1": { - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles@4.3.0": { - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": [ - "color-convert" - ] - }, - "ansi-styles@5.2.0": { - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" - }, - "ansis@4.1.0": { - "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==" - }, - "anymatch@3.1.3": { - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": [ - "normalize-path", - "picomatch@2.3.1" - ] - }, - "aria-hidden@1.2.6": { - "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", - "dependencies": [ - "tslib@2.8.1" - ] - }, - "aria-query@5.3.0": { - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dependencies": [ - "dequal" - ] - }, - "aria-query@5.3.2": { - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==" - }, - "arr-union@3.1.0": { - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" - }, - "array-buffer-byte-length@1.0.2": { - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dependencies": [ - "call-bound", - "is-array-buffer" - ] - }, - "arraybuffer.prototype.slice@1.0.4": { - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dependencies": [ - "array-buffer-byte-length", - "call-bind", - "define-properties", - "es-abstract", - "es-errors", - "get-intrinsic", - "is-array-buffer" - ] - }, - "assertion-error@2.0.1": { - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==" - }, - "assign-symbols@1.0.0": { - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" - }, - "ast-types@0.16.1": { - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "dependencies": [ - "tslib@2.8.1" - ] - }, - "async-function@1.0.0": { - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==" - }, - "async@3.2.6": { - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" - }, - "at-least-node@1.0.0": { - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "autoprefixer@10.4.21_postcss@8.5.6": { - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "dependencies": [ - "browserslist", - "caniuse-lite", - "fraction.js", - "normalize-range", - "picocolors", - "postcss", - "postcss-value-parser" - ], - "bin": true - }, - "available-typed-arrays@1.0.7": { - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": [ - "possible-typed-array-names" - ] - }, - "babel-dead-code-elimination@1.0.10": { - "integrity": "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA==", - "dependencies": [ - "@babel/core", - "@babel/parser", - "@babel/traverse", - "@babel/types" - ] - }, - "babel-plugin-polyfill-corejs2@0.4.13_@babel+core@7.27.4": { - "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", - "dependencies": [ - "@babel/compat-data", - "@babel/core", - "@babel/helper-define-polyfill-provider", - "semver" - ] - }, - "babel-plugin-polyfill-corejs3@0.11.1_@babel+core@7.27.4": { - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", - "dependencies": [ - "@babel/core", - "@babel/helper-define-polyfill-provider", - "core-js-compat" - ] - }, - "babel-plugin-polyfill-regenerator@0.6.4_@babel+core@7.27.4": { - "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", - "dependencies": [ - "@babel/core", - "@babel/helper-define-polyfill-provider" - ] - }, - "balanced-match@1.0.2": { - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js@1.5.1": { - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bignumber.js@9.3.0": { - "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==" - }, - "binary-extensions@2.3.0": { - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==" - }, - "brace-expansion@1.1.12": { - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dependencies": [ - "balanced-match", - "concat-map" - ] - }, - "brace-expansion@2.0.2": { - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dependencies": [ - "balanced-match" - ] - }, - "braces@3.0.3": { - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": [ - "fill-range" - ] - }, - "browserslist@4.25.0": { - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", - "dependencies": [ - "caniuse-lite", - "electron-to-chromium", - "node-releases", - "update-browserslist-db" - ], - "bin": true - }, - "buffer-from@1.1.2": { - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "bytewise-core@1.2.3": { - "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", - "dependencies": [ - "typewise-core" - ] - }, - "bytewise@1.1.0": { - "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", - "dependencies": [ - "bytewise-core", - "typewise" - ] - }, - "cac@6.7.14": { - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==" - }, - "call-bind-apply-helpers@1.0.2": { - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": [ - "es-errors", - "function-bind" - ] - }, - "call-bind@1.0.8": { - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dependencies": [ - "call-bind-apply-helpers", - "es-define-property", - "get-intrinsic", - "set-function-length" - ] - }, - "call-bound@1.0.4": { - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": [ - "call-bind-apply-helpers", - "get-intrinsic" - ] - }, - "caniuse-lite@1.0.30001724": { - "integrity": "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==" - }, - "chai@5.2.0": { - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dependencies": [ - "assertion-error", - "check-error", - "deep-eql", - "loupe", - "pathval" - ] - }, - "chalk@3.0.0": { - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": [ - "ansi-styles@4.3.0", - "supports-color" - ] - }, - "chalk@4.1.2": { - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": [ - "ansi-styles@4.3.0", - "supports-color" - ] - }, - "check-error@2.1.1": { - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==" - }, - "chokidar@3.6.0": { - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": [ - "anymatch", - "braces", - "glob-parent", - "is-binary-path", - "is-glob", - "normalize-path", - "readdirp" - ], - "optionalDependencies": [ - "fsevents" - ] - }, - "chownr@3.0.0": { - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" - }, - "class-variance-authority@0.7.1": { - "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", - "dependencies": [ - "clsx" - ] - }, - "cliui@8.0.1": { - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": [ - "string-width", - "strip-ansi", - "wrap-ansi" - ] - }, - "clsx@2.1.1": { - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" - }, - "cmdk@1.1.1_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8": { - "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", - "dependencies": [ - "@radix-ui/react-compose-refs", - "@radix-ui/react-dialog", - "@radix-ui/react-id", - "@radix-ui/react-primitive", - "react", - "react-dom" - ] - }, - "color-convert@2.0.1": { - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": [ - "color-name" - ] - }, - "color-name@1.1.4": { - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "commander@12.1.0": { - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==" - }, - "commander@2.20.3": { - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "common-tags@1.8.2": { - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" - }, - "concat-map@0.0.1": { - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "concaveman@1.2.1": { - "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==", - "dependencies": [ - "point-in-polygon", - "rbush@3.0.1", - "robust-predicates@2.0.4", - "tinyqueue@2.0.3" - ] - }, - "convert-source-map@2.0.0": { - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "core-js-compat@3.43.0": { - "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", - "dependencies": [ - "browserslist" - ] - }, - "core-util-is@1.0.3": { - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "crc@4.3.2": { - "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==" - }, - "cross-fetch@4.0.0": { - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dependencies": [ - "node-fetch" - ] - }, - "crypto-random-string@2.0.0": { - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" - }, - "crypto-random-string@5.0.0": { - "integrity": "sha512-KWjTXWwxFd6a94m5CdRGW/t82Tr8DoBc9dNnPCAbFI1EBweN6v1tv8y4Y1m7ndkp/nkIBRxUxAzpaBnR2k3bcQ==", - "dependencies": [ - "type-fest@2.19.0" - ] - }, - "css.escape@1.5.1": { - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "csstype@3.1.3": { - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "d3-array@1.2.4": { - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-geo@1.7.1": { - "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", - "dependencies": [ - "d3-array" - ] - }, - "d3-voronoi@1.1.2": { - "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==" - }, - "data-view-buffer@1.0.2": { - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dependencies": [ - "call-bound", - "es-errors", - "is-data-view" - ] - }, - "data-view-byte-length@1.0.2": { - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dependencies": [ - "call-bound", - "es-errors", - "is-data-view" - ] - }, - "data-view-byte-offset@1.0.1": { - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dependencies": [ - "call-bound", - "es-errors", - "is-data-view" - ] - }, - "debug@4.4.1": { - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dependencies": [ - "ms" - ] - }, - "deep-eql@5.0.2": { - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==" - }, - "deepmerge@4.3.1": { - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - }, - "define-data-property@1.1.4": { - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": [ - "es-define-property", - "es-errors", - "gopd" - ] - }, - "define-properties@1.2.1": { - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": [ - "define-data-property", - "has-property-descriptors", - "object-keys" - ] - }, - "dequal@2.0.3": { - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" - }, - "detect-libc@2.0.4": { - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==" - }, - "detect-node-es@1.1.0": { - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" - }, - "diff@8.0.2": { - "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==" - }, - "dom-accessibility-api@0.5.16": { - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" - }, - "dom-accessibility-api@0.6.3": { - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==" - }, - "dunder-proto@1.0.1": { - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": [ - "call-bind-apply-helpers", - "es-errors", - "gopd" - ] - }, - "duplex-maker@1.0.0": { - "integrity": "sha512-KoHuzggxg7f+vvjqOHfXxaQYI1POzBm+ah0eec7YDssZmbt6QFBI8d1nl5GQwAgR2f+VQCPvyvZtmWWqWuFtlA==" - }, - "duplexify@3.7.1": { - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dependencies": [ - "end-of-stream", - "inherits", - "readable-stream@2.3.8", - "stream-shift" - ] - }, - "earcut@2.2.4": { - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" - }, - "earcut@3.0.1": { - "integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==" - }, - "ejs@3.1.10": { - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dependencies": [ - "jake" - ], - "bin": true - }, - "electron-to-chromium@1.5.171": { - "integrity": "sha512-scWpzXEJEMrGJa4Y6m/tVotb0WuvNmasv3wWVzUAeCgKU0ToFOhUW6Z+xWnRQANMYGxN4ngJXIThgBJOqzVPCQ==" - }, - "emoji-regex@8.0.0": { - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "end-of-stream@1.4.5": { - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dependencies": [ - "once" - ] - }, - "enhanced-resolve@5.18.1": { - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", - "dependencies": [ - "graceful-fs", - "tapable" - ] - }, - "es-abstract@1.24.0": { - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", - "dependencies": [ - "array-buffer-byte-length", - "arraybuffer.prototype.slice", - "available-typed-arrays", - "call-bind", - "call-bound", - "data-view-buffer", - "data-view-byte-length", - "data-view-byte-offset", - "es-define-property", - "es-errors", - "es-object-atoms", - "es-set-tostringtag", - "es-to-primitive", - "function.prototype.name", - "get-intrinsic", - "get-proto", - "get-symbol-description", - "globalthis", - "gopd", - "has-property-descriptors", - "has-proto", - "has-symbols", - "hasown", - "internal-slot", - "is-array-buffer", - "is-callable", - "is-data-view", - "is-negative-zero", - "is-regex", - "is-set", - "is-shared-array-buffer", - "is-string", - "is-typed-array", - "is-weakref", - "math-intrinsics", - "object-inspect", - "object-keys", - "object.assign", - "own-keys", - "regexp.prototype.flags", - "safe-array-concat", - "safe-push-apply", - "safe-regex-test", - "set-proto", - "stop-iteration-iterator", - "string.prototype.trim", - "string.prototype.trimend", - "string.prototype.trimstart", - "typed-array-buffer", - "typed-array-byte-length", - "typed-array-byte-offset", - "typed-array-length", - "unbox-primitive", - "which-typed-array" - ] - }, - "es-define-property@1.0.1": { - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" - }, - "es-errors@1.3.0": { - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-module-lexer@1.7.0": { - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==" - }, - "es-object-atoms@1.1.1": { - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": [ - "es-errors" - ] - }, - "es-set-tostringtag@2.1.0": { - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dependencies": [ - "es-errors", - "get-intrinsic", - "has-tostringtag", - "hasown" - ] - }, - "es-to-primitive@1.3.0": { - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dependencies": [ - "is-callable", - "is-date-object", - "is-symbol" - ] - }, - "esbuild@0.25.5": { - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", - "optionalDependencies": [ - "@esbuild/aix-ppc64", - "@esbuild/android-arm", - "@esbuild/android-arm64", - "@esbuild/android-x64", - "@esbuild/darwin-arm64", - "@esbuild/darwin-x64", - "@esbuild/freebsd-arm64", - "@esbuild/freebsd-x64", - "@esbuild/linux-arm", - "@esbuild/linux-arm64", - "@esbuild/linux-ia32", - "@esbuild/linux-loong64", - "@esbuild/linux-mips64el", - "@esbuild/linux-ppc64", - "@esbuild/linux-riscv64", - "@esbuild/linux-s390x", - "@esbuild/linux-x64", - "@esbuild/netbsd-arm64", - "@esbuild/netbsd-x64", - "@esbuild/openbsd-arm64", - "@esbuild/openbsd-x64", - "@esbuild/sunos-x64", - "@esbuild/win32-arm64", - "@esbuild/win32-ia32", - "@esbuild/win32-x64" - ], - "scripts": true, - "bin": true - }, - "escalade@3.2.0": { - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" - }, - "esprima@4.0.1": { - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": true - }, - "estree-walker@1.0.1": { - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" - }, - "estree-walker@2.0.2": { - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "estree-walker@3.0.3": { - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dependencies": [ - "@types/estree@1.0.8" - ] - }, - "esutils@2.0.3": { - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "expect-type@1.2.1": { - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==" - }, - "extend-shallow@2.0.1": { - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": [ - "is-extendable@0.1.1" - ] - }, - "extend-shallow@3.0.2": { - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dependencies": [ - "assign-symbols", - "is-extendable@1.0.1" - ] - }, - "fast-deep-equal@3.1.3": { - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify@2.1.0": { - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-uri@3.0.6": { - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==" - }, - "fdir@6.4.6_picomatch@4.0.2": { - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dependencies": [ - "picomatch@4.0.2" - ], - "optionalPeers": [ - "picomatch@4.0.2" - ] - }, - "filelist@1.0.4": { - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dependencies": [ - "minimatch@5.1.6" - ] - }, - "fill-range@7.1.1": { - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": [ - "to-regex-range" - ] - }, - "for-each@0.3.5": { - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dependencies": [ - "is-callable" - ] - }, - "fraction.js@4.3.7": { - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==" - }, - "fs-extra@9.1.0": { - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": [ - "at-least-node", - "graceful-fs", - "jsonfile", - "universalify" - ] - }, - "fs.realpath@1.0.0": { - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents@2.3.3": { - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "os": ["darwin"], - "scripts": true - }, - "function-bind@1.1.2": { - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "function.prototype.name@1.1.8": { - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dependencies": [ - "call-bind", - "call-bound", - "define-properties", - "functions-have-names", - "hasown", - "is-callable" - ] - }, - "functions-have-names@1.2.3": { - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "gensync@1.0.0-beta.2": { - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, - "geojson-equality-ts@1.0.2": { - "integrity": "sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==", - "dependencies": [ - "@types/geojson" - ] - }, - "geojson-polygon-self-intersections@1.2.1": { - "integrity": "sha512-/QM1b5u2d172qQVO//9CGRa49jEmclKEsYOQmWP9ooEjj63tBM51m2805xsbxkzlEELQ2REgTf700gUhhlegxA==", - "dependencies": [ - "rbush@2.0.2" - ] - }, - "geojson-vt@4.0.2": { - "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==" - }, - "get-caller-file@2.0.5": { - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic@1.3.0": { - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": [ - "call-bind-apply-helpers", - "es-define-property", - "es-errors", - "es-object-atoms", - "function-bind", - "get-proto", - "gopd", - "has-symbols", - "hasown", - "math-intrinsics" - ] - }, - "get-nonce@1.0.1": { - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==" - }, - "get-own-enumerable-property-symbols@3.0.2": { - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, - "get-proto@1.0.1": { - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": [ - "dunder-proto", - "es-object-atoms" - ] - }, - "get-stream@6.0.1": { - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "get-symbol-description@1.1.0": { - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic" - ] - }, - "get-tsconfig@4.10.1": { - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", - "dependencies": [ - "resolve-pkg-maps" - ] - }, - "get-value@2.0.6": { - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" - }, - "gl-matrix@3.4.3": { - "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" - }, - "glob-parent@5.1.2": { - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": [ - "is-glob" - ] - }, - "glob@7.2.3": { - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": [ - "fs.realpath", - "inflight", - "inherits", - "minimatch@3.1.2", - "once", - "path-is-absolute" - ], - "deprecated": true - }, - "global-prefix@4.0.0": { - "integrity": "sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==", - "dependencies": [ - "ini", - "kind-of", - "which" - ] - }, - "globals@11.12.0": { - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, - "globalthis@1.0.4": { - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dependencies": [ - "define-properties", - "gopd" - ] - }, - "goober@2.1.16_csstype@3.1.3": { - "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", - "dependencies": [ - "csstype" - ] - }, - "gopd@1.2.0": { - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" - }, - "graceful-fs@4.2.11": { - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "gzipper@8.2.1": { - "integrity": "sha512-Vp2vDpwU4xKtWxTaLPfNTR4euqHJamB6aKCfSEbSd/CrgqihwNxrjihJcWJG1+3Ku1ROsfF6fPXRoytTFLhFlw==", - "dependencies": [ - "@gfx/zopfli", - "commander@12.1.0", - "simple-zstd" - ], - "bin": true - }, - "happy-dom@17.6.3": { - "integrity": "sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==", - "dependencies": [ - "webidl-conversions@7.0.0", - "whatwg-mimetype" - ] - }, - "has-bigints@1.1.0": { - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==" - }, - "has-flag@4.0.0": { - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-property-descriptors@1.0.2": { - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": [ - "es-define-property" - ] - }, - "has-proto@1.2.0": { - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dependencies": [ - "dunder-proto" - ] - }, - "has-symbols@1.1.0": { - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" - }, - "has-tostringtag@1.0.2": { - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": [ - "has-symbols" - ] - }, - "hasown@2.0.2": { - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": [ - "function-bind" - ] - }, - "html-parse-stringify@3.0.1": { - "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", - "dependencies": [ - "void-elements" - ] - }, - "i18next-browser-languagedetector@8.2.0": { - "integrity": "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==", - "dependencies": [ - "@babel/runtime" - ] - }, - "i18next-http-backend@3.0.2": { - "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==", - "dependencies": [ - "cross-fetch" - ] - }, - "i18next@25.2.1_typescript@5.8.3": { - "integrity": "sha512-+UoXK5wh+VlE1Zy5p6MjcvctHXAhRwQKCxiJD8noKZzIXmnAX8gdHX5fLPA3MEVxEN4vbZkQFy8N0LyD9tUqPw==", - "dependencies": [ - "@babel/runtime", - "typescript" - ], - "optionalPeers": [ - "typescript" - ] - }, - "idb-keyval@6.2.2": { - "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==" - }, - "idb@7.1.1": { - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" - }, - "ieee754@1.2.1": { - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "immer@10.1.1": { - "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==" - }, - "indent-string@4.0.0": { - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "inflight@1.0.6": { - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": [ - "once", - "wrappy" - ], - "deprecated": true - }, - "inherits@2.0.4": { - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini@4.1.3": { - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==" - }, - "internal-slot@1.1.0": { - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dependencies": [ - "es-errors", - "hasown", - "side-channel" - ] - }, - "is-array-buffer@3.0.5": { - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dependencies": [ - "call-bind", - "call-bound", - "get-intrinsic" - ] - }, - "is-async-function@2.1.1": { - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dependencies": [ - "async-function", - "call-bound", - "get-proto", - "has-tostringtag", - "safe-regex-test" - ] - }, - "is-bigint@1.1.0": { - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dependencies": [ - "has-bigints" - ] - }, - "is-binary-path@2.1.0": { - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": [ - "binary-extensions" - ] - }, - "is-boolean-object@1.2.2": { - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dependencies": [ - "call-bound", - "has-tostringtag" - ] - }, - "is-callable@1.2.7": { - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" - }, - "is-core-module@2.16.1": { - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dependencies": [ - "hasown" - ] - }, - "is-data-view@1.0.2": { - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dependencies": [ - "call-bound", - "get-intrinsic", - "is-typed-array" - ] - }, - "is-date-object@1.1.0": { - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dependencies": [ - "call-bound", - "has-tostringtag" - ] - }, - "is-extendable@0.1.1": { - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" - }, - "is-extendable@1.0.1": { - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": [ - "is-plain-object" - ] - }, - "is-extglob@2.1.1": { - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-finalizationregistry@1.1.1": { - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dependencies": [ - "call-bound" - ] - }, - "is-fullwidth-code-point@3.0.0": { - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-generator-function@1.1.0": { - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dependencies": [ - "call-bound", - "get-proto", - "has-tostringtag", - "safe-regex-test" - ] - }, - "is-glob@4.0.3": { - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": [ - "is-extglob" - ] - }, - "is-map@2.0.3": { - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" - }, - "is-module@1.0.0": { - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" - }, - "is-negative-zero@2.0.3": { - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" - }, - "is-number-object@1.1.1": { - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dependencies": [ - "call-bound", - "has-tostringtag" - ] - }, - "is-number@7.0.0": { - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-obj@1.0.1": { - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" - }, - "is-plain-object@2.0.4": { - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": [ - "isobject" - ] - }, - "is-regex@1.2.1": { - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dependencies": [ - "call-bound", - "gopd", - "has-tostringtag", - "hasown" - ] - }, - "is-regexp@1.0.0": { - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" - }, - "is-set@2.0.3": { - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" - }, - "is-shared-array-buffer@1.0.4": { - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dependencies": [ - "call-bound" - ] - }, - "is-stream@2.0.1": { - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "is-string@1.1.1": { - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dependencies": [ - "call-bound", - "has-tostringtag" - ] - }, - "is-symbol@1.1.1": { - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dependencies": [ - "call-bound", - "has-symbols", - "safe-regex-test" - ] - }, - "is-typed-array@1.1.15": { - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dependencies": [ - "which-typed-array" - ] - }, - "is-weakmap@2.0.2": { - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" - }, - "is-weakref@1.1.1": { - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dependencies": [ - "call-bound" - ] - }, - "is-weakset@2.0.4": { - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dependencies": [ - "call-bound", - "get-intrinsic" - ] - }, - "is-zst@1.0.0": { - "integrity": "sha512-ZA5lvshKAl8z30dX7saXLpVhpsq3d2EHK9uf7qtUjnOtdw4XBpAoWb2RvZ5kyoaebdoidnGI0g2hn9Z7ObPbww==" - }, - "isarray@1.0.0": { - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isarray@2.0.5": { - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "isexe@3.1.1": { - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" - }, - "isobject@3.0.1": { - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" - }, - "jake@10.9.2": { - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", - "dependencies": [ - "async", - "chalk@4.1.2", - "filelist", - "minimatch@3.1.2" - ], - "bin": true - }, - "jiti@2.4.2": { - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "bin": true - }, - "js-cookie@3.0.5": { - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" - }, - "js-tokens@4.0.0": { - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-tokens@9.0.1": { - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==" - }, - "jsesc@3.0.2": { - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "bin": true - }, - "jsesc@3.1.0": { - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "bin": true - }, - "json-schema-traverse@1.0.0": { - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "json-schema@0.4.0": { - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-stringify-pretty-compact@3.0.0": { - "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" - }, - "json-stringify-pretty-compact@4.0.0": { - "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==" - }, - "json5@2.2.3": { - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": true - }, - "jsonfile@6.1.0": { - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": [ - "universalify" - ], - "optionalDependencies": [ - "graceful-fs" - ] - }, - "jsonpointer@5.0.1": { - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" - }, - "jsts@2.7.1": { - "integrity": "sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==" - }, - "kdbush@4.0.2": { - "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" - }, - "kind-of@6.0.3": { - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "leven@3.1.0": { - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - }, - "lightningcss-darwin-arm64@1.30.1": { - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "os": ["darwin"], - "cpu": ["arm64"] - }, - "lightningcss-darwin-x64@1.30.1": { - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "os": ["darwin"], - "cpu": ["x64"] - }, - "lightningcss-freebsd-x64@1.30.1": { - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "os": ["freebsd"], - "cpu": ["x64"] - }, - "lightningcss-linux-arm-gnueabihf@1.30.1": { - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "os": ["linux"], - "cpu": ["arm"] - }, - "lightningcss-linux-arm64-gnu@1.30.1": { - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "lightningcss-linux-arm64-musl@1.30.1": { - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "os": ["linux"], - "cpu": ["arm64"] - }, - "lightningcss-linux-x64-gnu@1.30.1": { - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "os": ["linux"], - "cpu": ["x64"] - }, - "lightningcss-linux-x64-musl@1.30.1": { - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "os": ["linux"], - "cpu": ["x64"] - }, - "lightningcss-win32-arm64-msvc@1.30.1": { - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "os": ["win32"], - "cpu": ["arm64"] - }, - "lightningcss-win32-x64-msvc@1.30.1": { - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "os": ["win32"], - "cpu": ["x64"] - }, - "lightningcss@1.30.1": { - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dependencies": [ - "detect-libc" - ], - "optionalDependencies": [ - "lightningcss-darwin-arm64", - "lightningcss-darwin-x64", - "lightningcss-freebsd-x64", - "lightningcss-linux-arm-gnueabihf", - "lightningcss-linux-arm64-gnu", - "lightningcss-linux-arm64-musl", - "lightningcss-linux-x64-gnu", - "lightningcss-linux-x64-musl", - "lightningcss-win32-arm64-msvc", - "lightningcss-win32-x64-msvc" - ] - }, - "lodash.debounce@4.0.8": { - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "lodash.isequal@4.5.0": { - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "deprecated": true - }, - "lodash.sortby@4.7.0": { - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" - }, - "lodash@4.17.21": { - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "loupe@3.1.4": { - "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==" - }, - "lru-cache@5.1.1": { - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": [ - "yallist@3.1.1" - ] - }, - "lucide-react@0.507.0_react@19.1.0": { - "integrity": "sha512-XfgE6gvAHwAtnbUvWiTTHx4S3VGR+cUJHEc0vrh9Ogu672I1Tue2+Cp/8JJqpytgcBHAB1FVI297W4XGNwc2dQ==", - "dependencies": [ - "react" - ] - }, - "lz-string@1.5.0": { - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "bin": true - }, - "magic-string@0.25.9": { - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dependencies": [ - "sourcemap-codec" - ] - }, - "magic-string@0.30.17": { - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dependencies": [ - "@jridgewell/sourcemap-codec" - ] - }, - "maplibre-gl@5.4.0": { - "integrity": "sha512-ZVrtdFIhFAqt53H2k5Ssqn7QIKNI19fW+He5tr4loxZxWZffp1aZYY9ImNncAJaALU/NYlV6Eul7UVB56/N7WQ==", - "dependencies": [ - "@mapbox/geojson-rewind", - "@mapbox/jsonlint-lines-primitives", - "@mapbox/point-geometry", - "@mapbox/tiny-sdf", - "@mapbox/unitbezier", - "@mapbox/vector-tile", - "@mapbox/whoots-js", - "@maplibre/maplibre-gl-style-spec@23.3.0", - "@types/geojson", - "@types/geojson-vt", - "@types/mapbox__point-geometry", - "@types/mapbox__vector-tile", - "@types/pbf", - "@types/supercluster", - "earcut@3.0.1", - "geojson-vt", - "gl-matrix", - "global-prefix", - "kdbush", - "murmurhash-js", - "pbf", - "potpack", - "quickselect@3.0.0", - "supercluster", - "tinyqueue@3.0.0", - "vt-pbf" - ] - }, - "marchingsquares@1.3.3": { - "integrity": "sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==" - }, - "math-intrinsics@1.1.0": { - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" - }, - "min-indent@1.0.1": { - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" - }, - "minimatch@3.1.2": { - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": [ - "brace-expansion@1.1.12" - ] - }, - "minimatch@5.1.6": { - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": [ - "brace-expansion@2.0.2" - ] - }, - "minimist@1.2.8": { - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minipass@7.1.2": { - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" - }, - "minizlib@3.0.2": { - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dependencies": [ - "minipass" - ] - }, - "mkdirp@3.0.1": { - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "bin": true - }, - "ms@2.1.3": { - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "murmurhash-js@1.0.0": { - "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" - }, - "nanoid@3.3.11": { - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "bin": true - }, - "node-fetch@2.7.0": { - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": [ - "whatwg-url@5.0.0" - ] - }, - "node-releases@2.0.19": { - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" - }, - "normalize-path@3.0.0": { - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-range@0.1.2": { - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" - }, - "object-inspect@1.13.4": { - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" - }, - "object-keys@1.1.1": { - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign@4.1.7": { - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dependencies": [ - "call-bind", - "call-bound", - "define-properties", - "es-object-atoms", - "has-symbols", - "object-keys" - ] - }, - "once@1.4.0": { - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": [ - "wrappy" - ] - }, - "own-keys@1.0.1": { - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dependencies": [ - "get-intrinsic", - "object-keys", - "safe-push-apply" - ] - }, - "path-is-absolute@1.0.1": { - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-parse@1.0.7": { - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "pathe@2.0.3": { - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" - }, - "pathval@2.0.1": { - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==" - }, - "pbf@3.3.0": { - "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", - "dependencies": [ - "ieee754", - "resolve-protobuf-schema" - ], - "bin": true - }, - "peek-stream@1.1.3": { - "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", - "dependencies": [ - "buffer-from", - "duplexify", - "through2@2.0.5" - ] - }, - "picocolors@1.1.1": { - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "picomatch@2.3.1": { - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "picomatch@4.0.2": { - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" - }, - "point-in-polygon-hao@1.2.4": { - "integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==", - "dependencies": [ - "robust-predicates@3.0.2" - ] - }, - "point-in-polygon@1.1.0": { - "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==" - }, - "polyclip-ts@0.16.8": { - "integrity": "sha512-JPtKbDRuPEuAjuTdhR62Gph7Is2BS1Szx69CFOO3g71lpJDFo78k4tFyi+qFOMVPePEzdSKkpGU3NBXPHHjvKQ==", - "dependencies": [ - "bignumber.js", - "splaytree-ts" - ] - }, - "possible-typed-array-names@1.1.0": { - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==" - }, - "postcss-value-parser@4.2.0": { - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "postcss@8.5.6": { - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dependencies": [ - "nanoid", - "picocolors", - "source-map-js" - ] - }, - "potpack@2.0.0": { - "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==" - }, - "prettier@3.6.1": { - "integrity": "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==", - "bin": true - }, - "pretty-bytes@5.6.0": { - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" - }, - "pretty-bytes@6.1.1": { - "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==" - }, - "pretty-format@27.5.1": { - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dependencies": [ - "ansi-regex", - "ansi-styles@5.2.0", - "react-is" - ] - }, - "process-nextick-args@2.0.1": { - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "process-streams@1.0.3": { - "integrity": "sha512-xkIaM5vYnyekB88WyET78YEqXiaJRy0xcvIdE22n+myhvBT7LlLmX6iAtq7jDvVH8CUx2rqQsd32JdRyJMV3NA==", - "dependencies": [ - "duplex-maker" - ] - }, - "protocol-buffers-schema@3.6.0": { - "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" - }, - "punycode@2.3.1": { - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - }, - "qrcode-generator@1.5.0": { - "integrity": "sha512-sqo7otiDq5rA4djRkFI7IjLQqxRrLpIou0d3rqr03JJLUGf5raPh91xCio+lFFbQf0SlcVckStz0EmDEX3EeZA==" - }, - "quickselect@1.1.1": { - "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" - }, - "quickselect@2.0.0": { - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" - }, - "quickselect@3.0.0": { - "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==" - }, - "randombytes@2.1.0": { - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": [ - "safe-buffer@5.2.1" - ] - }, - "rbush@2.0.2": { - "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==", - "dependencies": [ - "quickselect@1.1.1" - ] - }, - "rbush@3.0.1": { - "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", - "dependencies": [ - "quickselect@2.0.0" - ] - }, - "react-dom@19.1.0_react@19.1.0": { - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", - "dependencies": [ - "react", - "scheduler" - ] - }, - "react-error-boundary@6.0.0_react@19.1.0": { - "integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==", - "dependencies": [ - "@babel/runtime", - "react" - ] - }, - "react-hook-form@7.58.1_react@19.1.0": { - "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==", - "dependencies": [ - "react" - ] - }, - "react-i18next@15.5.3_i18next@25.2.1__typescript@5.8.3_react@19.1.0_typescript@5.8.3": { - "integrity": "sha512-ypYmOKOnjqPEJZO4m1BI0kS8kWqkBNsKYyhVUfij0gvjy9xJNoG/VcGkxq5dRlVwzmrmY1BQMAmpbbUBLwC4Kw==", - "dependencies": [ - "@babel/runtime", - "html-parse-stringify", - "i18next", - "react", - "typescript" - ], - "optionalPeers": [ - "typescript" - ] - }, - "react-is@17.0.2": { - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "react-map-gl@8.0.4_maplibre-gl@5.4.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-SHdpvFIvswsZBg6BCPcwY/nbKuCo3sJM1Cj7Sd+gA3gFRFOixD+KtZ2XSuUWq2WySL2emYEXEgrLZoXsV4Ut4Q==", - "dependencies": [ - "@vis.gl/react-mapbox", - "@vis.gl/react-maplibre", - "maplibre-gl", - "react", - "react-dom" - ], - "optionalPeers": [ - "maplibre-gl" - ] - }, - "react-qrcode-logo@3.0.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-2+vZ3GNBdUpYxIKyt6SFZsDGXa0xniyUQ0wPI4O0hJTzRjttPIx1pPnH9IWQmp/4nDMoN47IBhi3Breu1KudYw==", - "dependencies": [ - "lodash.isequal", - "qrcode-generator", - "react", - "react-dom" - ] - }, - "react-refresh@0.17.0": { - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==" - }, - "react-remove-scroll-bar@2.3.8_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", - "dependencies": [ - "@types/react", - "react", - "react-style-singleton", - "tslib@2.8.1" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "react-remove-scroll@2.7.1_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", - "dependencies": [ - "@types/react", - "react", - "react-remove-scroll-bar", - "react-style-singleton", - "tslib@2.8.1", - "use-callback-ref", - "use-sidecar" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "react-style-singleton@2.2.3_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", - "dependencies": [ - "@types/react", - "get-nonce", - "react", - "tslib@2.8.1" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "react@19.1.0": { - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==" - }, - "readable-stream@2.3.8": { - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": [ - "core-util-is", - "inherits", - "isarray@1.0.0", - "process-nextick-args", - "safe-buffer@5.1.2", - "string_decoder@1.1.1", - "util-deprecate" - ] - }, - "readable-stream@3.6.2": { - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": [ - "inherits", - "string_decoder@1.3.0", - "util-deprecate" - ] - }, - "readdirp@3.6.0": { - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": [ - "picomatch@2.3.1" - ] - }, - "recast@0.23.11": { - "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", - "dependencies": [ - "ast-types", - "esprima", - "source-map@0.6.1", - "tiny-invariant", - "tslib@2.8.1" - ] - }, - "redent@3.0.0": { - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dependencies": [ - "indent-string", - "strip-indent" - ] - }, - "reflect.getprototypeof@1.0.10": { - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dependencies": [ - "call-bind", - "define-properties", - "es-abstract", - "es-errors", - "es-object-atoms", - "get-intrinsic", - "get-proto", - "which-builtin-type" - ] - }, - "regenerate-unicode-properties@10.2.0": { - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dependencies": [ - "regenerate" - ] - }, - "regenerate@1.4.2": { - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "regexp.prototype.flags@1.5.4": { - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dependencies": [ - "call-bind", - "define-properties", - "es-errors", - "get-proto", - "gopd", - "set-function-name" - ] - }, - "regexpu-core@6.2.0": { - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "dependencies": [ - "regenerate", - "regenerate-unicode-properties", - "regjsgen", - "regjsparser", - "unicode-match-property-ecmascript", - "unicode-match-property-value-ecmascript" - ] - }, - "regjsgen@0.8.0": { - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" - }, - "regjsparser@0.12.0": { - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "dependencies": [ - "jsesc@3.0.2" - ], - "bin": true - }, - "require-directory@2.1.1": { - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "require-from-string@2.0.2": { - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - }, - "resolve-pkg-maps@1.0.0": { - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==" - }, - "resolve-protobuf-schema@2.1.0": { - "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", - "dependencies": [ - "protocol-buffers-schema" - ] - }, - "resolve@1.22.10": { - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dependencies": [ - "is-core-module", - "path-parse", - "supports-preserve-symlinks-flag" - ], - "bin": true - }, - "rfc4648@1.5.4": { - "integrity": "sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==" - }, - "robust-predicates@2.0.4": { - "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" - }, - "robust-predicates@3.0.2": { - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" - }, - "rollup@2.79.2": { - "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", - "optionalDependencies": [ - "fsevents" - ], - "bin": true - }, - "rollup@4.44.0": { - "integrity": "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==", - "dependencies": [ - "@types/estree@1.0.8" - ], - "optionalDependencies": [ - "@rollup/rollup-android-arm-eabi", - "@rollup/rollup-android-arm64", - "@rollup/rollup-darwin-arm64", - "@rollup/rollup-darwin-x64", - "@rollup/rollup-freebsd-arm64", - "@rollup/rollup-freebsd-x64", - "@rollup/rollup-linux-arm-gnueabihf", - "@rollup/rollup-linux-arm-musleabihf", - "@rollup/rollup-linux-arm64-gnu", - "@rollup/rollup-linux-arm64-musl", - "@rollup/rollup-linux-loongarch64-gnu", - "@rollup/rollup-linux-powerpc64le-gnu", - "@rollup/rollup-linux-riscv64-gnu", - "@rollup/rollup-linux-riscv64-musl", - "@rollup/rollup-linux-s390x-gnu", - "@rollup/rollup-linux-x64-gnu", - "@rollup/rollup-linux-x64-musl", - "@rollup/rollup-win32-arm64-msvc", - "@rollup/rollup-win32-ia32-msvc", - "@rollup/rollup-win32-x64-msvc", - "fsevents" - ], - "bin": true - }, - "rw@1.3.3": { - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, - "rxjs@6.6.7": { - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": [ - "tslib@1.14.1" - ] - }, - "safe-array-concat@1.1.3": { - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dependencies": [ - "call-bind", - "call-bound", - "get-intrinsic", - "has-symbols", - "isarray@2.0.5" - ] - }, - "safe-buffer@5.1.2": { - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-buffer@5.2.1": { - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safe-push-apply@1.0.0": { - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dependencies": [ - "es-errors", - "isarray@2.0.5" - ] - }, - "safe-regex-test@1.1.0": { - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dependencies": [ - "call-bound", - "es-errors", - "is-regex" - ] - }, - "scheduler@0.26.0": { - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" - }, - "semver@6.3.1": { - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": true - }, - "serialize-javascript@6.0.2": { - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": [ - "randombytes" - ] - }, - "seroval-plugins@1.3.2_seroval@1.3.2": { - "integrity": "sha512-0QvCV2lM3aj/U3YozDiVwx9zpH0q8A60CTWIv4Jszj/givcudPb48B+rkU5D51NJ0pTpweGMttHjboPa9/zoIQ==", - "dependencies": [ - "seroval" - ] - }, - "seroval@1.3.2": { - "integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==" - }, - "set-function-length@1.2.2": { - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": [ - "define-data-property", - "es-errors", - "function-bind", - "get-intrinsic", - "gopd", - "has-property-descriptors" - ] - }, - "set-function-name@2.0.2": { - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": [ - "define-data-property", - "es-errors", - "functions-have-names", - "has-property-descriptors" - ] - }, - "set-proto@1.0.0": { - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dependencies": [ - "dunder-proto", - "es-errors", - "es-object-atoms" - ] - }, - "set-value@2.0.1": { - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dependencies": [ - "extend-shallow@2.0.1", - "is-extendable@0.1.1", - "is-plain-object", - "split-string" - ] - }, - "side-channel-list@1.0.0": { - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dependencies": [ - "es-errors", - "object-inspect" - ] - }, - "side-channel-map@1.0.1": { - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic", - "object-inspect" - ] - }, - "side-channel-weakmap@1.0.2": { - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": [ - "call-bound", - "es-errors", - "get-intrinsic", - "object-inspect", - "side-channel-map" - ] - }, - "side-channel@1.1.0": { - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": [ - "es-errors", - "object-inspect", - "side-channel-list", - "side-channel-map", - "side-channel-weakmap" - ] - }, - "siginfo@2.0.0": { - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" - }, - "simple-git-hooks@2.13.0": { - "integrity": "sha512-N+goiLxlkHJlyaYEglFypzVNMaNplPAk5syu0+OPp/Bk6dwVoXF6FfOw2vO0Dp+JHsBaI+w6cm8TnFl2Hw6tDA==", - "scripts": true, - "bin": true - }, - "simple-zstd@1.4.2": { - "integrity": "sha512-kGYEvT33M5XfyQvvW4wxl3eKcWbdbCc1V7OZzuElnaXft0qbVzoIIXHXiCm3JCUki+MZKKmvjl8p2VGLJc5Y/A==", - "dependencies": [ - "is-zst", - "peek-stream", - "process-streams", - "through2@4.0.2" - ] - }, - "skmeans@0.9.7": { - "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" - }, - "smob@1.5.0": { - "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==" - }, - "solid-js@1.9.7_seroval@1.3.2": { - "integrity": "sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==", - "dependencies": [ - "csstype", - "seroval", - "seroval-plugins" - ] - }, - "sort-asc@0.2.0": { - "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==" - }, - "sort-desc@0.2.0": { - "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==" - }, - "sort-object@3.0.3": { - "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", - "dependencies": [ - "bytewise", - "get-value", - "is-extendable@0.1.1", - "sort-asc", - "sort-desc", - "union-value" - ] - }, - "source-map-js@1.2.1": { - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" - }, - "source-map-support@0.5.21": { - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": [ - "buffer-from", - "source-map@0.6.1" - ] - }, - "source-map@0.6.1": { - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map@0.7.4": { - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" - }, - "source-map@0.8.0-beta.0": { - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dependencies": [ - "whatwg-url@7.1.0" - ] - }, - "sourcemap-codec@1.4.8": { - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": true - }, - "splaytree-ts@1.0.2": { - "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==" - }, - "split-string@3.1.0": { - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dependencies": [ - "extend-shallow@3.0.2" - ] - }, - "stackback@0.0.2": { - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" - }, - "std-env@3.9.0": { - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==" - }, - "ste-core@3.0.11": { - "integrity": "sha512-ivkRENMh0mdGoPlZ4xVcEaC8rXQfTEfvonRw5m8VDKV7kgcbZbaNd1TnKl08wXbcLdT7okSc63HNP8cVhy95zg==" - }, - "ste-simple-events@3.0.11": { - "integrity": "sha512-PDoQajqiTtJLNDWfJCihzACiTVZyFsXi6hNAVNelNJoNmqj+BaWuhJ/NHaAHxzfSRoMbL+hFgfPqFmxiHhAQSQ==", - "dependencies": [ - "ste-core" - ] - }, - "stop-iteration-iterator@1.1.0": { - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dependencies": [ - "es-errors", - "internal-slot" - ] - }, - "stream-shift@1.0.3": { - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" - }, - "string-width@4.2.3": { - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": [ - "emoji-regex", - "is-fullwidth-code-point", - "strip-ansi" - ] - }, - "string.prototype.matchall@4.0.12": { - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dependencies": [ - "call-bind", - "call-bound", - "define-properties", - "es-abstract", - "es-errors", - "es-object-atoms", - "get-intrinsic", - "gopd", - "has-symbols", - "internal-slot", - "regexp.prototype.flags", - "set-function-name", - "side-channel" - ] - }, - "string.prototype.trim@1.2.10": { - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dependencies": [ - "call-bind", - "call-bound", - "define-data-property", - "define-properties", - "es-abstract", - "es-object-atoms", - "has-property-descriptors" - ] - }, - "string.prototype.trimend@1.0.9": { - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dependencies": [ - "call-bind", - "call-bound", - "define-properties", - "es-object-atoms" - ] - }, - "string.prototype.trimstart@1.0.8": { - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dependencies": [ - "call-bind", - "define-properties", - "es-object-atoms" - ] - }, - "string_decoder@1.1.1": { - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": [ - "safe-buffer@5.1.2" - ] - }, - "string_decoder@1.3.0": { - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": [ - "safe-buffer@5.2.1" - ] - }, - "stringify-object@3.3.0": { - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dependencies": [ - "get-own-enumerable-property-symbols", - "is-obj", - "is-regexp" - ] - }, - "strip-ansi@6.0.1": { - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": [ - "ansi-regex" - ] - }, - "strip-comments@2.0.1": { - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" - }, - "strip-indent@3.0.0": { - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dependencies": [ - "min-indent" - ] - }, - "strip-literal@3.0.0": { - "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", - "dependencies": [ - "js-tokens@9.0.1" - ] - }, - "supercluster@8.0.1": { - "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", - "dependencies": [ - "kdbush" - ] - }, - "supports-color@7.2.0": { - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": [ - "has-flag" - ] - }, - "supports-preserve-symlinks-flag@1.0.0": { - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "sweepline-intersections@1.5.0": { - "integrity": "sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==", - "dependencies": [ - "tinyqueue@2.0.3" - ] - }, - "tailwind-merge@3.3.1": { - "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==" - }, - "tailwindcss-animate@1.0.7_tailwindcss@4.1.10": { - "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "dependencies": [ - "tailwindcss" - ] - }, - "tailwindcss@4.1.10": { - "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==" - }, - "tapable@2.2.2": { - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==" - }, - "tar@7.4.3": { - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dependencies": [ - "@isaacs/fs-minipass", - "chownr", - "minipass", - "minizlib", - "mkdirp", - "yallist@5.0.0" - ] - }, - "temp-dir@2.0.0": { - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" - }, - "tempy@0.6.0": { - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", - "dependencies": [ - "is-stream", - "temp-dir", - "type-fest@0.16.0", - "unique-string" - ] - }, - "terser@5.43.1": { - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", - "dependencies": [ - "@jridgewell/source-map", - "acorn", - "commander@2.20.3", - "source-map-support" - ], - "bin": true - }, - "testing-library@0.0.2_@angular+common@6.1.10__@angular+core@6.1.10___rxjs@6.6.7___zone.js@0.8.29__rxjs@6.6.7_@angular+core@6.1.10__rxjs@6.6.7__zone.js@0.8.29": { - "integrity": "sha512-KCbqCCllbgiCXOgmh9MdsgdJ05pmimXGuggtC78pzpxpq/40A3bS+NJoqwCIqZbNnMr6KIZ2mlMZoZCkWVnaWw==", - "dependencies": [ - "@angular/common", - "@angular/core", - "tslib@1.14.1" - ] - }, - "through2@2.0.5": { - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": [ - "readable-stream@2.3.8", - "xtend" - ] - }, - "through2@4.0.2": { - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dependencies": [ - "readable-stream@3.6.2" - ] - }, - "tiny-invariant@1.3.3": { - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, - "tiny-warning@1.0.3": { - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "tinybench@2.9.0": { - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==" - }, - "tinyexec@0.3.2": { - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==" - }, - "tinyglobby@0.2.14_picomatch@4.0.2": { - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dependencies": [ - "fdir", - "picomatch@4.0.2" - ] - }, - "tinypool@1.1.1": { - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==" - }, - "tinyqueue@2.0.3": { - "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" - }, - "tinyqueue@3.0.0": { - "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==" - }, - "tinyrainbow@2.0.0": { - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==" - }, - "tinyspy@4.0.3": { - "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==" - }, - "to-regex-range@5.0.1": { - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": [ - "is-number" - ] - }, - "topojson-client@3.1.0": { - "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", - "dependencies": [ - "commander@2.20.3" - ], - "bin": true - }, - "topojson-server@3.0.1": { - "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==", - "dependencies": [ - "commander@2.20.3" - ], - "bin": true - }, - "tr46@0.0.3": { - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tr46@1.0.1": { - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "dependencies": [ - "punycode" - ] - }, - "tslib@1.14.1": { - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "tslib@2.8.1": { - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "tslog@4.9.3": { - "integrity": "sha512-oDWuGVONxhVEBtschLf2cs/Jy8i7h1T+CpdkTNWQgdAF7DhRo2G8vMCgILKe7ojdEkLhICWgI1LYSSKaJsRgcw==" - }, - "tsx@4.20.3": { - "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", - "dependencies": [ - "esbuild", - "get-tsconfig" - ], - "optionalDependencies": [ - "fsevents" - ], - "bin": true - }, - "type-fest@0.16.0": { - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" - }, - "type-fest@2.19.0": { - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" - }, - "typed-array-buffer@1.0.3": { - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dependencies": [ - "call-bound", - "es-errors", - "is-typed-array" - ] - }, - "typed-array-byte-length@1.0.3": { - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dependencies": [ - "call-bind", - "for-each", - "gopd", - "has-proto", - "is-typed-array" - ] - }, - "typed-array-byte-offset@1.0.4": { - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dependencies": [ - "available-typed-arrays", - "call-bind", - "for-each", - "gopd", - "has-proto", - "is-typed-array", - "reflect.getprototypeof" - ] - }, - "typed-array-length@1.0.7": { - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dependencies": [ - "call-bind", - "for-each", - "gopd", - "is-typed-array", - "possible-typed-array-names", - "reflect.getprototypeof" - ] - }, - "typescript@5.8.3": { - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "bin": true - }, - "typewise-core@1.2.0": { - "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==" - }, - "typewise@1.0.3": { - "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", - "dependencies": [ - "typewise-core" - ] - }, - "unbox-primitive@1.1.0": { - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dependencies": [ - "call-bound", - "has-bigints", - "has-symbols", - "which-boxed-primitive" - ] - }, - "undici-types@6.21.0": { - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" - }, - "unicode-canonical-property-names-ecmascript@2.0.1": { - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==" - }, - "unicode-match-property-ecmascript@2.0.0": { - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dependencies": [ - "unicode-canonical-property-names-ecmascript", - "unicode-property-aliases-ecmascript" - ] - }, - "unicode-match-property-value-ecmascript@2.2.0": { - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==" - }, - "unicode-property-aliases-ecmascript@2.1.0": { - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" - }, - "union-value@1.0.1": { - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dependencies": [ - "arr-union", - "get-value", - "is-extendable@0.1.1", - "set-value" - ] - }, - "unique-string@2.0.0": { - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dependencies": [ - "crypto-random-string@2.0.0" - ] - }, - "universalify@2.0.1": { - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" - }, - "unplugin@2.3.5": { - "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==", - "dependencies": [ - "acorn", - "picomatch@4.0.2", - "webpack-virtual-modules" - ] - }, - "upath@1.2.0": { - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, - "update-browserslist-db@1.1.3_browserslist@4.25.0": { - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dependencies": [ - "browserslist", - "escalade", - "picocolors" - ], - "bin": true - }, - "use-callback-ref@1.3.3_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "dependencies": [ - "@types/react", - "react", - "tslib@2.8.1" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "use-sidecar@1.1.3_@types+react@19.1.8_react@19.1.0": { - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "dependencies": [ - "@types/react", - "detect-node-es", - "react", - "tslib@2.8.1" - ], - "optionalPeers": [ - "@types/react" - ] - }, - "use-sync-external-store@1.5.0_react@19.1.0": { - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "dependencies": [ - "react" - ] - }, - "util-deprecate@1.0.2": { - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "vite-node@3.2.4_@types+node@22.15.32": { - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", - "dependencies": [ - "cac", - "debug", - "es-module-lexer", - "pathe", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2" - ], - "bin": true - }, - "vite-node@3.2.4_@types+node@22.15.32_@types+node@22.15.15": { - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", - "dependencies": [ - "cac", - "debug", - "es-module-lexer", - "pathe", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15" - ], - "bin": true - }, - "vite-plugin-pwa@1.0.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.4__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.32": { - "integrity": "sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==", - "dependencies": [ - "debug", - "pretty-bytes@6.1.1", - "tinyglobby", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2", - "workbox-build", - "workbox-window" - ] - }, - "vite-plugin-pwa@1.0.0_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_workbox-build@7.3.0__ajv@8.17.1__@babel+core@7.27.4__rollup@2.79.2_workbox-window@7.3.0_@types+node@22.15.32_@types+node@22.15.15": { - "integrity": "sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==", - "dependencies": [ - "debug", - "pretty-bytes@6.1.1", - "tinyglobby", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15", - "workbox-build", - "workbox-window" - ] - }, - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2": { - "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", - "dependencies": [ - "@types/node@22.15.32", - "esbuild", - "fdir", - "picomatch@4.0.2", - "postcss", - "rollup@4.44.0", - "tinyglobby" - ], - "optionalDependencies": [ - "fsevents" - ], - "optionalPeers": [ - "@types/node@22.15.32" - ], - "bin": true - }, - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15": { - "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", - "dependencies": [ - "@types/node@22.15.15", - "esbuild", - "fdir", - "picomatch@4.0.2", - "postcss", - "rollup@4.44.0", - "tinyglobby" - ], - "optionalDependencies": [ - "fsevents" - ], - "optionalPeers": [ - "@types/node@22.15.15" - ], - "bin": true - }, - "vitest@3.2.4_@types+node@22.15.32_happy-dom@17.6.3_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2": { - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", - "dependencies": [ - "@types/chai", - "@types/node@22.15.32", - "@vitest/expect", - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32", - "@vitest/pretty-format", - "@vitest/runner", - "@vitest/snapshot", - "@vitest/spy", - "@vitest/utils", - "chai", - "debug", - "expect-type", - "happy-dom", - "magic-string@0.30.17", - "pathe", - "picomatch@4.0.2", - "std-env", - "tinybench", - "tinyexec", - "tinyglobby", - "tinypool", - "tinyrainbow", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2", - "vite-node@3.2.4_@types+node@22.15.32", - "why-is-node-running" - ], - "optionalPeers": [ - "@types/node@22.15.32", - "happy-dom" - ], - "bin": true - }, - "vitest@3.2.4_@types+node@22.15.32_happy-dom@17.6.3_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.15": { - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", - "dependencies": [ - "@types/chai", - "@types/node@22.15.15", - "@vitest/expect", - "@vitest/mocker@3.2.4_vite@7.0.0__@types+node@22.15.32__picomatch@4.0.2_@types+node@22.15.32_@types+node@22.15.15", - "@vitest/pretty-format", - "@vitest/runner", - "@vitest/snapshot", - "@vitest/spy", - "@vitest/utils", - "chai", - "debug", - "expect-type", - "happy-dom", - "magic-string@0.30.17", - "pathe", - "picomatch@4.0.2", - "std-env", - "tinybench", - "tinyexec", - "tinyglobby", - "tinypool", - "tinyrainbow", - "vite@7.0.0_@types+node@22.15.32_picomatch@4.0.2_@types+node@22.15.15", - "vite-node@3.2.4_@types+node@22.15.32_@types+node@22.15.15", - "why-is-node-running" - ], - "optionalPeers": [ - "@types/node@22.15.15", - "happy-dom" - ], - "bin": true - }, - "void-elements@3.1.0": { - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" - }, - "vt-pbf@3.1.3": { - "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==", - "dependencies": [ - "@mapbox/point-geometry", - "@mapbox/vector-tile", - "pbf" - ] - }, - "webidl-conversions@3.0.1": { - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "webidl-conversions@4.0.2": { - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "webidl-conversions@7.0.0": { - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" - }, - "webpack-virtual-modules@0.6.2": { - "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==" - }, - "whatwg-mimetype@3.0.0": { - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" - }, - "whatwg-url@5.0.0": { - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": [ - "tr46@0.0.3", - "webidl-conversions@3.0.1" - ] - }, - "whatwg-url@7.1.0": { - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dependencies": [ - "lodash.sortby", - "tr46@1.0.1", - "webidl-conversions@4.0.2" - ] - }, - "which-boxed-primitive@1.1.1": { - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dependencies": [ - "is-bigint", - "is-boolean-object", - "is-number-object", - "is-string", - "is-symbol" - ] - }, - "which-builtin-type@1.2.1": { - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dependencies": [ - "call-bound", - "function.prototype.name", - "has-tostringtag", - "is-async-function", - "is-date-object", - "is-finalizationregistry", - "is-generator-function", - "is-regex", - "is-weakref", - "isarray@2.0.5", - "which-boxed-primitive", - "which-collection", - "which-typed-array" - ] - }, - "which-collection@1.0.2": { - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dependencies": [ - "is-map", - "is-set", - "is-weakmap", - "is-weakset" - ] - }, - "which-typed-array@1.1.19": { - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dependencies": [ - "available-typed-arrays", - "call-bind", - "call-bound", - "for-each", - "get-proto", - "gopd", - "has-tostringtag" - ] - }, - "which@4.0.0": { - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dependencies": [ - "isexe" - ], - "bin": true - }, - "why-is-node-running@2.3.0": { - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dependencies": [ - "siginfo", - "stackback" - ], - "bin": true - }, - "workbox-background-sync@7.3.0": { - "integrity": "sha512-PCSk3eK7Mxeuyatb22pcSx9dlgWNv3+M8PqPaYDokks8Y5/FX4soaOqj3yhAZr5k6Q5JWTOMYgaJBpbw11G9Eg==", - "dependencies": [ - "idb", - "workbox-core" - ] - }, - "workbox-broadcast-update@7.3.0": { - "integrity": "sha512-T9/F5VEdJVhwmrIAE+E/kq5at2OY6+OXXgOWQevnubal6sO92Gjo24v6dCVwQiclAF5NS3hlmsifRrpQzZCdUA==", - "dependencies": [ - "workbox-core" - ] - }, - "workbox-build@7.3.0_ajv@8.17.1_@babel+core@7.27.4_rollup@2.79.2": { - "integrity": "sha512-JGL6vZTPlxnlqZRhR/K/msqg3wKP+m0wfEUVosK7gsYzSgeIxvZLi1ViJJzVL7CEeI8r7rGFV973RiEqkP3lWQ==", - "dependencies": [ - "@apideck/better-ajv-errors", - "@babel/core", - "@babel/preset-env", - "@babel/runtime", - "@rollup/plugin-babel", - "@rollup/plugin-node-resolve", - "@rollup/plugin-replace", - "@rollup/plugin-terser", - "@surma/rollup-plugin-off-main-thread", - "ajv", - "common-tags", - "fast-json-stable-stringify", - "fs-extra", - "glob", - "lodash", - "pretty-bytes@5.6.0", - "rollup@2.79.2", - "source-map@0.8.0-beta.0", - "stringify-object", - "strip-comments", - "tempy", - "upath", - "workbox-background-sync", - "workbox-broadcast-update", - "workbox-cacheable-response", - "workbox-core", - "workbox-expiration", - "workbox-google-analytics", - "workbox-navigation-preload", - "workbox-precaching", - "workbox-range-requests", - "workbox-recipes", - "workbox-routing", - "workbox-strategies", - "workbox-streams", - "workbox-sw", - "workbox-window" - ] - }, - "workbox-cacheable-response@7.3.0": { - "integrity": "sha512-eAFERIg6J2LuyELhLlmeRcJFa5e16Mj8kL2yCDbhWE+HUun9skRQrGIFVUagqWj4DMaaPSMWfAolM7XZZxNmxA==", - "dependencies": [ - "workbox-core" - ] - }, - "workbox-core@7.3.0": { - "integrity": "sha512-Z+mYrErfh4t3zi7NVTvOuACB0A/jA3bgxUN3PwtAVHvfEsZxV9Iju580VEETug3zYJRc0Dmii/aixI/Uxj8fmw==" - }, - "workbox-expiration@7.3.0": { - "integrity": "sha512-lpnSSLp2BM+K6bgFCWc5bS1LR5pAwDWbcKt1iL87/eTSJRdLdAwGQznZE+1czLgn/X05YChsrEegTNxjM067vQ==", - "dependencies": [ - "idb", - "workbox-core" - ] - }, - "workbox-google-analytics@7.3.0": { - "integrity": "sha512-ii/tSfFdhjLHZ2BrYgFNTrb/yk04pw2hasgbM70jpZfLk0vdJAXgaiMAWsoE+wfJDNWoZmBYY0hMVI0v5wWDbg==", - "dependencies": [ - "workbox-background-sync", - "workbox-core", - "workbox-routing", - "workbox-strategies" - ] - }, - "workbox-navigation-preload@7.3.0": { - "integrity": "sha512-fTJzogmFaTv4bShZ6aA7Bfj4Cewaq5rp30qcxl2iYM45YD79rKIhvzNHiFj1P+u5ZZldroqhASXwwoyusnr2cg==", - "dependencies": [ - "workbox-core" - ] - }, - "workbox-precaching@7.3.0": { - "integrity": "sha512-ckp/3t0msgXclVAYaNndAGeAoWQUv7Rwc4fdhWL69CCAb2UHo3Cef0KIUctqfQj1p8h6aGyz3w8Cy3Ihq9OmIw==", - "dependencies": [ - "workbox-core", - "workbox-routing", - "workbox-strategies" - ] - }, - "workbox-range-requests@7.3.0": { - "integrity": "sha512-EyFmM1KpDzzAouNF3+EWa15yDEenwxoeXu9bgxOEYnFfCxns7eAxA9WSSaVd8kujFFt3eIbShNqa4hLQNFvmVQ==", - "dependencies": [ - "workbox-core" - ] - }, - "workbox-recipes@7.3.0": { - "integrity": "sha512-BJro/MpuW35I/zjZQBcoxsctgeB+kyb2JAP5EB3EYzePg8wDGoQuUdyYQS+CheTb+GhqJeWmVs3QxLI8EBP1sg==", - "dependencies": [ - "workbox-cacheable-response", - "workbox-core", - "workbox-expiration", - "workbox-precaching", - "workbox-routing", - "workbox-strategies" - ] - }, - "workbox-routing@7.3.0": { - "integrity": "sha512-ZUlysUVn5ZUzMOmQN3bqu+gK98vNfgX/gSTZ127izJg/pMMy4LryAthnYtjuqcjkN4HEAx1mdgxNiKJMZQM76A==", - "dependencies": [ - "workbox-core" - ] - }, - "workbox-strategies@7.3.0": { - "integrity": "sha512-tmZydug+qzDFATwX7QiEL5Hdf7FrkhjaF9db1CbB39sDmEZJg3l9ayDvPxy8Y18C3Y66Nrr9kkN1f/RlkDgllg==", - "dependencies": [ - "workbox-core" - ] - }, - "workbox-streams@7.3.0": { - "integrity": "sha512-SZnXucyg8x2Y61VGtDjKPO5EgPUG5NDn/v86WYHX+9ZqvAsGOytP0Jxp1bl663YUuMoXSAtsGLL+byHzEuMRpw==", - "dependencies": [ - "workbox-core", - "workbox-routing" - ] - }, - "workbox-sw@7.3.0": { - "integrity": "sha512-aCUyoAZU9IZtH05mn0ACUpyHzPs0lMeJimAYkQkBsOWiqaJLgusfDCR+yllkPkFRxWpZKF8vSvgHYeG7LwhlmA==" - }, - "workbox-window@7.3.0": { - "integrity": "sha512-qW8PDy16OV1UBaUNGlTVcepzrlzyzNW/ZJvFQQs2j2TzGsg6IKjcpZC1RSquqQnTOafl5pCj5bGfAHlCjOOjdA==", - "dependencies": [ - "@types/trusted-types", - "workbox-core" - ] - }, - "wrap-ansi@7.0.0": { - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": [ - "ansi-styles@4.3.0", - "string-width", - "strip-ansi" - ] - }, - "wrappy@1.0.2": { - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "xtend@4.0.2": { - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n@5.0.8": { - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yallist@3.1.1": { - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yallist@5.0.0": { - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" - }, - "yargs-parser@21.1.1": { - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - }, - "yargs@17.7.2": { - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": [ - "cliui", - "escalade", - "get-caller-file", - "require-directory", - "string-width", - "y18n", - "yargs-parser" - ] - }, - "zod@3.25.67": { - "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==" - }, - "zone.js@0.8.29": { - "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" - }, - "zustand@5.0.5_@types+react@19.1.8_immer@10.1.1_react@19.1.0": { - "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==", - "dependencies": [ - "@types/react", - "immer", - "react" - ], - "optionalPeers": [ - "@types/react", - "immer", - "react" - ] - } - }, - "workspace": { - "members": { - "packages/web": { - "dependencies": [ - "jsr:@std/path@^1.1.0", - "npm:@types/w3c-web-serial@*", - "npm:@types/web-bluetooth@*" - ], - "packageJson": { - "dependencies": [ - "npm:@bufbuild/protobuf@^2.2.5", - "npm:@hookform/resolvers@^5.1.1", - "npm:@jsr/meshtastic__core@2.6.4", - "npm:@jsr/meshtastic__js@2.6.0-0", - "npm:@jsr/meshtastic__transport-http@*", - "npm:@jsr/meshtastic__transport-web-bluetooth@*", - "npm:@jsr/meshtastic__transport-web-serial@*", - "npm:@noble/curves@^1.9.0", - "npm:@radix-ui/react-accordion@^1.2.8", - "npm:@radix-ui/react-checkbox@^1.2.3", - "npm:@radix-ui/react-dialog@^1.1.11", - "npm:@radix-ui/react-dropdown-menu@^2.1.12", - "npm:@radix-ui/react-label@^2.1.4", - "npm:@radix-ui/react-menubar@^1.1.12", - "npm:@radix-ui/react-popover@^1.1.11", - "npm:@radix-ui/react-scroll-area@^1.2.6", - "npm:@radix-ui/react-select@^2.2.2", - "npm:@radix-ui/react-separator@^1.1.4", - "npm:@radix-ui/react-slider@^1.3.2", - "npm:@radix-ui/react-switch@^1.2.2", - "npm:@radix-ui/react-tabs@^1.1.9", - "npm:@radix-ui/react-toast@^1.2.11", - "npm:@radix-ui/react-toggle-group@^1.1.9", - "npm:@radix-ui/react-tooltip@^1.2.4", - "npm:@tailwindcss/postcss@^4.1.5", - "npm:@tanstack/react-router-devtools@^1.120.16", - "npm:@tanstack/react-router@^1.120.15", - "npm:@tanstack/router-cli@^1.121.37", - "npm:@tanstack/router-devtools@^1.120.15", - "npm:@tanstack/router-plugin@^1.120.15", - "npm:@testing-library/jest-dom@^6.6.3", - "npm:@testing-library/react@^16.3.0", - "npm:@testing-library/user-event@^14.6.1", - "npm:@turf/turf@^7.2.0", - "npm:@types/chrome@^0.0.318", - "npm:@types/js-cookie@^3.0.6", - "npm:@types/node@^22.15.3", - "npm:@types/react-dom@^19.1.3", - "npm:@types/react@^19.1.2", - "npm:@types/serviceworker@^0.0.133", - "npm:@types/w3c-web-serial@^1.0.8", - "npm:@types/web-bluetooth@^0.0.21", - "npm:@vitejs/plugin-react@^4.4.1", - "npm:autoprefixer@^10.4.21", - "npm:base64-js@^1.5.1", - "npm:class-variance-authority@~0.7.1", - "npm:clsx@^2.1.1", - "npm:cmdk@^1.1.1", - "npm:crypto-random-string@5", - "npm:gzipper@^8.2.1", - "npm:happy-dom@^17.4.6", - "npm:i18next-browser-languagedetector@^8.1.0", - "npm:i18next-http-backend@^3.0.2", - "npm:i18next@^25.2.0", - "npm:idb-keyval@^6.2.1", - "npm:immer@^10.1.1", - "npm:js-cookie@^3.0.5", - "npm:lucide-react@0.507", - "npm:maplibre-gl@5.4.0", - "npm:postcss@^8.5.3", - "npm:react-dom@^19.1.0", - "npm:react-error-boundary@6", - "npm:react-hook-form@^7.56.2", - "npm:react-i18next@^15.5.1", - "npm:react-map-gl@8.0.4", - "npm:react-qrcode-logo@3", - "npm:react@^19.1.0", - "npm:rfc4648@^1.5.4", - "npm:simple-git-hooks@^2.13.0", - "npm:tailwind-merge@^3.2.0", - "npm:tailwindcss-animate@^1.0.7", - "npm:tailwindcss@^4.1.5", - "npm:tar@^7.4.3", - "npm:testing-library@^0.0.2", - "npm:typescript@^5.8.3", - "npm:vite-plugin-pwa@1", - "npm:vite@7", - "npm:vitest@^3.2.4", - "npm:zod@^3.25.67", - "npm:zustand@5.0.5" - ] - } - } - } - } -} diff --git a/packages/web/package.json b/packages/web/package.json index 5377c169..4304fc39 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -4,20 +4,7 @@ "type": "module", "description": "Meshtastic web client", "license": "GPL-3.0-only", - "scripts": { - "build": "vite build", - "build:analyze": "BUNDLE_ANALYZE=true deno task build", - "lint": "deno lint src/", - "lint:fix": "deno lint --fix src/", - "format": "deno fmt src/", - "dev": "deno task dev:ui", - "dev:ui": "VITE_APP_VERSION=development deno run -A npm:vite dev", - "test": "deno run -A npm:vitest", - "check": "deno check", - "preview": "deno run -A npm:vite preview", - "generate:routes": "deno run -A npm:@tanstack/router-cli generate --outDir src/ routes --rootRoutePath /", - "package": "gzipper c -i html,js,css,png,ico,svg,json,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ ." - }, + "repository": { "type": "git", "url": "git+https://github.com/meshtastic/web.git" @@ -30,86 +17,86 @@ }, "homepage": "https://meshtastic.org", "dependencies": { - "@bufbuild/protobuf": "^2.2.5", + "@bufbuild/protobuf": "^2.6.0", "@hookform/resolvers": "^5.1.1", "@meshtastic/core": "npm:@jsr/meshtastic__core@2.6.4", "@meshtastic/js": "npm:@jsr/meshtastic__js@2.6.0-0", "@meshtastic/transport-http": "npm:@jsr/meshtastic__transport-http", "@meshtastic/transport-web-bluetooth": "npm:@jsr/meshtastic__transport-web-bluetooth", "@meshtastic/transport-web-serial": "npm:@jsr/meshtastic__transport-web-serial", - "@noble/curves": "^1.9.0", - "@radix-ui/react-accordion": "^1.2.8", - "@radix-ui/react-checkbox": "^1.2.3", - "@radix-ui/react-dialog": "^1.1.11", - "@radix-ui/react-dropdown-menu": "^2.1.12", - "@radix-ui/react-label": "^2.1.4", - "@radix-ui/react-menubar": "^1.1.12", - "@radix-ui/react-popover": "^1.1.11", - "@radix-ui/react-scroll-area": "^1.2.6", - "@radix-ui/react-select": "^2.2.2", - "@radix-ui/react-separator": "^1.1.4", - "@radix-ui/react-slider": "^1.3.2", - "@radix-ui/react-switch": "^1.2.2", - "@radix-ui/react-tabs": "^1.1.9", - "@radix-ui/react-toast": "^1.2.11", - "@radix-ui/react-toggle-group": "^1.1.9", - "@radix-ui/react-tooltip": "^1.2.4", - "@tanstack/react-router": "^1.120.15", - "@tanstack/react-router-devtools": "^1.120.16", - "@tanstack/router-cli": "^1.121.37", - "@tanstack/router-devtools": "^1.120.15", + "@noble/curves": "^1.9.2", + "@radix-ui/react-accordion": "^1.2.11", + "@radix-ui/react-checkbox": "^1.3.2", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-menubar": "^1.1.15", + "@radix-ui/react-popover": "^1.1.14", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.5", + "@radix-ui/react-switch": "^1.2.5", + "@radix-ui/react-tabs": "^1.1.12", + "@radix-ui/react-toast": "^1.2.14", + "@radix-ui/react-toggle-group": "^1.1.10", + "@radix-ui/react-tooltip": "^1.2.7", + "@tanstack/react-router": "^1.125.4", + "@tanstack/react-router-devtools": "^1.125.4", + "@tanstack/router-cli": "^1.125.4", + "@tanstack/router-devtools": "^1.125.4", "@turf/turf": "^7.2.0", - "@types/node": "^24.0.4", + "@types/node": "^24.0.10", "@types/web-bluetooth": "^0.0.21", "base64-js": "^1.5.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "crypto-random-string": "^5.0.0", - "i18next": "^25.2.0", - "i18next-browser-languagedetector": "^8.1.0", + "i18next": "^25.3.1", + "i18next-browser-languagedetector": "^8.2.0", "i18next-http-backend": "^3.0.2", - "idb-keyval": "^6.2.1", + "idb-keyval": "^6.2.2", "immer": "^10.1.1", "js-cookie": "^3.0.5", - "lucide-react": "^0.507.0", - "maplibre-gl": "5.4.0", + "lucide-react": "^0.525.0", + "maplibre-gl": "5.6.1", "react": "^19.1.0", "react-dom": "^19.1.0", "react-error-boundary": "^6.0.0", - "react-hook-form": "^7.56.2", - "react-i18next": "^15.5.1", + "react-hook-form": "^7.60.0", + "react-i18next": "^15.6.0", "react-map-gl": "8.0.4", "react-qrcode-logo": "^3.0.0", "rfc4648": "^1.5.4", - "zod": "^3.25.67", - "zustand": "5.0.5" + "zod": "^3.25.75", + "zustand": "5.0.6" }, "devDependencies": { - "@tailwindcss/postcss": "^4.1.5", - "@tanstack/router-plugin": "^1.120.15", + "@tailwindcss/postcss": "^4.1.11", + "@tanstack/router-plugin": "^1.125.5", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", - "@types/chrome": "^0.0.318", - "@types/react": "^19.1.2", - "@types/react-dom": "^19.1.3", - "@types/serviceworker": "^0.0.133", + "@types/chrome": "^0.0.329", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@types/serviceworker": "^0.0.140", "@types/js-cookie": "^3.0.6", "@types/w3c-web-serial": "^1.0.8", - "@vitejs/plugin-react": "^4.4.1", + "@vitejs/plugin-react": "^4.6.0", "autoprefixer": "^10.4.21", "gzipper": "^8.2.1", - "happy-dom": "^17.4.6", - "postcss": "^8.5.3", + "happy-dom": "^18.0.1", + "postcss": "^8.5.6", "simple-git-hooks": "^2.13.0", - "tailwind-merge": "^3.2.0", - "tailwindcss": "^4.1.5", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.11", "tailwindcss-animate": "^1.0.7", "tar": "^7.4.3", "testing-library": "^0.0.2", "typescript": "^5.8.3", - "vite": "^7.0.0", + "vite": "^7.0", "vitest": "^3.2.4" } } diff --git a/packages/web/postcss.config.cjs b/packages/web/postcss.config.cjs index e5640725..483f3785 100644 --- a/packages/web/postcss.config.cjs +++ b/packages/web/postcss.config.cjs @@ -1,5 +1,5 @@ module.exports = { plugins: { - '@tailwindcss/postcss': {}, + "@tailwindcss/postcss": {}, }, }; diff --git a/packages/web/public/Logo.svg b/packages/web/public/Logo.svg index e6863f6a..2d4a4fb6 100644 --- a/packages/web/public/Logo.svg +++ b/packages/web/public/Logo.svg @@ -1,16 +1,41 @@ - + - -Created with Fabric.js 4.6.0 - - - - - - - - - - - - \ No newline at end of file + + Created with Fabric.js 4.6.0 + + + + + + + + + + + diff --git a/packages/web/public/Logo_Black.svg b/packages/web/public/Logo_Black.svg index e0f9bb19..3568d300 100644 --- a/packages/web/public/Logo_Black.svg +++ b/packages/web/public/Logo_Black.svg @@ -1,12 +1,26 @@ - - - - - - - - + + + + + + + + diff --git a/packages/web/public/Logo_White.svg b/packages/web/public/Logo_White.svg index b1bcd575..7c5417ed 100644 --- a/packages/web/public/Logo_White.svg +++ b/packages/web/public/Logo_White.svg @@ -1,12 +1,28 @@ - - - - - - - - + + + + + + + + diff --git a/packages/web/public/chirpy.svg b/packages/web/public/chirpy.svg index d215662d..8769215f 100644 --- a/packages/web/public/chirpy.svg +++ b/packages/web/public/chirpy.svg @@ -1 +1,64 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/diy.svg b/packages/web/public/devices/diy.svg index 823467ed..2a364fd5 100644 --- a/packages/web/public/devices/diy.svg +++ b/packages/web/public/devices/diy.svg @@ -1 +1,2233 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-ht62-esp32c3-sx1262.svg b/packages/web/public/devices/heltec-ht62-esp32c3-sx1262.svg index c52534ef..ff244831 100644 --- a/packages/web/public/devices/heltec-ht62-esp32c3-sx1262.svg +++ b/packages/web/public/devices/heltec-ht62-esp32c3-sx1262.svg @@ -1 +1,2604 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-mesh-node-t114-case.svg b/packages/web/public/devices/heltec-mesh-node-t114-case.svg index b2abe639..895c6a39 100644 --- a/packages/web/public/devices/heltec-mesh-node-t114-case.svg +++ b/packages/web/public/devices/heltec-mesh-node-t114-case.svg @@ -1 +1,271 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-mesh-node-t114.svg b/packages/web/public/devices/heltec-mesh-node-t114.svg index 779a8f6a..d679a4b4 100644 --- a/packages/web/public/devices/heltec-mesh-node-t114.svg +++ b/packages/web/public/devices/heltec-mesh-node-t114.svg @@ -1 +1,398 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-v3-case.svg b/packages/web/public/devices/heltec-v3-case.svg index 1b1d3c55..2f772c5b 100644 --- a/packages/web/public/devices/heltec-v3-case.svg +++ b/packages/web/public/devices/heltec-v3-case.svg @@ -1 +1,74 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-v3.svg b/packages/web/public/devices/heltec-v3.svg index 13a5fa64..1c38cdcc 100644 --- a/packages/web/public/devices/heltec-v3.svg +++ b/packages/web/public/devices/heltec-v3.svg @@ -1 +1,1496 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-vision-master-e213.svg b/packages/web/public/devices/heltec-vision-master-e213.svg index 2c1cca09..1f128233 100644 --- a/packages/web/public/devices/heltec-vision-master-e213.svg +++ b/packages/web/public/devices/heltec-vision-master-e213.svg @@ -1 +1,149 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-vision-master-e290.svg b/packages/web/public/devices/heltec-vision-master-e290.svg index ca7d296a..dc64e35e 100644 --- a/packages/web/public/devices/heltec-vision-master-e290.svg +++ b/packages/web/public/devices/heltec-vision-master-e290.svg @@ -1 +1,221 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-vision-master-t190.svg b/packages/web/public/devices/heltec-vision-master-t190.svg index 55db34f9..0822ce3d 100644 --- a/packages/web/public/devices/heltec-vision-master-t190.svg +++ b/packages/web/public/devices/heltec-vision-master-t190.svg @@ -1 +1,213 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-wireless-paper-V1_0.svg b/packages/web/public/devices/heltec-wireless-paper-V1_0.svg index cb3f188d..def8143e 100644 --- a/packages/web/public/devices/heltec-wireless-paper-V1_0.svg +++ b/packages/web/public/devices/heltec-wireless-paper-V1_0.svg @@ -1 +1,510 @@ - + + + diff --git a/packages/web/public/devices/heltec-wireless-paper.svg b/packages/web/public/devices/heltec-wireless-paper.svg index cb3f188d..def8143e 100644 --- a/packages/web/public/devices/heltec-wireless-paper.svg +++ b/packages/web/public/devices/heltec-wireless-paper.svg @@ -1 +1,510 @@ - + + + diff --git a/packages/web/public/devices/heltec-wireless-tracker-V1-0.svg b/packages/web/public/devices/heltec-wireless-tracker-V1-0.svg index a5392595..e7676004 100644 --- a/packages/web/public/devices/heltec-wireless-tracker-V1-0.svg +++ b/packages/web/public/devices/heltec-wireless-tracker-V1-0.svg @@ -1 +1,2031 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-wireless-tracker.svg b/packages/web/public/devices/heltec-wireless-tracker.svg index a5392595..e7676004 100644 --- a/packages/web/public/devices/heltec-wireless-tracker.svg +++ b/packages/web/public/devices/heltec-wireless-tracker.svg @@ -1 +1,2031 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/heltec-wsl-v3.svg b/packages/web/public/devices/heltec-wsl-v3.svg index 1741223e..4dccfd5d 100644 --- a/packages/web/public/devices/heltec-wsl-v3.svg +++ b/packages/web/public/devices/heltec-wsl-v3.svg @@ -1 +1,1068 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/nano-g2-ultra.svg b/packages/web/public/devices/nano-g2-ultra.svg index 6dbe47af..e90c2359 100644 --- a/packages/web/public/devices/nano-g2-ultra.svg +++ b/packages/web/public/devices/nano-g2-ultra.svg @@ -1 +1,216 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/pico.svg b/packages/web/public/devices/pico.svg index 82ce6526..15d60bf5 100644 --- a/packages/web/public/devices/pico.svg +++ b/packages/web/public/devices/pico.svg @@ -1,2956 +1,3510 @@ + viewBox="303.37 653.64 1455.17 586.58" + version="1.1" + id="svg426" + sodipodi:docname="pico.svg" + inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" +> + id="namedview426" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="2.5279551" + inkscape:cx="522.16117" + inkscape:cy="248.22435" + inkscape:window-width="1920" + inkscape:window-height="1111" + inkscape:window-x="-9" + inkscape:window-y="-9" + inkscape:window-maximized="1" + inkscape:current-layer="Layer_3" + /> + id="defs1" + > + id="style1" + > + .cls-1 { + fill: #c08c2d; + } + .cls-2 { + fill: #38996b; + } + .cls-3 { + fill: #cbcccb; + } + .cls-4 { + fill: #574841; + } + .cls-5 { + fill: #eab96b; + } + .cls-6 { + fill: #2b2b2b; + } + .cls-12, .cls-13, .cls-7, .cls-8, .cls-9 { + fill: none; + } + .cls-7, .cls-8, .cls-9 { + stroke: #050606; + } + .cls-12, .cls-7, .cls-8, .cls-9 { + stroke-miterlimit: 10; + } + .cls-7 { + stroke-width: 2.04px; + } + .cls-8 { + stroke-width: 1.25px; + } + .cls-9 { + stroke-width: 3.13px; + } + .cls-10 { + fill: #caa987; + } + .cls-11 { + fill: #808181; + } + .cls-12 { + stroke: #bbbcbc; + stroke-width: 5.85px; + } + .cls-13 { + stroke: #fff; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.91px; + } + .cls-14 { + fill: #fff; + } + - - - - - - - - - - - - - - - + id="Layer_3" + data-name="Layer 3" + > + + + + + + + + + + + + + + + + class="cls-4" + cx="1505.08" + cy="785.89" + r="24.43" + id="circle14" + /> + class="cls-1" + cx="1505.08" + cy="785.89" + r="14.51" + id="circle15" + /> - + class="cls-5" + points="1687.78 1138.83 1697.36 1148.41 1697.36 1182.51 1701.94 1196.38 1701.94 1239.19 1715.82 1239.19 1715.82 1138.83 1698.4 1121.41" + id="polyline15" + /> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-5" + points="1687.78 756.11 1697.36 746.53 1697.36 712.43 1701.94 698.56 1701.94 655.75 1715.82 655.75 1715.82 756.11 1698.4 773.53" + id="polyline16" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + class="cls-7" + points="304.39 999.73 304.39 993.6 304.39 966.56 304.39 960.08" + id="polyline96" + /> + - - - - + class="cls-7" + points="304.39 890.12 304.39 896.6 304.39 923.63 304.39 929.76" + id="polyline97" + /> + + + + - - + class="cls-7" + cx="346.27" + cy="699.85" + r="15.16" + id="circle100" + /> + + - - + class="cls-7" + cx="416.65" + cy="699.85" + r="15.16" + id="circle102" + /> + + - - + class="cls-7" + cx="487.02" + cy="699.85" + r="15.16" + id="circle104" + /> + + - - + class="cls-7" + cx="838.89" + cy="699.85" + r="15.16" + id="circle106" + /> + + - - + class="cls-7" + cx="1190.59" + cy="699.85" + r="15.16" + id="circle108" + /> + + - - + class="cls-7" + cx="1542.64" + cy="699.85" + r="15.16" + id="circle110" + /> + + - - + class="cls-7" + cx="557.4" + cy="699.85" + r="15.16" + id="circle112" + /> + + - - + class="cls-7" + cx="627.77" + cy="699.85" + r="15.16" + id="circle114" + /> + + - - + class="cls-7" + cx="698.14" + cy="699.85" + r="15.16" + id="circle116" + /> + + - - + class="cls-7" + cx="768.52" + cy="699.85" + r="15.16" + id="circle118" + /> + + - - + class="cls-7" + cx="909.27" + cy="699.85" + r="15.16" + id="circle120" + /> + + - - + class="cls-7" + cx="979.64" + cy="699.85" + r="15.16" + id="circle122" + /> + + - - + class="cls-7" + cx="1050.02" + cy="699.85" + r="15.16" + id="circle124" + /> + + - - + class="cls-7" + cx="1120.39" + cy="699.85" + r="15.16" + id="circle126" + /> + + - - + class="cls-7" + cx="1261.14" + cy="699.85" + r="15.16" + id="circle128" + /> + + - - + class="cls-7" + cx="1331.51" + cy="699.85" + r="15.16" + id="circle130" + /> + + - - + class="cls-7" + cx="1401.89" + cy="699.85" + r="15.16" + id="circle132" + /> + + - - + class="cls-7" + cx="1472.26" + cy="699.85" + r="15.16" + id="circle134" + /> + + - - + class="cls-7" + cx="1613.01" + cy="699.85" + r="15.16" + id="circle136" + /> + + - - + class="cls-7" + cx="1683.39" + cy="699.85" + r="15.16" + id="circle138" + /> + + - - - + class="cls-7" + cx="346.27" + cy="1194.55" + r="15.16" + id="circle140" + /> + + + - - - + class="cls-7" + cx="349.03" + cy="1014.88" + r="15.16" + id="circle143" + /> + + + - - - + class="cls-7" + cx="349.03" + cy="944.92" + r="15.16" + id="circle146" + /> + + + - - + class="cls-7" + cx="349.03" + cy="874.96" + r="15.16" + id="circle149" + /> + + - - + class="cls-7" + cx="416.65" + cy="1194.55" + r="15.16" + id="circle151" + /> + + - - + class="cls-7" + cx="487.02" + cy="1194.55" + r="15.16" + id="circle153" + /> + + - - + class="cls-7" + cx="838.89" + cy="1194.55" + r="15.16" + id="circle155" + /> + + - - + class="cls-7" + cx="1190.59" + cy="1194.55" + r="15.16" + id="circle157" + /> + + - - + class="cls-7" + cx="1542.64" + cy="1194.55" + r="15.16" + id="circle159" + /> + + - - + class="cls-7" + cx="557.4" + cy="1194.55" + r="15.16" + id="circle161" + /> + + - - + class="cls-7" + cx="627.77" + cy="1194.55" + r="15.16" + id="circle163" + /> + + - - + class="cls-7" + cx="698.14" + cy="1194.55" + r="15.16" + id="circle165" + /> + + - - + class="cls-7" + cx="768.52" + cy="1194.55" + r="15.16" + id="circle167" + /> + + - - + class="cls-7" + cx="909.27" + cy="1194.55" + r="15.16" + id="circle169" + /> + + - - + class="cls-7" + cx="979.64" + cy="1194.55" + r="15.16" + id="circle171" + /> + + - - + class="cls-7" + cx="1050.02" + cy="1194.55" + r="15.16" + id="circle173" + /> + + - - + class="cls-7" + cx="1120.39" + cy="1194.55" + r="15.16" + id="circle175" + /> + + - - + class="cls-7" + cx="1261.14" + cy="1194.55" + r="15.16" + id="circle177" + /> + + - - + class="cls-7" + cx="1331.51" + cy="1194.55" + r="15.16" + id="circle179" + /> + + - - + class="cls-7" + cx="1401.89" + cy="1194.55" + r="15.16" + id="circle181" + /> + + - - + class="cls-7" + cx="1472.26" + cy="1194.55" + r="15.16" + id="circle183" + /> + + - - + class="cls-7" + cx="1613.01" + cy="1194.55" + r="15.16" + id="circle185" + /> + + - - - - - - - - - - + class="cls-7" + cx="1683.39" + cy="1194.55" + r="15.16" + id="circle187" + /> + + + + + + + + + + + class="cls-11" + points="1678.02 871.15 1678.02 893.72 1698.16 893.72 1708.06 898.41 1719.34 898.41 1719.34 867.05 1708.06 867.05 1698.16 871.45 1678.02 871.15" + id="polygon197" + /> + class="cls-11" + points="1678.02 1002.2 1678.02 1024.77 1698.16 1024.77 1708.06 1029.46 1719.34 1029.46 1719.34 998.1 1708.06 998.1 1698.16 1002.49 1678.02 1002.2" + id="polygon198" + /> + class="cls-7" + points="1678.02 871.15 1678.02 893.72 1698.16 893.72 1708.06 898.41 1719.34 898.41 1719.34 867.05 1708.06 867.05 1698.16 871.45 1678.02 871.15" + id="polygon199" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-7" + points="1678.02 1002.2 1678.02 1024.77 1698.16 1024.77 1708.06 1029.46 1719.34 1029.46 1719.34 998.1 1708.06 998.1 1698.16 1002.49 1678.02 1002.2" + id="polygon200" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class="cls-7" + cx="1505.08" + cy="785.89" + r="14.51" + id="circle239" + /> + class="cls-7" + cx="1505.08" + cy="785.89" + r="24.43" + id="circle240" + /> + class="cls-4" + cx="477.75" + cy="1108.22" + r="24.43" + id="circle241" + /> + class="cls-1" + cx="477.75" + cy="1108.22" + r="14.51" + id="circle242" + /> + class="cls-7" + cx="477.75" + cy="1108.22" + r="14.51" + id="circle243" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-7" + cx="477.75" + cy="1108.22" + r="24.43" + id="circle244" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-14" + points="401.66 858.14 401.66 884.45 386.52 871.29 401.66 858.14" + id="polygon361" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/web/public/devices/promicro.svg b/packages/web/public/devices/promicro.svg index 3dc26021..4ca7d076 100644 --- a/packages/web/public/devices/promicro.svg +++ b/packages/web/public/devices/promicro.svg @@ -1 +1,2619 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/rak-wismeshtap.svg b/packages/web/public/devices/rak-wismeshtap.svg index 34e77876..5801916e 100644 --- a/packages/web/public/devices/rak-wismeshtap.svg +++ b/packages/web/public/devices/rak-wismeshtap.svg @@ -1 +1,264 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/rak11310.svg b/packages/web/public/devices/rak11310.svg index 8f526a47..c5f90bab 100644 --- a/packages/web/public/devices/rak11310.svg +++ b/packages/web/public/devices/rak11310.svg @@ -1,2339 +1,2794 @@ + viewBox="603.65 579.13 682.64 792.16" + version="1.1" + id="svg292" + sodipodi:docname="rak11310.svg" + inkscape:version="1.4 (e7c3feb1, 2024-10-09)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" +> + id="namedview292" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="1.0967905" + inkscape:cx="411.65566" + inkscape:cy="490.97802" + inkscape:window-width="1472" + inkscape:window-height="890" + inkscape:window-x="0" + inkscape:window-y="38" + inkscape:window-maximized="1" + inkscape:current-layer="Layer_3" + /> + id="defs1" + > + id="style1" + > + .cls-1 { + fill: #3a3a3a; + } + .cls-19, .cls-2, .cls-5, .cls-8 { + fill: none; + } + .cls-2 { + stroke: #fff; + stroke-width: 1.17px; + } + .cls-2, .cls-5, .cls-8 { + stroke-miterlimit: 10; + } + .cls-3 { + fill: #c08c2d; + } + .cls-4 { + fill: #cbcccb; + } + .cls-5, .cls-8 { + stroke: #050606; + } + .cls-5 { + stroke-width: 2.04px; + } + .cls-6 { + fill: #267f4b; + } + .cls-7 { + fill: #9e9d9e; + } + .cls-8 { + stroke-width: 4.58px; + } + .cls-9 { + fill: #808181; + } + .cls-10 { + fill: #e8eae8; + } + .cls-11 { + fill: #fffef5; + } + .cls-12 { + fill: #f5e3c1; + } + .cls-13 { + fill: #fad908; + } + .cls-14 { + fill: #2b2b2b; + } + .cls-15 { + fill: #a4a5a3; + } + .cls-16 { + fill: #dad9d9; + } + .cls-17 { + fill: #dad7bf; + } + .cls-18 { + fill: #231f20; + } + - + id="Layer_3" + data-name="Layer 3" + > + + class="cls-2" + points="878.86 1369 878.86 1311.97 648.66 1311.97 648.66 1369" + id="polyline1" + /> - - - - - - - - - - - - + class="cls-2" + x1="703.99" + y1="1311.97" + x2="703.99" + y2="1369" + id="line1" + /> + + + + + + + + + + + + + class="cls-2" + points="1034.16 1369 1034.16 1311.97 1264.36 1311.97 1264.36 1369" + id="polyline10" + /> - - - - - - + class="cls-2" + x1="1209.03" + y1="1311.97" + x2="1209.03" + y2="1369" + id="line10" + /> + + + + + + - - - - - - - + class="cls-4" + points="802.2 840.16 816.4 832.91 816.4 846.55 802.2 840.16" + id="polygon18" + /> + + + + + + + - + class="cls-4" + cx="967.43" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse22" + /> + - + class="cls-4" + cx="978.97" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse23" + /> + - + class="cls-4" + cx="990.52" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse24" + /> + - + class="cls-4" + cx="1002.07" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse25" + /> + - + class="cls-4" + cx="1013.61" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse26" + /> + - + class="cls-4" + cx="1025.16" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse27" + /> + - + class="cls-4" + cx="1036.71" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse28" + /> + - + class="cls-4" + cx="1048.26" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse29" + /> + - + class="cls-4" + cx="1059.8" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse30" + /> + - + class="cls-4" + cx="1071.35" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse31" + /> + - - - - - - - - - - - + class="cls-4" + cx="1082.9" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse32" + /> + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-4" + cx="955.69" + cy="767.23" + rx="3.58" + ry="3.42" + id="ellipse42" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class="cls-2" + points="759.88 754.44 759.88 742.96 776.89 742.96" + id="polyline115" + /> - - - - + class="cls-2" + points="759.88 772.52 759.88 784 776.89 784" + id="polyline116" + /> + + + + + class="cls-2" + points="759.88 821.65 759.88 810.17 776.89 810.17" + id="polyline119" + /> + class="cls-2" + points="759.88 839.73 759.88 851.21 776.89 851.21" + id="polyline120" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-4" + points="802.2 774.49 816.4 767.24 816.4 780.88 802.2 774.49" + id="polygon120" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class="cls-4" + points="710.4 861.71 672.68 861.71 691.54 842.85 710.4 861.71" + id="polygon210" + /> + class="cls-4" + points="1252.96 725.68 1280.87 725.68 1266.92 744.54 1252.96 725.68" + id="polygon211" + /> + class="cls-2" + points="614.59 842.85 712.03 842.85 712.03 756.31" + id="polyline211" + /> + class="cls-2" + x1="614.59" + y1="753.87" + x2="679.75" + y2="753.87" + id="line211" + /> + class="cls-2" + x1="613.69" + y1="704.61" + x2="631.79" + y2="704.61" + id="line212" + /> + class="cls-2" + x1="688.67" + y1="612.38" + x2="688.67" + y2="628.07" + id="line213" + /> + class="cls-2" + x1="705.88" + y1="612.38" + x2="705.88" + y2="628.07" + id="line214" + /> + class="cls-2" + points="787.99 623.7 787.99 613.07 799.54 613.07" + id="polyline214" + /> + class="cls-2" + points="887.39 613.07 897.01 613.07 897.01 623.03" + id="polyline215" + /> - - - - - + class="cls-2" + x1="897.01" + y1="655.77" + x2="897.01" + y2="688.51" + id="line215" + /> + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-4" + points="1257.39 1001.27 1273.92 1001.27 1273.92 1177.74 1257.39 1177.74 1257.39 1119.44 1239.47 1089.51 1257.39 1061.63 1257.39 1001.27" + id="polygon218" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + class="cls-19" + points="846.59 1196.74 846.59 1192.01 846.59 1187.28 846.59 1182.54 841.85 1182.54 837.12 1182.54 837.12 1187.28 837.12 1192.01 837.12 1196.74 841.85 1196.74 846.59 1196.74" + id="polygon275" + /> + + - + class="cls-19" + points="851.32 1187.28 851.32 1192.01 856.05 1192.01 856.05 1187.28 856.05 1182.54 851.32 1182.54 851.32 1187.28" + id="polygon276" + /> + + class="cls-19" + points="808.72 1121.01 813.45 1121.01 818.18 1121.01 818.18 1116.28 818.18 1111.54 813.45 1111.54 808.72 1111.54 808.72 1116.28 808.72 1121.01" + id="polygon277" + /> - + class="cls-1" + points="803.98 1168.34 803.98 1163.61 799.25 1163.61 799.25 1168.34 799.25 1173.08 803.98 1173.08 803.98 1168.34" + id="polygon278" + /> + - + class="cls-1" + points="799.25 1144.68 799.25 1149.41 799.25 1154.14 803.98 1154.14 808.72 1154.14 808.72 1149.41 803.98 1149.41 803.98 1144.68 799.25 1144.68" + id="polygon279" + /> + + class="cls-1" + points="799.25 1130.48 803.98 1130.48 803.98 1135.21 803.98 1139.94 808.72 1139.94 808.72 1135.21 808.72 1130.48 808.72 1125.74 813.45 1125.74 818.18 1125.74 818.18 1130.48 818.18 1135.21 822.92 1135.21 822.92 1130.48 822.92 1125.74 822.92 1121.01 822.92 1116.28 822.92 1111.54 822.92 1106.81 822.92 1102.08 818.18 1102.08 818.18 1106.81 813.45 1106.81 808.72 1106.81 808.72 1111.54 813.45 1111.54 818.18 1111.54 818.18 1116.28 818.18 1121.01 813.45 1121.01 808.72 1121.01 808.72 1116.28 808.72 1111.54 803.98 1111.54 803.98 1116.28 803.98 1121.01 799.25 1121.01 799.25 1116.28 799.25 1111.54 794.52 1111.54 794.52 1116.28 794.52 1121.01 794.52 1125.74 799.25 1125.74 799.25 1130.48" + id="polygon280" + /> - + class="cls-1" + points="813.45 1102.08 813.45 1097.34 808.72 1097.34 808.72 1092.61 803.98 1092.61 803.98 1087.88 803.98 1083.14 808.72 1083.14 808.72 1087.88 813.45 1087.88 813.45 1083.14 818.18 1083.14 822.92 1083.14 822.92 1078.41 818.18 1078.41 813.45 1078.41 808.72 1078.41 803.98 1078.41 799.25 1078.41 794.52 1078.41 794.52 1083.14 799.25 1083.14 799.25 1087.88 799.25 1092.61 799.25 1097.34 799.25 1102.08 803.98 1102.08 803.98 1106.81 808.72 1106.81 808.72 1102.08 813.45 1102.08" + id="polygon281" + /> + - + class="cls-1" + points="851.32 1130.48 851.32 1135.21 846.59 1135.21 846.59 1139.94 851.32 1139.94 851.32 1144.68 856.05 1144.68 856.05 1139.94 860.79 1139.94 860.79 1135.21 856.05 1135.21 856.05 1130.48 851.32 1130.48" + id="polygon282" + /> + + class="cls-1" + points="837.12 1163.61 837.12 1158.88 841.85 1158.88 841.85 1154.14 841.85 1149.41 841.85 1144.68 837.12 1144.68 837.12 1139.94 837.12 1135.21 832.38 1135.21 832.38 1130.48 832.38 1125.74 827.65 1125.74 827.65 1130.48 827.65 1135.21 827.65 1139.94 832.38 1139.94 832.38 1144.68 832.38 1149.41 832.38 1154.14 827.65 1154.14 827.65 1158.88 827.65 1163.61 832.38 1163.61 837.12 1163.61" + id="polygon283" + /> + class="cls-1" + points="822.92 1149.41 822.92 1144.68 818.18 1144.68 818.18 1149.41 818.18 1154.14 822.92 1154.14 822.92 1149.41" + id="polygon284" + /> - - + class="cls-1" + points="851.32 1158.88 846.59 1158.88 846.59 1163.61 846.59 1168.34 846.59 1173.08 841.85 1173.08 841.85 1177.81 837.12 1177.81 837.12 1173.08 832.38 1173.08 832.38 1177.81 832.38 1182.54 832.38 1187.28 827.65 1187.28 827.65 1192.01 822.92 1192.01 818.18 1192.01 818.18 1187.28 818.18 1182.54 822.92 1182.54 822.92 1177.81 818.18 1177.81 818.18 1173.08 822.92 1173.08 822.92 1168.34 818.18 1168.34 818.18 1163.61 818.18 1158.88 818.18 1154.14 813.45 1154.14 813.45 1158.88 813.45 1163.61 813.45 1168.34 813.45 1173.08 808.72 1173.08 803.98 1173.08 803.98 1177.81 799.25 1177.81 799.25 1173.08 794.52 1173.08 794.52 1177.81 794.52 1182.54 799.25 1182.54 799.25 1187.28 803.98 1187.28 803.98 1182.54 808.72 1182.54 808.72 1187.28 808.72 1192.01 808.72 1196.74 808.72 1201.48 813.45 1201.48 818.18 1201.48 818.18 1196.74 822.92 1196.74 827.65 1196.74 832.38 1196.74 837.12 1196.74 837.12 1192.01 837.12 1187.28 837.12 1182.54 841.85 1182.54 846.59 1182.54 846.59 1187.28 846.59 1192.01 846.59 1196.74 841.85 1196.74 837.12 1196.74 837.12 1201.48 841.85 1201.48 846.59 1201.48 851.32 1201.48 856.05 1201.48 860.79 1201.48 860.79 1196.74 860.79 1192.01 860.79 1187.28 865.52 1187.28 865.52 1182.54 860.79 1182.54 856.05 1182.54 856.05 1187.28 856.05 1192.01 851.32 1192.01 851.32 1187.28 851.32 1182.54 856.05 1182.54 856.05 1177.81 856.05 1173.08 856.05 1168.34 856.05 1163.61 860.79 1163.61 860.79 1158.88 856.05 1158.88 851.32 1158.88" + id="polygon285" + /> + + + class="cls-1" + points="794.52 1196.74 794.52 1201.48 799.25 1201.48 799.25 1196.74 799.25 1192.01 794.52 1192.01 794.52 1196.74" + id="polygon286" + /> + class="cls-1" + points="794.52 1135.21 789.78 1135.21 785.05 1135.21 780.32 1135.21 780.32 1139.94 785.05 1139.94 789.78 1139.94 794.52 1139.94 794.52 1135.21" + id="polygon287" + /> - + class="cls-1" + points="775.58 1130.48 775.58 1125.74 770.85 1125.74 766.12 1125.74 766.12 1130.48 766.12 1135.21 770.85 1135.21 770.85 1139.94 770.85 1144.68 770.85 1149.41 775.58 1149.41 780.32 1149.41 780.32 1144.68 775.58 1144.68 775.58 1139.94 775.58 1135.21 780.32 1135.21 780.32 1130.48 775.58 1130.48" + id="polygon288" + /> + - + class="cls-1" + points="846.59 1087.88 841.85 1087.88 837.12 1087.88 837.12 1092.61 837.12 1097.34 837.12 1102.08 837.12 1106.81 841.85 1106.81 846.59 1106.81 851.32 1106.81 856.05 1106.81 856.05 1102.08 856.05 1097.34 856.05 1092.61 856.05 1087.88 851.32 1087.88 846.59 1087.88" + id="polygon289" + /> + - - + class="cls-1" + points="766.12 1106.81 770.85 1106.81 775.58 1106.81 775.58 1102.08 775.58 1097.34 775.58 1092.61 775.58 1087.88 770.85 1087.88 766.12 1087.88 761.38 1087.88 756.65 1087.88 756.65 1092.61 756.65 1097.34 756.65 1102.08 756.65 1106.81 761.38 1106.81 766.12 1106.81" + id="polygon290" + /> + + + class="cls-1" + points="761.38 1149.41 761.38 1144.68 761.38 1139.94 756.65 1139.94 751.92 1139.94 751.92 1135.21 751.92 1130.48 756.65 1130.48 756.65 1125.74 751.92 1125.74 747.18 1125.74 747.18 1130.48 747.18 1135.21 747.18 1139.94 747.18 1144.68 751.92 1144.68 756.65 1144.68 756.65 1149.41 751.92 1149.41 747.18 1149.41 747.18 1154.14 751.92 1154.14 756.65 1154.14 761.38 1154.14 766.12 1154.14 770.85 1154.14 770.85 1149.41 766.12 1149.41 761.38 1149.41" + id="polygon291" + /> - - - - - - - - - - - - - - - + class="cls-1" + points="766.12 1173.08 761.38 1173.08 756.65 1173.08 756.65 1177.81 756.65 1182.54 756.65 1187.28 756.65 1192.01 761.38 1192.01 766.12 1192.01 770.85 1192.01 775.58 1192.01 775.58 1187.28 775.58 1182.54 775.58 1177.81 775.58 1173.08 770.85 1173.08 766.12 1173.08" + id="polygon292" + /> + + + + + + + + + + + + + + + diff --git a/packages/web/public/devices/rak2560.svg b/packages/web/public/devices/rak2560.svg index b8514f01..137df86a 100644 --- a/packages/web/public/devices/rak2560.svg +++ b/packages/web/public/devices/rak2560.svg @@ -1 +1,379 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/rak4631.svg b/packages/web/public/devices/rak4631.svg index 6dc2957a..d107dd67 100644 --- a/packages/web/public/devices/rak4631.svg +++ b/packages/web/public/devices/rak4631.svg @@ -1,3514 +1,4244 @@ + viewBox="709.5 366.32 581.38 1184.53" + version="1.1" + id="svg535" + sodipodi:docname="rak4631.svg" + inkscape:version="1.4 (e7c3feb1, 2024-10-09)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" +> + id="namedview535" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:zoom="0.61688272" + inkscape:cx="-286.11598" + inkscape:cy="359.06339" + inkscape:window-width="1472" + inkscape:window-height="890" + inkscape:window-x="0" + inkscape:window-y="38" + inkscape:window-maximized="1" + inkscape:current-layer="svg535" + /> + id="defs1" + > + id="style1" + > + .cls-1 { + fill: #383838; + } + .cls-2 { + fill: #217e6a; + } + .cls-3 { + fill: #cbcccb; + } + .cls-4 { + fill: #fff; + } + .cls-11, + .cls-13, + .cls-15, + .cls-16, + .cls-17, + .cls-18, + .cls-19, + .cls-20, + .cls-22, + .cls-23, + .cls-24, + .cls-26, + .cls-5, + .cls-7 { + fill: none; + } + .cls-13, .cls-15, .cls-16, .cls-17, .cls-18, .cls-19, .cls-26, .cls-5 { + stroke: #050606; + } + .cls-13, + .cls-15, + .cls-16, + .cls-17, + .cls-18, + .cls-19, + .cls-23, + .cls-26, + .cls-5, + .cls-7 { + stroke-miterlimit: 10; + } + .cls-5, .cls-7 { + stroke-width: 1.67px; + } + .cls-6 { + fill: #eecc42; + } + .cls-7 { + stroke: #eecc42; + } + .cls-8 { + fill: #2c2d2d; + } + .cls-9 { + fill: #dfac52; + } + .cls-10 { + fill: #c6c6c5; + } + .cls-11, .cls-20, .cls-22, .cls-24 { + stroke: #fff; + stroke-linejoin: round; + } + .cls-11 { + stroke-width: 1.37px; + } + .cls-12 { + fill: #202121; + } + .cls-13, .cls-24 { + stroke-width: 3px; + } + .cls-14 { + fill: #b4b4b5; + } + .cls-15 { + stroke-width: 1.08px; + } + .cls-16 { + stroke-width: 1.24px; + } + .cls-17 { + stroke-width: 1.69px; + } + .cls-18 { + stroke-width: 0.97px; + } + .cls-19 { + stroke-width: 0.98px; + } + .cls-20 { + stroke-width: 1.33px; + } + .cls-21 { + fill: #b1b0b1; + } + .cls-22, .cls-24 { + stroke-linecap: round; + } + .cls-22 { + stroke-width: 1.07px; + } + .cls-23 { + stroke: #dfac52; + } + .cls-25 { + fill: #f2e3c2; + } + .cls-26 { + stroke-width: 2.25px; + } + .cls-27 { + fill: #226bb5; + } + .cls-28 { + fill: #231f20; + } + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="Layer_7" + data-name="Layer 7" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-11" + points="720.77 1050.99 1158.2 1050.99 1158.2 1244.34 717.25 1244.34" + id="polyline183" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class="cls-11" + points="717.25 1542.17 717.25 1253.98 919.27 1253.98" + id="polyline209" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-11" + points="948.48 1253.98 1205.03 1253.98 1205.03 1312.52" + id="polyline210" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + class="cls-20" + x1="1189.34" + y1="1097.81" + x2="1236.06" + y2="1097.81" + id="line299" + /> + + + + + + + + + + + + - - - - - - - - - - - - + class="cls-20" + x1="1236.06" + y1="1097.81" + x2="1282.78" + y2="1097.81" + id="line309" + /> + + + + + + + + + + + + + class="cls-20" + x1="1236.06" + y1="1291.7" + x2="1282.78" + y2="1291.7" + id="line319" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-20" + points="1015.23 1306.26 1015.23 1312.82 1021.39 1312.82 1021.39 1328.41 1015.23 1328.41 1015.23 1334.97 1021.39 1334.97 1021.39 1350.57 1015.23 1350.57 1015.23 1358.38 981.79 1358.38 981.79 1283.25 1015.23 1283.25 1015.23 1290.66 1021.39 1290.66 1021.39 1306.26 1015.23 1306.26" + id="polygon319" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + class="cls-22" + points="1086.93 552.72 1086.93 578.81 1041.69 578.81 1041.69 552.72" + id="polyline425" + /> + + + + + - - + class="cls-24" + x1="1148.56" + y1="550.67" + x2="1148.56" + y2="576.36" + id="line429" + /> + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-24" + x1="825.04" + y1="550.67" + x2="825.04" + y2="576.36" + id="line430" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class="cls-4" + points="1256.82 498.47 1284.59 498.47 1270.99 512.07 1256.82 498.47" + id="polygon456" + /> + class="cls-4" + points="1246.27 1034.9 1274.04 1034.9 1260.44 1048.5 1246.27 1034.9" + id="polygon457" + /> + class="cls-4" + points="1169.65 1078.76 1169.65 1050.99 1183.25 1064.59 1169.65 1078.76" + id="polygon458" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + class="cls-4" + points="1217.88 1282.29 1217.88 1254.52 1231.48 1268.12 1217.88 1282.29" + id="polygon459" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class="cls-1" + points="803.98,1144.68 799.25,1144.68 799.25,1149.41 799.25,1154.14 803.98,1154.14 808.72,1154.14 808.72,1149.41 803.98,1149.41 " + id="polygon279" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="808.72,1125.74 813.45,1125.74 818.18,1125.74 818.18,1130.48 818.18,1135.21 822.92,1135.21 822.92,1130.48 822.92,1125.74 822.92,1121.01 822.92,1116.28 822.92,1111.54 822.92,1106.81 822.92,1102.08 818.18,1102.08 818.18,1106.81 813.45,1106.81 808.72,1106.81 808.72,1111.54 813.45,1111.54 818.18,1111.54 818.18,1116.28 818.18,1121.01 813.45,1121.01 808.72,1121.01 808.72,1116.28 808.72,1111.54 803.98,1111.54 803.98,1116.28 803.98,1121.01 799.25,1121.01 799.25,1116.28 799.25,1111.54 794.52,1111.54 794.52,1116.28 794.52,1121.01 794.52,1125.74 799.25,1125.74 799.25,1130.48 803.98,1130.48 803.98,1135.21 803.98,1139.94 808.72,1139.94 808.72,1135.21 808.72,1130.48 " + id="polygon280" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="808.72,1083.14 808.72,1087.88 813.45,1087.88 813.45,1083.14 818.18,1083.14 822.92,1083.14 822.92,1078.41 818.18,1078.41 813.45,1078.41 808.72,1078.41 803.98,1078.41 799.25,1078.41 794.52,1078.41 794.52,1083.14 799.25,1083.14 799.25,1087.88 799.25,1092.61 799.25,1097.34 799.25,1102.08 803.98,1102.08 803.98,1106.81 808.72,1106.81 808.72,1102.08 813.45,1102.08 813.45,1097.34 808.72,1097.34 808.72,1092.61 803.98,1092.61 803.98,1087.88 803.98,1083.14 " + id="polygon281" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + x="944.7782" + y="850.44324" + width="4.73" + height="4.7399998" + id="rect281" + style="fill: #3a3a3a" + /> + class="cls-1" + points="856.05,1139.94 860.79,1139.94 860.79,1135.21 856.05,1135.21 856.05,1130.48 851.32,1130.48 851.32,1135.21 846.59,1135.21 846.59,1139.94 851.32,1139.94 851.32,1144.68 856.05,1144.68 " + id="polygon282" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="837.12,1139.94 837.12,1135.21 832.38,1135.21 832.38,1130.48 832.38,1125.74 827.65,1125.74 827.65,1130.48 827.65,1135.21 827.65,1139.94 832.38,1139.94 832.38,1144.68 832.38,1149.41 832.38,1154.14 827.65,1154.14 827.65,1158.88 827.65,1163.61 832.38,1163.61 837.12,1163.61 837.12,1158.88 841.85,1158.88 841.85,1154.14 841.85,1149.41 841.85,1144.68 837.12,1144.68 " + id="polygon283" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="822.92,1144.68 818.18,1144.68 818.18,1149.41 818.18,1154.14 822.92,1154.14 822.92,1149.41 " + id="polygon284" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="837.12,1177.81 837.12,1173.08 832.38,1173.08 832.38,1177.81 832.38,1182.54 832.38,1187.28 827.65,1187.28 827.65,1192.01 822.92,1192.01 818.18,1192.01 818.18,1187.28 818.18,1182.54 822.92,1182.54 822.92,1177.81 818.18,1177.81 818.18,1173.08 822.92,1173.08 822.92,1168.34 818.18,1168.34 818.18,1163.61 818.18,1158.88 818.18,1154.14 813.45,1154.14 813.45,1158.88 813.45,1163.61 813.45,1168.34 813.45,1173.08 808.72,1173.08 803.98,1173.08 803.98,1177.81 799.25,1177.81 799.25,1173.08 794.52,1173.08 794.52,1177.81 794.52,1182.54 799.25,1182.54 799.25,1187.28 803.98,1187.28 803.98,1182.54 808.72,1182.54 808.72,1187.28 808.72,1192.01 808.72,1196.74 808.72,1201.48 813.45,1201.48 818.18,1201.48 818.18,1196.74 822.92,1196.74 827.65,1196.74 832.38,1196.74 837.12,1196.74 837.12,1192.01 837.12,1187.28 837.12,1182.54 841.85,1182.54 846.59,1182.54 846.59,1187.28 846.59,1192.01 846.59,1196.74 841.85,1196.74 837.12,1196.74 837.12,1201.48 841.85,1201.48 846.59,1201.48 851.32,1201.48 856.05,1201.48 860.79,1201.48 860.79,1196.74 860.79,1192.01 860.79,1187.28 865.52,1187.28 865.52,1182.54 860.79,1182.54 856.05,1182.54 856.05,1187.28 856.05,1192.01 851.32,1192.01 851.32,1187.28 851.32,1182.54 856.05,1182.54 856.05,1177.81 856.05,1173.08 856.05,1168.34 856.05,1163.61 860.79,1163.61 860.79,1158.88 856.05,1158.88 851.32,1158.88 846.59,1158.88 846.59,1163.61 846.59,1168.34 846.59,1173.08 841.85,1173.08 841.85,1177.81 " + id="polygon285" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="770.85,1139.94 770.85,1144.68 770.85,1149.41 775.58,1149.41 780.32,1149.41 780.32,1144.68 775.58,1144.68 775.58,1139.94 775.58,1135.21 780.32,1135.21 780.32,1130.48 775.58,1130.48 775.58,1125.74 770.85,1125.74 766.12,1125.74 766.12,1130.48 766.12,1135.21 770.85,1135.21 " + id="polygon288" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="841.85,1106.81 846.59,1106.81 851.32,1106.81 856.05,1106.81 856.05,1102.08 856.05,1097.34 856.05,1092.61 856.05,1087.88 851.32,1087.88 846.59,1087.88 841.85,1087.88 837.12,1087.88 837.12,1092.61 837.12,1097.34 837.12,1102.08 837.12,1106.81 " + id="polygon289" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + d="m 944.77824,803.11328 h -33.14 v 37.87 h 37.87 v -37.87 z m 0,9.47 v 23.66 h -28.41 v -28.4 h 28.41 z" + id="path289" + style="fill: #3a3a3a" + /> + class="cls-1" + points="770.85,1087.88 766.12,1087.88 761.38,1087.88 756.65,1087.88 756.65,1092.61 756.65,1097.34 756.65,1102.08 756.65,1106.81 761.38,1106.81 766.12,1106.81 770.85,1106.81 775.58,1106.81 775.58,1102.08 775.58,1097.34 775.58,1092.61 775.58,1087.88 " + id="polygon290" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + d="m 840.63824,840.98328 h 28.4 v -37.87 h -37.87 v 37.87 z m -4.73,-9.47 v -23.67 h 28.4 v 28.4 h -28.4 z" + id="path290" + style="fill: #3a3a3a" + /> + class="cls-1" + x="864.30823" + y="874.11328" + width="4.73" + height="4.73" + id="rect290" + style="fill: #3a3a3a" + /> + class="cls-1" + points="756.65,1130.48 756.65,1125.74 751.92,1125.74 747.18,1125.74 747.18,1130.48 747.18,1135.21 747.18,1139.94 747.18,1144.68 751.92,1144.68 756.65,1144.68 756.65,1149.41 751.92,1149.41 747.18,1149.41 747.18,1154.14 751.92,1154.14 756.65,1154.14 761.38,1154.14 766.12,1154.14 770.85,1154.14 770.85,1149.41 766.12,1149.41 761.38,1149.41 761.38,1144.68 761.38,1139.94 756.65,1139.94 751.92,1139.94 751.92,1135.21 751.92,1130.48 " + id="polygon291" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + points="761.38,1192.01 766.12,1192.01 770.85,1192.01 775.58,1192.01 775.58,1187.28 775.58,1182.54 775.58,1177.81 775.58,1173.08 770.85,1173.08 766.12,1173.08 761.38,1173.08 756.65,1173.08 756.65,1177.81 756.65,1182.54 756.65,1187.28 756.65,1192.01 " + id="polygon292" + style="fill: #3a3a3a" + transform="translate(83.988238,-275.29672)" + /> + class="cls-1" + d="m 859.56824,888.31328 h -28.4 v 37.87 h 37.87 v -37.87 z m 4.74,9.47 v 23.66 h -28.4 v -28.4 h 28.4 z" + id="path292" + style="fill: #3a3a3a" + /> diff --git a/packages/web/public/devices/rak4631_case.svg b/packages/web/public/devices/rak4631_case.svg index a0b2bbb8..bcc88e29 100644 --- a/packages/web/public/devices/rak4631_case.svg +++ b/packages/web/public/devices/rak4631_case.svg @@ -1 +1,322 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/rpipicow.svg b/packages/web/public/devices/rpipicow.svg index cb4b1f68..49950a95 100644 --- a/packages/web/public/devices/rpipicow.svg +++ b/packages/web/public/devices/rpipicow.svg @@ -1 +1,2305 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/seeed-sensecap-indicator.svg b/packages/web/public/devices/seeed-sensecap-indicator.svg index f7bf9db0..2ec73bb4 100644 --- a/packages/web/public/devices/seeed-sensecap-indicator.svg +++ b/packages/web/public/devices/seeed-sensecap-indicator.svg @@ -1 +1,546 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/seeed-xiao-s3.svg b/packages/web/public/devices/seeed-xiao-s3.svg index 04e97fe0..a7f8046d 100644 --- a/packages/web/public/devices/seeed-xiao-s3.svg +++ b/packages/web/public/devices/seeed-xiao-s3.svg @@ -1 +1,1002 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/station-g2.svg b/packages/web/public/devices/station-g2.svg index 8d2e0aed..efc702d7 100644 --- a/packages/web/public/devices/station-g2.svg +++ b/packages/web/public/devices/station-g2.svg @@ -1 +1,512 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/t-deck.svg b/packages/web/public/devices/t-deck.svg index cdc53c5d..7b025e76 100644 --- a/packages/web/public/devices/t-deck.svg +++ b/packages/web/public/devices/t-deck.svg @@ -1 +1,697 @@ -QWERTYIUPOASDFGHKJLaltZXCVBMN \ No newline at end of file + + QWERTYIUPOASDFGHKJLaltZXCVBMN + diff --git a/packages/web/public/devices/t-echo.svg b/packages/web/public/devices/t-echo.svg index e178a50f..fc21b063 100644 --- a/packages/web/public/devices/t-echo.svg +++ b/packages/web/public/devices/t-echo.svg @@ -1 +1,195 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/t-watch-s3.svg b/packages/web/public/devices/t-watch-s3.svg index 19084c19..9bd241a2 100644 --- a/packages/web/public/devices/t-watch-s3.svg +++ b/packages/web/public/devices/t-watch-s3.svg @@ -1 +1,126 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tbeam-s3-core.svg b/packages/web/public/devices/tbeam-s3-core.svg index f42e6d2c..522c7c8b 100644 --- a/packages/web/public/devices/tbeam-s3-core.svg +++ b/packages/web/public/devices/tbeam-s3-core.svg @@ -1 +1,2514 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tbeam.svg b/packages/web/public/devices/tbeam.svg index cd0475c6..cc6797f8 100644 --- a/packages/web/public/devices/tbeam.svg +++ b/packages/web/public/devices/tbeam.svg @@ -1 +1,3447 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tlora-c6.svg b/packages/web/public/devices/tlora-c6.svg index 8b626638..bf906e1e 100644 --- a/packages/web/public/devices/tlora-c6.svg +++ b/packages/web/public/devices/tlora-c6.svg @@ -1 +1,493 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tlora-t3s3-epaper.svg b/packages/web/public/devices/tlora-t3s3-epaper.svg index 6f2e8452..8df65f47 100644 --- a/packages/web/public/devices/tlora-t3s3-epaper.svg +++ b/packages/web/public/devices/tlora-t3s3-epaper.svg @@ -1 +1,294 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tlora-t3s3-v1.svg b/packages/web/public/devices/tlora-t3s3-v1.svg index 1f8847d4..d5356e66 100644 --- a/packages/web/public/devices/tlora-t3s3-v1.svg +++ b/packages/web/public/devices/tlora-t3s3-v1.svg @@ -1 +1,1311 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tlora-v2-1-1_6.svg b/packages/web/public/devices/tlora-v2-1-1_6.svg index dbe36ef5..7a4c8b4f 100644 --- a/packages/web/public/devices/tlora-v2-1-1_6.svg +++ b/packages/web/public/devices/tlora-v2-1-1_6.svg @@ -1 +1,1237 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tlora-v2-1-1_8.svg b/packages/web/public/devices/tlora-v2-1-1_8.svg index dbe36ef5..7a4c8b4f 100644 --- a/packages/web/public/devices/tlora-v2-1-1_8.svg +++ b/packages/web/public/devices/tlora-v2-1-1_8.svg @@ -1 +1,1237 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/tracker-t1000-e.svg b/packages/web/public/devices/tracker-t1000-e.svg index 6f7a06c9..9ed42cf2 100644 --- a/packages/web/public/devices/tracker-t1000-e.svg +++ b/packages/web/public/devices/tracker-t1000-e.svg @@ -1 +1,441 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/devices/unknown.svg b/packages/web/public/devices/unknown.svg index 1d2cd87b..cbafa4ef 100644 --- a/packages/web/public/devices/unknown.svg +++ b/packages/web/public/devices/unknown.svg @@ -1,160 +1,242 @@ + class="svg-icon" + style="overflow: hidden; fill: currentColor" + viewBox="0 0 909.87988 546.85529" + version="1.1" + id="svg3" + xml:space="preserve" + width="909.87988" + height="546.85529" + sodipodi:docname="unknown.svg" + inkscape:version="1.4 (e7c3feb1, 2024-10-09)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" +> + + diff --git a/packages/web/public/devices/wio-tracker-wm1110.svg b/packages/web/public/devices/wio-tracker-wm1110.svg index 15ace5c5..2f5b6903 100644 --- a/packages/web/public/devices/wio-tracker-wm1110.svg +++ b/packages/web/public/devices/wio-tracker-wm1110.svg @@ -1 +1,3445 @@ -LoRaWI FILEDRESETGNSSBLE \ No newline at end of file + + LoRaWI FILEDRESETGNSSBLE + diff --git a/packages/web/public/devices/wm1110_dev_kit.svg b/packages/web/public/devices/wm1110_dev_kit.svg index 94aefe30..48da0230 100644 --- a/packages/web/public/devices/wm1110_dev_kit.svg +++ b/packages/web/public/devices/wm1110_dev_kit.svg @@ -1 +1,4908 @@ - \ No newline at end of file + + + diff --git a/packages/web/public/icon.svg b/packages/web/public/icon.svg index e6863f6a..2d4a4fb6 100644 --- a/packages/web/public/icon.svg +++ b/packages/web/public/icon.svg @@ -1,16 +1,41 @@ - + - -Created with Fabric.js 4.6.0 - - - - - - - - - - - - \ No newline at end of file + + Created with Fabric.js 4.6.0 + + + + + + + + + + + diff --git a/packages/web/public/logo.svg b/packages/web/public/logo.svg index e6863f6a..2d4a4fb6 100644 --- a/packages/web/public/logo.svg +++ b/packages/web/public/logo.svg @@ -1,16 +1,41 @@ - + - -Created with Fabric.js 4.6.0 - - - - - - - - - - - - \ No newline at end of file + + Created with Fabric.js 4.6.0 + + + + + + + + + + + diff --git a/packages/web/public/logo_black.svg b/packages/web/public/logo_black.svg index e0f9bb19..3568d300 100644 --- a/packages/web/public/logo_black.svg +++ b/packages/web/public/logo_black.svg @@ -1,12 +1,26 @@ - - - - - - - - + + + + + + + + diff --git a/packages/web/public/logo_white.svg b/packages/web/public/logo_white.svg index b1bcd575..7c5417ed 100644 --- a/packages/web/public/logo_white.svg +++ b/packages/web/public/logo_white.svg @@ -1,12 +1,28 @@ - - - - - - - - + + + + + + + + diff --git a/packages/web/src/index.tsx b/packages/web/src/index.tsx index fa0cecf5..d66afd57 100644 --- a/packages/web/src/index.tsx +++ b/packages/web/src/index.tsx @@ -16,7 +16,6 @@ declare module "@tanstack/react-router" { router: ReturnType; } } - const container = document.getElementById("root") as HTMLElement; const root = createRoot(container); diff --git a/packages/web/vite.config.ts b/packages/web/vite.config.ts index 16fc670c..7bef6349 100644 --- a/packages/web/vite.config.ts +++ b/packages/web/vite.config.ts @@ -27,6 +27,9 @@ export default defineConfig({ // }, // }), ], + optimizeDeps: { + include: ["react/jsx-runtime"], + }, define: { "import.meta.env.VITE_COMMIT_HASH": JSON.stringify(hash), },