diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx
index c914a510f..85924b514 100644
--- a/src/renderer/App.tsx
+++ b/src/renderer/App.tsx
@@ -261,6 +261,7 @@ import { usePathHistoryStore } from './stores/pathHistoryStore';
import { usePositionHistoryStore } from './stores/positionHistoryStore';
import { useReticulumIdentityStore } from './stores/reticulumIdentityStore';
import { useReticulumPeerStore } from './stores/reticulumPeerStore';
+import { useRncpTransferStore } from './stores/rncpTransferStore';
import { useRrcSessionStore } from './stores/rrcSessionStore';
// Tabs capability filtering lives in appTabMappings.ts (computeTabMappings).
@@ -1290,6 +1291,7 @@ function AppContent() {
void rrcSessionsByHub;
return useRrcSessionStore.getState().totalUnread();
}, [rrcUnreadByRoom, rrcUnreadByHub, rrcSessionsByHub]);
+ const remotePendingOffers = useRncpTransferStore((s) => s.pendingOffers.size);
const rrcMessageFlat = useMemo(() => {
const out: RrcChatMessage[] = [];
for (const list of rrcMessages.values()) out.push(...list);
@@ -2836,6 +2838,11 @@ function AppContent() {
chatUnread={chatUnread}
roomsUnread={roomsUnread}
rrcUnread={rrcUnread}
+ remotePendingOffers={
+ protocol === 'reticulum' && capabilities.hasReticulumRemotePanel
+ ? remotePendingOffers
+ : 0
+ }
collapsed={sidebarCollapsed}
onToggle={handleSidebarToggle}
/>
diff --git a/src/renderer/components/ChatPanel.tsx b/src/renderer/components/ChatPanel.tsx
index dd11500f4..41b3e99af 100644
--- a/src/renderer/components/ChatPanel.tsx
+++ b/src/renderer/components/ChatPanel.tsx
@@ -151,6 +151,7 @@ import { ChatPayloadText } from './ChatPayloadText';
import { HelpTooltip } from './HelpTooltip';
import { MessageStatusBadge } from './MessageStatusBadge';
import { ChatDmRncpControl } from './remote/ChatDmRncpControl';
+import { ChatDmRncpOfferBanner } from './remote/ChatDmRncpOfferBanner';
import { ReticulumAttachmentLine } from './ReticulumAttachmentLine';
import {
ReticulumDmPathActions,
@@ -3035,6 +3036,12 @@ function ChatPanel({
/>
{/* Compose emoji picker — Linux only; macOS/Windows use native showEmojiPanel() */}
+ {protocol === 'reticulum' &&
+ hasRncpTransfer &&
+ isDmMode &&
+ reticulumDmDestinationHash != null && (
+
+ )}
{
expect(screen.getByRole('tab', { name: 'RRC, 7 unread' })).toBeInTheDocument();
});
+ it('shows Remote pending-offer badge when remotePendingOffers > 0', () => {
+ const onChange = vi.fn();
+ render(
+ ,
+ );
+ expect(screen.getByText('2')).toBeInTheDocument();
+ expect(screen.getByRole('tab', { name: /2 pending inbound file offers/i })).toBeInTheDocument();
+ });
+
+ it('hides Remote badge when remotePendingOffers is 0', () => {
+ render(
+ ,
+ );
+ expect(screen.getByRole('tab', { name: 'Remote' })).toBeInTheDocument();
+ expect(screen.queryByText('0')).not.toBeInTheDocument();
+ });
+
it('hides RRC unread badge when rrcUnread is 0', () => {
const onChange = vi.fn();
render(
diff --git a/src/renderer/components/Sidebar.tsx b/src/renderer/components/Sidebar.tsx
index cf3164d36..f509aa838 100644
--- a/src/renderer/components/Sidebar.tsx
+++ b/src/renderer/components/Sidebar.tsx
@@ -19,6 +19,8 @@ interface SidebarProps {
roomsUnread?: number;
/** Unread RRC message count for RRC tab badge; 0 hides badge */
rrcUnread?: number;
+ /** Pending rncp inbound offers for Remote tab badge; 0 hides badge */
+ remotePendingOffers?: number;
/** Set of tab indices that are disabled (greyed out, non-clickable) */
disabledTabs?: Set;
collapsed: boolean;
@@ -33,6 +35,7 @@ export default function Sidebar({
chatUnread = 0,
roomsUnread = 0,
rrcUnread = 0,
+ remotePendingOffers = 0,
disabledTabs,
collapsed,
onToggle,
@@ -64,19 +67,26 @@ export default function Sidebar({
const showChatBadge = slotId === 'Chat' && chatUnread > 0;
const showRoomsBadge = slotId === 'Rooms' && roomsUnread > 0;
const showRrcBadge = slotId === 'RRC' && rrcUnread > 0;
+ const showRemoteBadge = slotId === 'Remote' && remotePendingOffers > 0;
const badgeCount = showChatBadge
? chatUnread
: showRoomsBadge
? roomsUnread
: showRrcBadge
? rrcUnread
- : 0;
- const showBadge = showChatBadge || showRoomsBadge || showRrcBadge;
+ : showRemoteBadge
+ ? remotePendingOffers
+ : 0;
+ const showBadge = showChatBadge || showRoomsBadge || showRrcBadge || showRemoteBadge;
const tabAriaLabel = showBadge
- ? t('aria.tabWithUnread', {
- label: displayLabel,
- count: badgeCount > 99 ? '99+' : badgeCount,
- })
+ ? showRemoteBadge
+ ? t('reticulumRemote.transfer.pendingOffersBadgeAria', {
+ count: badgeCount > 99 ? 99 : badgeCount,
+ })
+ : t('aria.tabWithUnread', {
+ label: displayLabel,
+ count: badgeCount > 99 ? '99+' : badgeCount,
+ })
: displayLabel;
return (
@@ -108,7 +118,11 @@ export default function Sidebar({
{showBadge && (
-
+
{badgeCount > 99 ? '99+' : badgeCount}
)}
diff --git a/src/renderer/components/remote/ChatDmRncpControl.test.tsx b/src/renderer/components/remote/ChatDmRncpControl.test.tsx
index d3f082316..13a4f6384 100644
--- a/src/renderer/components/remote/ChatDmRncpControl.test.tsx
+++ b/src/renderer/components/remote/ChatDmRncpControl.test.tsx
@@ -1,18 +1,67 @@
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import { beforeEach, describe, expect, it } from 'vitest';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { ensureRncpDestinationReachable } from '@/renderer/lib/ensureRncpDestinationReachable';
+import { sendRncpRequestEnable } from '@/renderer/lib/sendRncpRequestEnable';
import { useReticulumIdentityActivityStore } from '@/renderer/stores/reticulumIdentityActivityStore';
import { useReticulumRemoteAddressStore } from '@/renderer/stores/reticulumRemoteAddressStore';
import { useRncpTransferStore } from '@/renderer/stores/rncpTransferStore';
import { ChatDmRncpControl } from './ChatDmRncpControl';
+vi.mock('@/renderer/lib/ensureRncpDestinationReachable', () => ({
+ ensureRncpDestinationReachable: vi.fn(),
+}));
+
+vi.mock('@/renderer/lib/sendRncpRequestEnable', () => ({
+ sendRncpRequestEnable: vi.fn(),
+}));
+
+const addToast = vi.fn();
+
+vi.mock('@/renderer/components/Toast', () => ({
+ useToast: () => ({ addToast }),
+}));
+
const PEER_HASH = 'a'.repeat(32);
const PEER_IDENTITY = 'd'.repeat(32);
+const DEST_HASH = 'c'.repeat(32);
+
+function seedSavedRncpAddress(): void {
+ useReticulumRemoteAddressStore.setState({
+ addresses: new Map([
+ [
+ 'addr1',
+ {
+ id: 'addr1',
+ label: 'Alice',
+ service: 'rncp',
+ destination_hash: DEST_HASH,
+ lxmf_peer_hash: PEER_HASH,
+ created_at: 1,
+ updated_at: 1,
+ },
+ ],
+ ]),
+ hydrated: true,
+ hydrate: () => Promise.resolve(),
+ });
+}
describe('ChatDmRncpControl', () => {
beforeEach(() => {
+ addToast.mockReset();
+ vi.mocked(ensureRncpDestinationReachable).mockReset();
+ vi.mocked(ensureRncpDestinationReachable).mockResolvedValue({ status: 'reachable', hops: 1 });
+ vi.mocked(sendRncpRequestEnable).mockReset();
+ vi.mocked(sendRncpRequestEnable).mockResolvedValue({ ok: true });
+ vi.mocked(window.electronAPI.reticulum.rncp.showOpenFileDialog).mockReset();
+ vi.mocked(window.electronAPI.reticulum.rncp.showOpenFileDialog).mockResolvedValue({
+ canceled: true,
+ path: null,
+ });
+ vi.mocked(window.electronAPI.reticulum.rncp.send).mockReset();
useRncpTransferStore.getState().clearAll();
useReticulumRemoteAddressStore.setState({
addresses: new Map(),
@@ -175,4 +224,67 @@ describe('ChatDmRncpControl', () => {
expect(window.electronAPI.reticulum.rncp.accept).toHaveBeenCalledWith({ transfer_id: 't1' });
expect(useRncpTransferStore.getState().pendingOffers.size).toBe(0);
});
+
+ it('hard-blocks send when the receive dest is peerUnreachable', async () => {
+ seedSavedRncpAddress();
+ vi.mocked(ensureRncpDestinationReachable).mockResolvedValue({ status: 'peerUnreachable' });
+ const user = userEvent.setup();
+ render();
+ await user.click(screen.getByRole('button', { name: 'Send file to Alice via rncp' }));
+ await user.click(screen.getByRole('button', { name: 'Send file' }));
+
+ await waitFor(() => {
+ expect(ensureRncpDestinationReachable).toHaveBeenCalledWith({
+ destinationHash: DEST_HASH,
+ lxmfPeerHash: PEER_HASH,
+ });
+ });
+ expect(window.electronAPI.reticulum.rncp.showOpenFileDialog).not.toHaveBeenCalled();
+ expect(window.electronAPI.reticulum.rncp.send).not.toHaveBeenCalled();
+ expect(addToast).toHaveBeenCalledWith(
+ 'No path to that destination. The peer may be offline.',
+ 'error',
+ );
+ });
+
+ it('opens enable-request confirm when listenerLikelyOff and confirm sends the request', async () => {
+ seedSavedRncpAddress();
+ vi.mocked(ensureRncpDestinationReachable).mockResolvedValue({ status: 'listenerLikelyOff' });
+ const user = userEvent.setup();
+ render();
+ await user.click(screen.getByRole('button', { name: 'Send file to Alice via rncp' }));
+ await user.click(screen.getByRole('button', { name: 'Send file' }));
+
+ expect(await screen.findByText('File receiving may be off')).toBeInTheDocument();
+ expect(window.electronAPI.reticulum.rncp.showOpenFileDialog).not.toHaveBeenCalled();
+
+ await user.click(screen.getByRole('button', { name: 'Send enable request' }));
+ await waitFor(() => {
+ expect(sendRncpRequestEnable).toHaveBeenCalledWith(PEER_HASH);
+ });
+ });
+
+ it('proceeds to the file picker when the receive dest is reachable', async () => {
+ seedSavedRncpAddress();
+ vi.mocked(ensureRncpDestinationReachable).mockResolvedValue({ status: 'reachable', hops: 2 });
+ vi.mocked(window.electronAPI.reticulum.rncp.showOpenFileDialog).mockResolvedValue({
+ canceled: false,
+ path: '/tmp/hello.txt',
+ });
+ vi.mocked(window.electronAPI.reticulum.rncp.send).mockResolvedValue({
+ ok: true,
+ transfer_id: 'xfer-1',
+ });
+ const user = userEvent.setup();
+ render();
+ await user.click(screen.getByRole('button', { name: 'Send file to Alice via rncp' }));
+ await user.click(screen.getByRole('button', { name: 'Send file' }));
+
+ await waitFor(() => {
+ expect(window.electronAPI.reticulum.rncp.send).toHaveBeenCalledWith({
+ destination_hash: DEST_HASH,
+ path: '/tmp/hello.txt',
+ });
+ });
+ });
});
diff --git a/src/renderer/components/remote/ChatDmRncpControl.tsx b/src/renderer/components/remote/ChatDmRncpControl.tsx
index b74aa49d3..d5b73dc76 100644
--- a/src/renderer/components/remote/ChatDmRncpControl.tsx
+++ b/src/renderer/components/remote/ChatDmRncpControl.tsx
@@ -2,6 +2,7 @@ import { Upload } from 'lucide-react-motion';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { ConfirmModal } from '@/renderer/components/ConfirmModal';
import { RemotePathCapabilityChip } from '@/renderer/components/remote/RemotePathCapabilityChip';
import { useToast } from '@/renderer/components/Toast';
import { useRemotePathCapability } from '@/renderer/hooks/useRemotePathCapability';
@@ -9,6 +10,7 @@ import {
findLatestRncpReceiveDestShareInDmCandidates,
type RncpDmShareCandidate,
} from '@/renderer/lib/applyRncpReceiveDestShareFromChatHistory';
+import { ensureRncpDestinationReachable } from '@/renderer/lib/ensureRncpDestinationReachable';
import { errLikeToLogString } from '@/renderer/lib/errLikeToLogString';
import { parseReticulumDestinationInput } from '@/renderer/lib/reticulum/reticulumDestinationInput';
import { rncpOfferMatchesLxmfPeer } from '@/renderer/lib/rncpOfferPeerMatch';
@@ -84,6 +86,7 @@ export function ChatDmRncpControl({
const [destinationInput, setDestinationInput] = useState(savedAddress?.destination_hash ?? '');
const [rememberAddress, setRememberAddress] = useState(false);
const [sending, setSending] = useState(false);
+ const [enableRequestConfirmOpen, setEnableRequestConfirmOpen] = useState(false);
const [localTransferIds, setLocalTransferIds] = useState([]);
const chatShareAppliedRef = useRef(null);
const notifiedTerminalRef = useRef(new Set());
@@ -191,10 +194,22 @@ export function ChatDmRncpControl({
addToast(t('reticulumRemote.errors.invalidAddress'), 'error');
return;
}
- const picked = await window.electronAPI.reticulum.rncp.showOpenFileDialog();
- if (picked.canceled || !picked.path) return;
setSending(true);
try {
+ const reach = await ensureRncpDestinationReachable({
+ destinationHash: parsedHash,
+ lxmfPeerHash,
+ });
+ if (reach.status === 'peerUnreachable') {
+ addToast(t('reticulumRemote.transfer.peerUnreachable'), 'error');
+ return;
+ }
+ if (reach.status === 'listenerLikelyOff') {
+ setEnableRequestConfirmOpen(true);
+ return;
+ }
+ const picked = await window.electronAPI.reticulum.rncp.showOpenFileDialog();
+ if (picked.canceled || !picked.path) return;
const res = await window.electronAPI.reticulum.rncp.send({
destination_hash: parsedHash,
path: picked.path,
@@ -294,6 +309,11 @@ export function ChatDmRncpControl({
}
}, [addToast, dmShareCandidates, lxmfPeerHash, t]);
+ const handleConfirmEnableRequest = useCallback(() => {
+ setEnableRequestConfirmOpen(false);
+ void handleRequestEnable();
+ }, [handleRequestEnable]);
+
const handleUseFromChat = useCallback(() => {
const fromDm = findLatestRncpReceiveDestShareInDmCandidates(dmShareCandidates);
if (fromDm) {
@@ -501,10 +521,13 @@ export function ChatDmRncpControl({
type="button"
disabled={!parsedHash || sending}
aria-label={t('reticulumRemote.transfer.sendAria')}
+ aria-busy={sending}
onClick={() => void handleSend()}
className="w-full rounded bg-blue-700/80 px-3 py-1.5 text-xs font-medium text-white hover:bg-blue-600 disabled:opacity-50"
>
- {sending ? t('chatPanel.rncp.sending') : t('chatPanel.rncp.chooseAndSend')}
+ {sending
+ ? t('reticulumRemote.transfer.checkingReachability')
+ : t('chatPanel.rncp.chooseAndSend')}
{!savedAddress && (
void handleSend()}
className="rounded bg-blue-700/80 px-3 py-1.5 text-xs font-medium text-white hover:bg-blue-600 disabled:opacity-50"
>
- {t('reticulumRemote.transfer.send')}
+ {transferBusy
+ ? t('reticulumRemote.transfer.checkingReachability')
+ : t('reticulumRemote.transfer.send')}
) : (
@@ -556,12 +643,21 @@ export function RemoteTransferSection({
void handleFetch()}
className="rounded bg-blue-700/80 px-3 py-1.5 text-xs font-medium text-white hover:bg-blue-600 disabled:opacity-50"
>
- {t('reticulumRemote.transfer.fetch')}
+ {transferBusy
+ ? t('reticulumRemote.transfer.checkingReachability')
+ : t('reticulumRemote.transfer.fetch')}
)}
@@ -632,6 +728,17 @@ export function RemoteTransferSection({
))
)}
+ {enableRequestConfirmOpen && (
+ {
+ setEnableRequestConfirmOpen(false);
+ }}
+ />
+ )}
);
}
diff --git a/src/renderer/lib/ensureRncpDestinationReachable.test.ts b/src/renderer/lib/ensureRncpDestinationReachable.test.ts
new file mode 100644
index 000000000..4c41071b1
--- /dev/null
+++ b/src/renderer/lib/ensureRncpDestinationReachable.test.ts
@@ -0,0 +1,70 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+
+vi.mock('@/renderer/lib/reticulum/reticulumSidecarReads', () => ({
+ probeReticulumPeer: vi.fn(),
+}));
+
+import { probeReticulumPeer } from '@/renderer/lib/reticulum/reticulumSidecarReads';
+
+import { ensureRncpDestinationReachable } from './ensureRncpDestinationReachable';
+
+const DEST = 'a'.repeat(32);
+const LXMF = 'b'.repeat(32);
+
+describe('ensureRncpDestinationReachable', () => {
+ beforeEach(() => {
+ vi.mocked(probeReticulumPeer).mockReset();
+ });
+
+ it('returns reachable when the receive dest probe succeeds', async () => {
+ vi.mocked(probeReticulumPeer).mockResolvedValueOnce({ ok: true, hops: 2 });
+ await expect(
+ ensureRncpDestinationReachable({ destinationHash: DEST, lxmfPeerHash: LXMF }),
+ ).resolves.toEqual({ status: 'reachable', hops: 2 });
+ expect(probeReticulumPeer).toHaveBeenCalledTimes(1);
+ expect(probeReticulumPeer).toHaveBeenCalledWith(DEST);
+ });
+
+ it('returns listenerLikelyOff when dest fails but LXMF probe succeeds', async () => {
+ vi.mocked(probeReticulumPeer)
+ .mockResolvedValueOnce({ ok: false, error: 'timeout' })
+ .mockResolvedValueOnce({ ok: true, hops: 1 });
+ await expect(
+ ensureRncpDestinationReachable({ destinationHash: DEST, lxmfPeerHash: LXMF }),
+ ).resolves.toEqual({ status: 'listenerLikelyOff' });
+ expect(probeReticulumPeer).toHaveBeenCalledWith(DEST);
+ expect(probeReticulumPeer).toHaveBeenCalledWith(LXMF);
+ });
+
+ it('returns peerUnreachable when both probes fail', async () => {
+ vi.mocked(probeReticulumPeer)
+ .mockResolvedValueOnce({ ok: false })
+ .mockResolvedValueOnce({ ok: false });
+ await expect(
+ ensureRncpDestinationReachable({ destinationHash: DEST, lxmfPeerHash: LXMF }),
+ ).resolves.toEqual({ status: 'peerUnreachable' });
+ });
+
+ it('returns peerUnreachable when dest fails and no LXMF hash is provided', async () => {
+ vi.mocked(probeReticulumPeer).mockResolvedValueOnce({ ok: false });
+ await expect(ensureRncpDestinationReachable({ destinationHash: DEST })).resolves.toEqual({
+ status: 'peerUnreachable',
+ });
+ expect(probeReticulumPeer).toHaveBeenCalledTimes(1);
+ });
+
+ it('returns peerUnreachable when LXMF hash equals the receive dest', async () => {
+ vi.mocked(probeReticulumPeer).mockResolvedValueOnce({ ok: false });
+ await expect(
+ ensureRncpDestinationReachable({ destinationHash: DEST, lxmfPeerHash: DEST }),
+ ).resolves.toEqual({ status: 'peerUnreachable' });
+ expect(probeReticulumPeer).toHaveBeenCalledTimes(1);
+ });
+
+ it('returns peerUnreachable for invalid destination hashes without probing', async () => {
+ await expect(
+ ensureRncpDestinationReachable({ destinationHash: 'short', lxmfPeerHash: LXMF }),
+ ).resolves.toEqual({ status: 'peerUnreachable' });
+ expect(probeReticulumPeer).not.toHaveBeenCalled();
+ });
+});
diff --git a/src/renderer/lib/ensureRncpDestinationReachable.ts b/src/renderer/lib/ensureRncpDestinationReachable.ts
new file mode 100644
index 000000000..0803f987d
--- /dev/null
+++ b/src/renderer/lib/ensureRncpDestinationReachable.ts
@@ -0,0 +1,65 @@
+import { probeReticulumPeer } from '@/renderer/lib/reticulum/reticulumSidecarReads';
+import { isCanonicalReticulumDestinationHash } from '@/shared/reticulumDestinationHash';
+
+export type RncpDestinationReachability =
+ | { status: 'reachable'; hops?: number }
+ | { status: 'listenerLikelyOff' }
+ | { status: 'peerUnreachable' };
+
+export interface EnsureRncpDestinationReachableArgs {
+ /** rncp.receive (or fetch) destination hash — required path for the transfer. */
+ destinationHash: string;
+ /**
+ * Peer LXMF delivery hash when known (Chat DM always; Remote when saved).
+ * Used only when the receive dest probe fails, to distinguish offline vs
+ * listener-not-announcing.
+ */
+ lxmfPeerHash?: string | null;
+}
+
+/** True when `value` is already trimmed/lowercased 32-char hex (rncp/LXMF dest). */
+export function isRncpHexHash(value: string): boolean {
+ return isCanonicalReticulumDestinationHash(value);
+}
+
+/**
+ * Preflight before rncp send/fetch: require a live path to the transfer destination.
+ * When that fails but LXMF still probes ok, classify as listener-likely-off so the
+ * UI can prompt an enable-request instead of queuing a stuck 0% transfer.
+ */
+export async function ensureRncpDestinationReachable(
+ args: EnsureRncpDestinationReachableArgs,
+): Promise {
+ const destinationHash = args.destinationHash.trim().toLowerCase();
+ if (!isRncpHexHash(destinationHash)) {
+ return { status: 'peerUnreachable' };
+ }
+
+ let destProbe: Awaited>;
+ try {
+ destProbe = await probeReticulumPeer(destinationHash);
+ } catch {
+ // catch-no-log-ok probe failures classify as unreachable for the gate
+ return { status: 'peerUnreachable' };
+ }
+ if (destProbe.ok) {
+ return { status: 'reachable', hops: destProbe.hops };
+ }
+
+ const lxmf = args.lxmfPeerHash?.trim().toLowerCase() ?? '';
+ if (!isRncpHexHash(lxmf) || lxmf === destinationHash) {
+ return { status: 'peerUnreachable' };
+ }
+
+ let lxmfProbe: Awaited>;
+ try {
+ lxmfProbe = await probeReticulumPeer(lxmf);
+ } catch {
+ // catch-no-log-ok probe failures classify as unreachable for the gate
+ return { status: 'peerUnreachable' };
+ }
+ if (lxmfProbe.ok) {
+ return { status: 'listenerLikelyOff' };
+ }
+ return { status: 'peerUnreachable' };
+}
diff --git a/src/renderer/locales/cs/translation.json b/src/renderer/locales/cs/translation.json
index e7ea79534..b91b65396 100644
--- a/src/renderer/locales/cs/translation.json
+++ b/src/renderer/locales/cs/translation.json
@@ -600,7 +600,6 @@
"rememberAddress": "Zapamatovat si tuto adresu",
"rememberAddressAria": "Zapamatovat si tento cíl RNCP pro tohoto kolegu",
"chooseAndSend": "Vyberte soubor a odešlete...",
- "sending": "Odesílání...",
"sendStarted": "Odesílání {{file}}…",
"sendFailed": "Odeslání se nezdařilo: {{error}}",
"newOfferToast": "{{peer}} ti chce poslat soubor: {{file}}",
@@ -621,7 +620,9 @@
"forgetAddress": "Zapomenout uložený cíl",
"forgetAddressAria": "Odebrat uložený cíl příjmu rncp pro tohoto kolegu",
"forgotAddressToast": "Zapomněli jste uložený cíl rncp pro tohoto kolegu.",
- "filledFromChatToast": "Vyplněný cíl z chatu (neuloženo — zaškrtněte Nezapomeňte jej ponechat)."
+ "filledFromChatToast": "Vyplněný cíl z chatu (neuloženo — zaškrtněte Nezapomeňte jej ponechat).",
+ "offerBannerTitle": "Nabídky příchozích souborů",
+ "offerBannerTitleAria": "Nevyřízené nabídky příchozích souborů od tohoto partnera"
},
"shareLocation": "Sdílejte polohu",
"shareLocationLabel": "📍 Sdílená poloha",
@@ -4881,7 +4882,12 @@
"copyInstructions": "Kopírovat pokyny",
"instructionsCopied": "Pokyny zkopírovány.",
"receiveDestSharedToast": "Uložen rncp receive destination uživatele {{peer}} — nyní můžete odeslat soubor.",
- "receiveDestShareFailed": "Nelze uložit cíl příjmu rncp partnera."
+ "receiveDestShareFailed": "Nelze uložit cíl příjmu rncp partnera.",
+ "peerUnreachable": "Žádná cesta k tomuto cíli. Partner může být offline.",
+ "checkingReachability": "Kontrola dosažitelnosti…",
+ "listenerLikelyOffTitle": "Příjem souborů může být vypnutý",
+ "listenerLikelyOffBody": "Žádná cesta k cílovému umístění jejich souboru, ale hledají online chat. Požádejte je, aby povolili příjem souborů (Vzdálené → Nastavení → Nabídky příchozích souborů), a zkuste to znovu.",
+ "listenerLikelyOffConfirm": "Odeslat požadavek na povolení"
},
"enableRequest": {
"title": "Povolit příjem souborů?",
@@ -4898,9 +4904,9 @@
"enableFailed": "Nelze povolit příjem souboru: {{error}}",
"saveDirRequired": "Chcete-li povolit příjem, vyberte složku pro uložení.",
"identityUnknown": "Hash identity tohoto peera se zatím nepodařilo zjistit — příchozí dotazování je povoleno, ale peer nebyl přidán na seznam povolených. Zkuste to znovu, až dorazí cesta nebo oznámení.",
- "lxmfBody": "Povolte příjem souborů (rncp), pokud používáte mesh-client: Remote → Settings → Inbound file offers. Nebo spusťte rncp/rncp-rs v režimu poslechu.",
"lxmfShareBody": "Příjem souborů je povolen. Zde je můj rncp receive destination (mesh-client jej pro vás uloží).",
- "shareDestWarning": "Pokud povolíte, mesh-client odešle váš cíl příjmu rncp tomuto partnerovi, aby mohl automaticky vyplnit soubor."
+ "shareDestWarning": "Pokud povolíte, mesh-client odešle váš cíl příjmu rncp tomuto partnerovi, aby mohl automaticky vyplnit soubor.",
+ "lxmfBody": "Povolte příjem rncp (Vzdálené → Nastavení → Nabídky příchozích souborů) a pošlete mi svůj hash pro příjem rncp."
},
"saved": {
"labelPlaceholder": "Označení",
diff --git a/src/renderer/locales/de/translation.json b/src/renderer/locales/de/translation.json
index 605651f60..126dd4d34 100644
--- a/src/renderer/locales/de/translation.json
+++ b/src/renderer/locales/de/translation.json
@@ -601,7 +601,6 @@
"rememberAddress": "Diese Adresse merken",
"rememberAddressAria": "Merken Sie sich dieses rncp-Ziel für diesen Peer",
"chooseAndSend": "Datei auswählen & senden...",
- "sending": "Senden…",
"sendStarted": "{{file}} wird gesendet...",
"sendFailed": "Senden fehlgeschlagen: {{error}}",
"newOfferToast": "{{peer}} möchte dir eine Datei senden: {{file}}",
@@ -622,7 +621,9 @@
"forgetAddress": "Gespeichertes Ziel vergessen",
"forgetAddressAria": "Entfernen Sie das gespeicherte rncp-Empfangsziel für diesen Peer",
"forgotAddressToast": "Gespeichertes rncp-Ziel für diesen Peer vergessen.",
- "filledFromChatToast": "Gefülltes Ziel aus dem Chat (nicht gespeichert — aktivieren Sie Denken Sie daran, es zu behalten)."
+ "filledFromChatToast": "Gefülltes Ziel aus dem Chat (nicht gespeichert — aktivieren Sie Denken Sie daran, es zu behalten).",
+ "offerBannerTitle": "Eingehende Dateiangebote",
+ "offerBannerTitleAria": "Ausstehende eingehende Dateiangebote von diesem Peer"
},
"shareLocation": "Standort teilen",
"shareLocationLabel": "📍 Geteilter Standort",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Anweisungen kopieren",
"instructionsCopied": "Anweisungen kopiert.",
"receiveDestSharedToast": "rncp-Empfangsziel von {{peer}} gespeichert — Sie können jetzt eine Datei senden.",
- "receiveDestShareFailed": "Das RNCP-Empfangsziel des Peers konnte nicht gespeichert werden."
+ "receiveDestShareFailed": "Das RNCP-Empfangsziel des Peers konnte nicht gespeichert werden.",
+ "peerUnreachable": "Kein Weg zu diesem Ziel. Der Peer ist möglicherweise offline.",
+ "checkingReachability": "Erreichbarkeit prüfen…",
+ "listenerLikelyOffTitle": "Möglicherweise ist der Dateiempfang deaktiviert",
+ "listenerLikelyOffBody": "Kein Pfad zu ihrem Dateiempfangsziel, aber sie suchen online nach Chat. Bitten Sie sie, den Dateiempfang zu aktivieren (Remote → Einstellungen → Angebote für eingehende Dateien) und versuchen Sie es dann erneut.",
+ "listenerLikelyOffConfirm": "Aktivierungsanfrage senden"
},
"enableRequest": {
"title": "Dateiempfang aktivieren?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Dateiempfang konnte nicht aktiviert werden: {{error}}",
"saveDirRequired": "Wählen Sie einen Speicherordner aus, um den Empfang zu aktivieren.",
"identityUnknown": "Der Identitäts-Hash dieses Peers konnte noch nicht aufgelöst werden — eingehendes Nachfragen ist aktiviert, aber der Peer wurde nicht zur Erlaubnisliste hinzugefügt. Versuche es erneut, sobald ein Pfad oder ein Announce eintrifft.",
- "lxmfBody": "Bitte aktivieren Sie den Dateiempfang (rncp), wenn Sie mesh-client: Remote → Settings → Inbound file offers verwenden. Oder führen Sie rncp/rncp-rs im Listen-Modus aus.",
"lxmfShareBody": "Dateiempfang ist aktiviert. Hier ist mein rncp-Empfangsziel (mesh-client speichert es für Sie).",
- "shareDestWarning": "Wenn Sie diese Option aktivieren, sendet der Mesh-Client Ihr RNCP-Empfangsziel an diesen Peer, damit dieser den Dateiversand automatisch ausfüllen kann."
+ "shareDestWarning": "Wenn Sie diese Option aktivieren, sendet der Mesh-Client Ihr RNCP-Empfangsziel an diesen Peer, damit dieser den Dateiversand automatisch ausfüllen kann.",
+ "lxmfBody": "Bitte aktivieren Sie den rncp-Empfang (Remote → Einstellungen → Angebote für eingehende Dateien) und senden Sie mir Ihren rncp-Empfangs-Hash."
},
"saved": {
"labelPlaceholder": "Etikett",
diff --git a/src/renderer/locales/en/translation.json b/src/renderer/locales/en/translation.json
index 2ca8805f5..344af3718 100644
--- a/src/renderer/locales/en/translation.json
+++ b/src/renderer/locales/en/translation.json
@@ -515,12 +515,13 @@
"forgotAddressToast": "Forgot saved rncp destination for this peer.",
"filledFromChatToast": "Filled destination from chat (not saved — check Remember to keep it).",
"chooseAndSend": "Choose file & send…",
- "sending": "Sending…",
"sendStarted": "Sending {{file}}…",
"sendFailed": "Failed to send: {{error}}",
"newOfferToast": "{{peer}} wants to send you a file: {{file}}",
"requestEnable": "Request enable",
- "requestEnableAria": "Ask this peer to enable file receiving"
+ "requestEnableAria": "Ask this peer to enable file receiving",
+ "offerBannerTitle": "Incoming file offers",
+ "offerBannerTitleAria": "Pending inbound file offers from this peer"
},
"closeDm": "Close DM",
"resendMessage": "Resend message",
@@ -4740,6 +4741,11 @@
"requestEnableSent": "Asked the peer to enable file receiving.",
"requestEnableRateLimited": "You already sent a request recently. Try again later.",
"requestEnableFailed": "Could not send enable request: {{error}}",
+ "peerUnreachable": "No path to that destination. The peer may be offline.",
+ "checkingReachability": "Checking reachability…",
+ "listenerLikelyOffTitle": "File receiving may be off",
+ "listenerLikelyOffBody": "No path to their file receive destination, but they look online for chat. Ask them to enable file receiving (Remote → Settings → Inbound file offers), then try again.",
+ "listenerLikelyOffConfirm": "Send enable request",
"offerToast": "Incoming file offer: {{file}}",
"copyInstructionsAria": "Copy instructions for enabling file receive",
"copyInstructions": "Copy instructions",
@@ -4763,7 +4769,7 @@
"enableFailed": "Could not enable file receiving: {{error}}",
"saveDirRequired": "Choose a save folder to enable receiving.",
"identityUnknown": "Could not resolve this peer's identity hash yet — inbound Ask is enabled, but they were not added to the allow list. Try again after a path or announce arrives.",
- "lxmfBody": "Please enable file receiving (rncp) if you use mesh-client: Remote → Settings → Inbound file offers. Or run rncp/rncp-rs in listen mode.",
+ "lxmfBody": "Please enable rncp receive (Remote → Settings → Inbound file offers) and send me your rncp receive hash.",
"lxmfShareBody": "File receiving is enabled. Here is my rncp receive destination (mesh-client will save it for you)."
},
"saved": {
diff --git a/src/renderer/locales/es/translation.json b/src/renderer/locales/es/translation.json
index c031228c7..a7f2958f7 100644
--- a/src/renderer/locales/es/translation.json
+++ b/src/renderer/locales/es/translation.json
@@ -601,7 +601,6 @@
"rememberAddress": "Recordar esta dirección",
"rememberAddressAria": "Recordar este destino rncp para este compañero",
"chooseAndSend": "Elegir archivo y enviar...",
- "sending": "Enviando",
"sendStarted": "Enviando {{file}}…",
"sendFailed": "Error al enviar: {{error}}",
"newOfferToast": "{{peer}} quiere enviarte un archivo: {{file}}",
@@ -622,7 +621,9 @@
"forgetAddress": "Olvidar destino guardado",
"forgetAddressAria": "Eliminar el destino de recepción rncp guardado para este par",
"forgotAddressToast": "Se ha olvidado el destino rncp guardado para este par.",
- "filledFromChatToast": "Destino llenado desde el chat (no guardado — marque Recordar para conservarlo)."
+ "filledFromChatToast": "Destino llenado desde el chat (no guardado — marque Recordar para conservarlo).",
+ "offerBannerTitle": "Ofertas de archivos entrantes",
+ "offerBannerTitleAria": "Ofertas de archivos entrantes pendientes de este par"
},
"shareLocation": "Compartir ubicación",
"shareLocationLabel": "📍 Ubicación compartida",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Copiar instrucciones",
"instructionsCopied": "Instrucciones copiadas.",
"receiveDestSharedToast": "Se guardó el destino de recepción rncp de {{peer}}: ya puede enviar un archivo.",
- "receiveDestShareFailed": "No se pudo guardar el destino de recepción rncp del par."
+ "receiveDestShareFailed": "No se pudo guardar el destino de recepción rncp del par.",
+ "peerUnreachable": "No hay camino hacia ese destino. Es posible que el interlocutor esté desconectado.",
+ "checkingReachability": "Comprobando accesibilidad...",
+ "listenerLikelyOffTitle": "La recepción de archivos puede estar desactivada",
+ "listenerLikelyOffBody": "No hay ruta al destino de recepción de su archivo, pero buscan chat en línea. Pídales que habiliten la recepción de archivos (Remoto → Configuración → Ofertas de archivos entrantes) y luego vuelva a intentarlo.",
+ "listenerLikelyOffConfirm": "Enviar solicitud de habilitación"
},
"enableRequest": {
"title": "¿Habilitar la recepción de archivos?",
@@ -4896,9 +4902,9 @@
"enableFailed": "No se ha podido habilitar la recepción de archivos: {{error}}",
"saveDirRequired": "Elija una carpeta de guardado para habilitar la recepción.",
"identityUnknown": "Aún no se pudo resolver el hash de identidad de este par — el modo Preguntar está activado, pero no se añadió a la lista de permitidos. Inténtalo de nuevo cuando llegue una ruta o un anuncio.",
- "lxmfBody": "Habilite la recepción de archivos (rncp) si utiliza mesh-client: → Configuración remota Ofertas de archivos → entrantes. O ejecute rncp/rncp-rs en modo de escucha.",
"lxmfShareBody": "La recepción de archivos está habilitada. Aquí está mi destino de recepción rncp (mesh-client lo guardará para usted).",
- "shareDestWarning": "Si lo habilita, mesh-client enviará su destino de recepción rncp a este par para que pueda completar automáticamente el envío del archivo."
+ "shareDestWarning": "Si lo habilita, mesh-client enviará su destino de recepción rncp a este par para que pueda completar automáticamente el envío del archivo.",
+ "lxmfBody": "Habilite la recepción de rncp (Remoto → Configuración → Ofertas de archivos entrantes) y envíeme su hash de recepción de rncp."
},
"saved": {
"labelPlaceholder": "Designación",
diff --git a/src/renderer/locales/fr/translation.json b/src/renderer/locales/fr/translation.json
index 46fa11c33..5354a5413 100644
--- a/src/renderer/locales/fr/translation.json
+++ b/src/renderer/locales/fr/translation.json
@@ -601,7 +601,6 @@
"rememberAddress": "Mémoriser cette adresse",
"rememberAddressAria": "Mémoriser cette destination rncp pour cet homologue",
"chooseAndSend": "Choisissez le fichier et envoyez…",
- "sending": "Envoi en cours...",
"sendStarted": "Envoi {{file}}…",
"sendFailed": "Échec de l'envoi : {{error}}",
"newOfferToast": "{{peer}} souhaite vous envoyer un fichier : {{file}}",
@@ -622,7 +621,9 @@
"forgetAddress": "Oublier la destination enregistrée",
"forgetAddressAria": "Supprimer la destination de réception rncp enregistrée pour cet homologue",
"forgotAddressToast": "Destination rncp enregistrée oubliée pour cet homologue.",
- "filledFromChatToast": "Destination remplie à partir du chat (non enregistrée — cochez la case N'oubliez pas de la conserver)."
+ "filledFromChatToast": "Destination remplie à partir du chat (non enregistrée — cochez la case N'oubliez pas de la conserver).",
+ "offerBannerTitle": "Offres de fichiers entrants",
+ "offerBannerTitleAria": "Offres de fichiers entrants en attente de cet homologue"
},
"shareLocation": "Partager l'emplacement",
"shareLocationLabel": "📍 Emplacement partagé",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Copier les instructions",
"instructionsCopied": "Instructions copiées.",
"receiveDestSharedToast": "Destination de réception rncp de {{peer}} enregistrée — vous pouvez envoyer un fichier.",
- "receiveDestShareFailed": "Impossible d'enregistrer la destination de réception RNCP du homologue."
+ "receiveDestShareFailed": "Impossible d'enregistrer la destination de réception RNCP du homologue.",
+ "peerUnreachable": "Aucun chemin vers cette destination. L'homologue est peut-être hors ligne.",
+ "checkingReachability": "Vérification de l'accessibilité…",
+ "listenerLikelyOffTitle": "La réception de fichiers est peut-être désactivée",
+ "listenerLikelyOffBody": "Aucun chemin vers la destination de réception de leur fichier, mais ils recherchent en ligne pour discuter. Demandez-leur d'activer la réception de fichiers (À distance → Paramètres → Offres de fichiers entrants), puis réessayez.",
+ "listenerLikelyOffConfirm": "Envoyer une demande d'activation"
},
"enableRequest": {
"title": "Activer la réception de fichiers ?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Impossible d'activer la réception du fichier : {{error}}",
"saveDirRequired": "Choisissez un dossier de sauvegarde pour activer la réception.",
"identityUnknown": "Impossible de résoudre le hachage d'identité de ce pair pour le moment — le mode Demander est activé, mais il n'a pas été ajouté à la liste d'autorisation. Réessayez après l'arrivée d'un chemin ou d'une annonce.",
- "lxmfBody": "Veuillez activer la réception de fichiers (rncp) si vous utilisez mesh-client : Remote → Settings → Inbound file offers. Ou exécutez rncp/rncp-rs en mode écoute.",
"lxmfShareBody": "La réception de fichiers est activée. Voici ma destination de réception rncp (mesh-client l'enregistrera pour vous).",
- "shareDestWarning": "Si vous l'activez, mesh-client enverra votre destination de réception rncp à cet homologue afin qu'il puisse remplir automatiquement l'envoi de fichiers."
+ "shareDestWarning": "Si vous l'activez, mesh-client enverra votre destination de réception rncp à cet homologue afin qu'il puisse remplir automatiquement l'envoi de fichiers.",
+ "lxmfBody": "Veuillez activer la réception rncp (À distance → Paramètres → Offres de fichiers entrants) et envoyez-moi votre hachage de réception rncp."
},
"saved": {
"labelPlaceholder": "Dénomination",
diff --git a/src/renderer/locales/id/translation.json b/src/renderer/locales/id/translation.json
index 09d4b5b37..66640ee78 100644
--- a/src/renderer/locales/id/translation.json
+++ b/src/renderer/locales/id/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "Ingat alamat ini",
"rememberAddressAria": "Ingat tujuan rncp untuk rekan ini",
"chooseAndSend": "Pilih file & kirim…",
- "sending": "Mengirim…",
"sendStarted": "Mengirim {{file}}…",
"sendFailed": "Gagal mengirim: {{error}}",
"newOfferToast": "{{peer}} ingin mengirimi Anda file: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "Lupakan tujuan tersimpan",
"forgetAddressAria": "Hapus tujuan penerimaan rncp yang disimpan untuk rekan ini",
"forgotAddressToast": "Lupa menyimpan tujuan rncp untuk rekan ini.",
- "filledFromChatToast": "Tujuan yang diisi dari obrolan (tidak disimpan — centang Ingat untuk menyimpannya)."
+ "filledFromChatToast": "Tujuan yang diisi dari obrolan (tidak disimpan — centang Ingat untuk menyimpannya).",
+ "offerBannerTitle": "Penawaran file masuk",
+ "offerBannerTitleAria": "Penawaran file masuk yang tertunda dari rekan ini"
},
"shareLocation": "Bagikan lokasi",
"shareLocationLabel": "📍 Lokasi bersama",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Salin instruksi",
"instructionsCopied": "Instruksi disalin.",
"receiveDestSharedToast": "Destinasi penerimaan rncp {{peer}} disimpan — Anda dapat mengirim file sekarang.",
- "receiveDestShareFailed": "Tidak dapat menyimpan tujuan penerimaan rncp rekan."
+ "receiveDestShareFailed": "Tidak dapat menyimpan tujuan penerimaan rncp rekan.",
+ "peerUnreachable": "Tidak ada jalan menuju tujuan itu. Rekan tersebut mungkin sedang offline.",
+ "checkingReachability": "Memeriksa jangkauan…",
+ "listenerLikelyOffTitle": "Penerimaan file mungkin tidak aktif",
+ "listenerLikelyOffBody": "Tidak ada jalur ke tujuan penerimaan file mereka, tetapi mereka mencari obrolan online. Minta mereka untuk mengaktifkan penerimaan file (Jarak Jauh → Pengaturan → Penawaran file masuk), lalu coba lagi.",
+ "listenerLikelyOffConfirm": "Kirim permintaan pengaktifan"
},
"enableRequest": {
"title": "Aktifkan penerimaan file?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Tidak dapat mengaktifkan penerimaan file: {{error}}",
"saveDirRequired": "Pilih folder penyimpanan untuk mengaktifkan penerimaan.",
"identityUnknown": "Hash identitas peer ini belum dapat ditentukan — mode Tanya untuk file masuk sudah aktif, tetapi peer belum ditambahkan ke daftar izin. Coba lagi setelah jalur atau pengumuman diterima.",
- "lxmfBody": "Harap aktifkan penerimaan file (rncp) jika Anda menggunakan mesh-client: Remote → Settings → Inbound file offers. Atau jalankan rncp/rncp-rs dalam mode mendengarkan.",
"lxmfShareBody": "Penerimaan file diaktifkan. Ini tujuan penerimaan rncp saya (mesh-client akan menyimpannya untuk Anda).",
- "shareDestWarning": "Jika Anda mengaktifkannya, mesh-client akan mengirimkan tujuan penerimaan rncp Anda ke rekan ini sehingga mereka dapat mengisi otomatis pengiriman file."
+ "shareDestWarning": "Jika Anda mengaktifkannya, mesh-client akan mengirimkan tujuan penerimaan rncp Anda ke rekan ini sehingga mereka dapat mengisi otomatis pengiriman file.",
+ "lxmfBody": "Harap aktifkan penerimaan rncp (Jarak Jauh → Pengaturan → Penawaran file masuk) dan kirimkan saya hash penerimaan rncp Anda."
},
"saved": {
"labelPlaceholder": "Label",
diff --git a/src/renderer/locales/it/translation.json b/src/renderer/locales/it/translation.json
index 59322e33e..80cdecb37 100644
--- a/src/renderer/locales/it/translation.json
+++ b/src/renderer/locales/it/translation.json
@@ -601,7 +601,6 @@
"rememberAddress": "Ricorda questo indirizzo",
"rememberAddressAria": "Ricorda questa destinazione rncp per questo peer",
"chooseAndSend": "Scegli file e invia...",
- "sending": "Invio in corso…",
"sendStarted": "Invio di {{file}} in corso...",
"sendFailed": "Invio non riuscito: {{error}}",
"newOfferToast": "{{peer}} vuole inviarle un file: {{file}}",
@@ -622,7 +621,9 @@
"forgetAddress": "Dimentica la destinazione salvata",
"forgetAddressAria": "Rimuovi la destinazione di ricezione rncp salvata per questo peer",
"forgotAddressToast": "Ho dimenticato la destinazione rncp salvata per questo peer.",
- "filledFromChatToast": "Destinazione riempita dalla chat (non salvata — seleziona Ricordati di conservarla)."
+ "filledFromChatToast": "Destinazione riempita dalla chat (non salvata — seleziona Ricordati di conservarla).",
+ "offerBannerTitle": "Offerte di file in arrivo",
+ "offerBannerTitleAria": "Offerte di file in entrata in sospeso da questo peer"
},
"shareLocation": "Condividi posizione",
"shareLocationLabel": "📍Posizione condivisa",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Copia istruzioni",
"instructionsCopied": "Istruzioni copiate.",
"receiveDestSharedToast": "Destinazione di ricezione rncp di {{peer}} salvata: ora puoi inviare un file.",
- "receiveDestShareFailed": "Impossibile salvare la destinazione di ricezione rncp del peer."
+ "receiveDestShareFailed": "Impossibile salvare la destinazione di ricezione rncp del peer.",
+ "peerUnreachable": "Nessun percorso per quella destinazione. Il peer potrebbe essere offline.",
+ "checkingReachability": "Verifica della raggiungibilità…",
+ "listenerLikelyOffTitle": "La ricezione dei file potrebbe essere disattivata",
+ "listenerLikelyOffBody": "Nessun percorso verso la destinazione di ricezione del file, ma cercano online la chat. Chiedi loro di abilitare la ricezione dei file (Telecomando → Impostazioni → Offerte di file in entrata), quindi riprova.",
+ "listenerLikelyOffConfirm": "Invia richiesta di abilitazione"
},
"enableRequest": {
"title": "Abilitare la ricezione dei file?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Impossibile abilitare la ricezione dei file: {{error}}",
"saveDirRequired": "Scegli una cartella di salvataggio per abilitare la ricezione.",
"identityUnknown": "Non è stato ancora possibile risolvere l'hash di identità di questo peer — la modalità Chiedi è attiva, ma il peer non è stato aggiunto alla lista dei consentiti. Riprova dopo l'arrivo di un percorso o di un annuncio.",
- "lxmfBody": "Abilitare la ricezione dei file (rncp) se si utilizzano le offerte di file mesh-client: Remote → Settings → Inbound. Oppure esegui rncp/rncp-rs in modalità di ascolto.",
"lxmfShareBody": "La ricezione file è abilitata. Ecco la mia destinazione di ricezione rncp (mesh-client la salverà per te).",
- "shareDestWarning": "Se abiliti, mesh-client invierà la destinazione di ricezione rncp a questo peer in modo che possa compilare automaticamente l'invio del file."
+ "shareDestWarning": "Se abiliti, mesh-client invierà la destinazione di ricezione rncp a questo peer in modo che possa compilare automaticamente l'invio del file.",
+ "lxmfBody": "Abilita la ricezione rncp (Telecomando → Impostazioni → Offerte file in entrata) e inviami il tuo hash di ricezione rncp."
},
"saved": {
"labelPlaceholder": "Label",
diff --git a/src/renderer/locales/ja/translation.json b/src/renderer/locales/ja/translation.json
index 15ce4a5e5..7dbf02808 100644
--- a/src/renderer/locales/ja/translation.json
+++ b/src/renderer/locales/ja/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "この住所を記憶する",
"rememberAddressAria": "このピアのこのrncp宛先を覚えておいてください",
"chooseAndSend": "ファイルを選択して送信…",
- "sending": "送信中・・・",
"sendStarted": "{{file}}を送信中…",
"sendFailed": "次の送信に失敗しました: {{error}}",
"newOfferToast": "{{peer}}様からファイルのお送りをご希望です: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "保存された行き先を忘れる",
"forgetAddressAria": "このピアの保存されたrncp受信先を削除します",
"forgotAddressToast": "このピアの保存されたrncp宛先を忘れました。",
- "filledFromChatToast": "チャットから移動先を入力します(保存されていません。忘れずに保存するようにチェックしてください)。"
+ "filledFromChatToast": "チャットから移動先を入力します(保存されていません。忘れずに保存するようにチェックしてください)。",
+ "offerBannerTitle": "受信ファイルオファー",
+ "offerBannerTitleAria": "このピアからの保留中の受信ファイル オファー"
},
"shareLocation": "位置情報を共有する",
"shareLocationLabel": "📍 共有場所",
@@ -4879,7 +4880,12 @@
"copyInstructions": "手順をコピー",
"instructionsCopied": "手順をコピーしました。",
"receiveDestSharedToast": "{{peer}} の rncp 受信先を保存しました — ファイルを送信できます。",
- "receiveDestShareFailed": "ピアの rncp 受信先を保存できませんでした。"
+ "receiveDestShareFailed": "ピアの rncp 受信先を保存できませんでした。",
+ "peerUnreachable": "その目的地への道はありません。ピアがオフラインである可能性があります。",
+ "checkingReachability": "到達可能性を確認しています…",
+ "listenerLikelyOffTitle": "ファイル受信がオフになっている可能性があります",
+ "listenerLikelyOffBody": "ファイルの受信先へのパスはありませんが、オンラインでチャットを探しています。ファイル受信を有効にするよう依頼して (リモート → 設定 → 受信ファイル オファー)、もう一度試してください。",
+ "listenerLikelyOffConfirm": "有効化リクエストを送信する"
},
"enableRequest": {
"title": "ファイル受信を有効にしますか?",
@@ -4896,9 +4902,9 @@
"enableFailed": "ファイル受信を有効にできませんでした: {{error}}",
"saveDirRequired": "受信を有効にする保存フォルダを選択します。",
"identityUnknown": "このピアのIDハッシュをまだ解決できませんでした。受信時の確認は有効になりましたが、許可リストには追加されていません。パスまたはアナウンスの到着後にもう一度お試しください。",
- "lxmfBody": "mesh-clientをご利用の場合はファイル受信(rncp)を有効にしてください: Remote → Settings → Inbound file offers。またはリッスンモードで rncp/rncp-rs を実行してください。",
"lxmfShareBody": "ファイル受信が有効です。これが私の rncp 受信先です(mesh-client が保存します)。",
- "shareDestWarning": "有効にすると、mesh-client は rncp 受信宛先をこのピアに送信し、ファイル送信を自動入力できるようになります。"
+ "shareDestWarning": "有効にすると、mesh-client は rncp 受信宛先をこのピアに送信し、ファイル送信を自動入力できるようになります。",
+ "lxmfBody": "rncp 受信を有効にして (リモート → 設定 → インバウンド ファイル オファー)、rncp 受信ハッシュを送信してください。"
},
"saved": {
"labelPlaceholder": "ラベル",
diff --git a/src/renderer/locales/ko/translation.json b/src/renderer/locales/ko/translation.json
index 0d3c459c9..c16711198 100644
--- a/src/renderer/locales/ko/translation.json
+++ b/src/renderer/locales/ko/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "이 주소를 기억하세요",
"rememberAddressAria": "이 피어에 대한 이 rncp 대상을 기억하십시오.",
"chooseAndSend": "파일을 선택하고 보내세요...",
- "sending": "배상…",
"sendStarted": "{{file}} 보내는 중…",
"sendFailed": "전송 실패: {{error}}",
"newOfferToast": "{{peer}}이(가) 당신에게 파일을 보내려고 합니다: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "저장된 목적지 잊음",
"forgetAddressAria": "이 피어에 대해 저장된 rncp 수신 대상을 제거합니다",
"forgotAddressToast": "이 피어의 저장된 rncp 대상을 잊어버렸습니다.",
- "filledFromChatToast": "채팅에서 목적지를 채웠습니다 (저장되지 않음 — 잊지 말고 보관하세요)."
+ "filledFromChatToast": "채팅에서 목적지를 채웠습니다 (저장되지 않음 — 잊지 말고 보관하세요).",
+ "offerBannerTitle": "수신 파일 제안",
+ "offerBannerTitleAria": "이 피어로부터 보류 중인 인바운드 파일 제안"
},
"shareLocation": "위치 공유",
"shareLocationLabel": "📍 공유 위치",
@@ -4879,7 +4880,12 @@
"copyInstructions": "지침 복사",
"instructionsCopied": "지침이 복사되었습니다.",
"receiveDestSharedToast": "{{peer}}의 rncp 수신 대상을 저장했습니다 — 이제 파일을 보낼 수 있습니다.",
- "receiveDestShareFailed": "피어의 rncp 수신 대상을 저장할 수 없습니다."
+ "receiveDestShareFailed": "피어의 rncp 수신 대상을 저장할 수 없습니다.",
+ "peerUnreachable": "해당 목적지까지의 경로가 없습니다. 피어가 오프라인일 수 있습니다.",
+ "checkingReachability": "연결 가능성 확인 중…",
+ "listenerLikelyOffTitle": "파일 수신이 꺼져 있을 수 있습니다.",
+ "listenerLikelyOffBody": "파일 수신 대상에 대한 경로가 없지만 온라인에서 채팅을 찾습니다. 파일 수신 활성화(원격 → 설정 → 인바운드 파일 제공)를 요청한 후 다시 시도하세요.",
+ "listenerLikelyOffConfirm": "활성화 요청 보내기"
},
"enableRequest": {
"title": "파일 수신을 활성화하시겠습니까?",
@@ -4896,9 +4902,9 @@
"enableFailed": "파일 수신을 활성화할 수 없습니다: {{error}}",
"saveDirRequired": "수신을 활성화하려면 저장 폴더를 선택하세요.",
"identityUnknown": "이 피어의 신원 해시를 아직 확인할 수 없습니다 — 수신 확인은 활성화되었지만 허용 목록에는 추가되지 않았습니다. 경로나 알림이 도착한 후 다시 시도하세요.",
- "lxmfBody": "mesh-client를 사용하는 경우 파일 수신(rncp)을 활성화하십시오: 원격 → 설정 → 인바운드 파일 제공. 또는 청취 모드에서 rncp/rncp-rs를 실행하십시오.",
"lxmfShareBody": "파일 수신이 활성화되었습니다. 제 rncp 수신 대상입니다(mesh-client가 저장합니다).",
- "shareDestWarning": "활성화하면 mesh-client는 rncp 수신 대상을 이 피어에 보내 파일 보내기를 자동 채울 수 있습니다."
+ "shareDestWarning": "활성화하면 mesh-client는 rncp 수신 대상을 이 피어에 보내 파일 보내기를 자동 채울 수 있습니다.",
+ "lxmfBody": "rncp 수신을 활성화하고(원격 → 설정 → 인바운드 파일 제공) rncp 수신 해시를 보내주세요."
},
"saved": {
"labelPlaceholder": "상표",
diff --git a/src/renderer/locales/nl/translation.json b/src/renderer/locales/nl/translation.json
index d9be70013..18f7bc39e 100644
--- a/src/renderer/locales/nl/translation.json
+++ b/src/renderer/locales/nl/translation.json
@@ -600,7 +600,6 @@
"rememberAddress": "Dit adres onthouden",
"rememberAddressAria": "Onthoud deze rncp-bestemming voor deze collega",
"chooseAndSend": "Bestand kiezen en verzenden...",
- "sending": "Versturen...",
"sendStarted": "{{file}} verzenden…",
"sendFailed": "Verzenden mislukt: {{error}}",
"newOfferToast": "{{peer}} wil je een bestand sturen: {{file}}",
@@ -621,7 +620,9 @@
"forgetAddress": "Opgeslagen bestemming vergeten",
"forgetAddressAria": "Verwijder de opgeslagen rncp-ontvangstbestemming voor deze peer",
"forgotAddressToast": "Opgeslagen rncp-bestemming voor deze peer vergeten.",
- "filledFromChatToast": "Gevuld doel van chat (niet opgeslagen — vink Vergeet niet om het te bewaren)."
+ "filledFromChatToast": "Gevuld doel van chat (niet opgeslagen — vink Vergeet niet om het te bewaren).",
+ "offerBannerTitle": "Inkomende bestandsaanbiedingen",
+ "offerBannerTitleAria": "In afwachting van inkomende bestandsaanbiedingen van deze peer"
},
"shareLocation": "Deel locatie",
"shareLocationLabel": "📍 Gedeelde locatie",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Kopieer instructies",
"instructionsCopied": "Instructies gekopieerd.",
"receiveDestSharedToast": "rncp-ontvangstbestemming van {{peer}} opgeslagen — u kunt nu een bestand verzenden.",
- "receiveDestShareFailed": "Kan de rncp-ontvangstbestemming van de peer niet opslaan."
+ "receiveDestShareFailed": "Kan de rncp-ontvangstbestemming van de peer niet opslaan.",
+ "peerUnreachable": "Geen pad naar die bestemming. De peer is mogelijk offline.",
+ "checkingReachability": "Bereikbaarheid controleren...",
+ "listenerLikelyOffTitle": "Het ontvangen van bestanden is mogelijk uitgeschakeld",
+ "listenerLikelyOffBody": "Er is geen pad naar de bestemming van hun bestand, maar ze zoeken online naar chat. Vraag hen om het ontvangen van bestanden in te schakelen (Op afstand → Instellingen → Inkomende bestandsaanbiedingen) en probeer het vervolgens opnieuw.",
+ "listenerLikelyOffConfirm": "Inschakelverzoek verzenden"
},
"enableRequest": {
"title": "Bestandsontvangst inschakelen?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Kon het ontvangen van bestanden niet inschakelen: {{error}}",
"saveDirRequired": "Kies een opslagmap om ontvangst in te schakelen.",
"identityUnknown": "De identiteitshash van deze peer kon nog niet worden bepaald — inkomend vragen is ingeschakeld, maar de peer is niet aan de toestaanlijst toegevoegd. Probeer het opnieuw nadat een pad of aankondiging is ontvangen.",
- "lxmfBody": "Schakel bestandsontvangst (rncp) in als u mesh-client gebruikt: Extern → Instellingen → Inkomende bestandsaanbiedingen. Of voer rncp/rncp-rs uit in de luistermodus.",
"lxmfShareBody": "Bestandsontvangst is ingeschakeld. Dit is mijn rncp-ontvangstbestemming (mesh-client bewaart dit voor u).",
- "shareDestWarning": "Als u dit inschakelt, zal mesh-client uw rncp-ontvangstbestemming naar deze peer sturen, zodat zij het verzenden van bestanden automatisch kunnen aanvullen."
+ "shareDestWarning": "Als u dit inschakelt, zal mesh-client uw rncp-ontvangstbestemming naar deze peer sturen, zodat zij het verzenden van bestanden automatisch kunnen aanvullen.",
+ "lxmfBody": "Schakel rncp-ontvangst in (Op afstand → Instellingen → Inkomende bestandsaanbiedingen) en stuur mij uw rncp-ontvangst-hash."
},
"saved": {
"labelPlaceholder": "Label",
diff --git a/src/renderer/locales/pl/translation.json b/src/renderer/locales/pl/translation.json
index 48107aa3e..13d8ce3b3 100644
--- a/src/renderer/locales/pl/translation.json
+++ b/src/renderer/locales/pl/translation.json
@@ -601,7 +601,6 @@
"rememberAddress": "Zapamiętaj ten adres",
"rememberAddressAria": "Zapamiętaj to miejsce docelowe rncp dla tego partnera",
"chooseAndSend": "Wybierz plik i wyślij...",
- "sending": "Wysyłanie…",
"sendStarted": "Wysyłanie: {{file}}…",
"sendFailed": "Nie udało się wysłać: {{error}}",
"newOfferToast": "{{peer}} chce wysłać Ci plik: {{file}}",
@@ -624,7 +623,9 @@
"forgetAddress": "Zapomnij o zapisanym miejscu docelowym",
"forgetAddressAria": "Usuń zapisane miejsce docelowe odbioru rncp dla tego partnera",
"forgotAddressToast": "Nie pamiętasz zapisanego miejsca docelowego rncp dla tego partnera.",
- "filledFromChatToast": "Wypełnione miejsce docelowe z czatu (niezapisane — zaznacz Pamiętaj, aby je zachować)."
+ "filledFromChatToast": "Wypełnione miejsce docelowe z czatu (niezapisane — zaznacz Pamiętaj, aby je zachować).",
+ "offerBannerTitle": "Przychodzące oferty plików",
+ "offerBannerTitleAria": "Oczekujące oferty plików przychodzących od tego partnera"
},
"shareLocation": "Udostępnij lokalizację",
"shareLocationLabel": "📍 Udostępniona lokalizacja",
@@ -4883,7 +4884,12 @@
"copyInstructions": "Kopiuj instrukcje",
"instructionsCopied": "Skopiowano instrukcje.",
"receiveDestSharedToast": "Zapisano miejsce docelowe odbioru rncp użytkownika {{peer}} — możesz teraz wysłać plik.",
- "receiveDestShareFailed": "Nie można zapisać miejsca docelowego odbioru rncp urządzenia równorzędnego."
+ "receiveDestShareFailed": "Nie można zapisać miejsca docelowego odbioru rncp urządzenia równorzędnego.",
+ "peerUnreachable": "Żadnej drogi do tego celu. Partner może być offline.",
+ "checkingReachability": "Sprawdzam osiągalność…",
+ "listenerLikelyOffTitle": "Odbieranie plików może być wyłączone",
+ "listenerLikelyOffBody": "Brak ścieżki do miejsca docelowego odbioru pliku, ale szukają czatu w Internecie. Poproś o włączenie odbierania plików (Zdalne → Ustawienia → Oferty plików przychodzących), a następnie spróbuj ponownie.",
+ "listenerLikelyOffConfirm": "Wyślij prośbę o włączenie"
},
"enableRequest": {
"title": "Włączyć odbiór plików?",
@@ -4900,9 +4906,9 @@
"enableFailed": "Nie można włączyć odbierania plików: {{error}}",
"saveDirRequired": "Wybierz folder zapisu, aby włączyć odbiór.",
"identityUnknown": "Nie udało się jeszcze ustalić skrótu tożsamości tego peera — tryb pytania jest włączony, ale nie dodano go do listy dozwolonych. Spróbuj ponownie, gdy nadejdzie ścieżka lub ogłoszenie.",
- "lxmfBody": "Włącz odbieranie plików (rncp), jeśli używasz funkcji mesh-client: Remote → Settings → Inbound file offers. Lub uruchom rncp/rncp-rs w trybie słuchania.",
"lxmfShareBody": "Odbieranie plików jest włączone. Oto moje miejsce docelowe odbioru rncp (mesh-client zapisze je dla Ciebie).",
- "shareDestWarning": "Jeśli włączysz, mesh-client wyśle miejsce docelowe odbioru rncp do tego partnera, aby mógł automatycznie wypełnić wysyłanie pliku."
+ "shareDestWarning": "Jeśli włączysz, mesh-client wyśle miejsce docelowe odbioru rncp do tego partnera, aby mógł automatycznie wypełnić wysyłanie pliku.",
+ "lxmfBody": "Włącz odbieranie rncp (Zdalne → Ustawienia → Oferty plików przychodzących) i wyślij mi swój skrót odbierania rncp."
},
"saved": {
"labelPlaceholder": "Oznaczenie",
diff --git a/src/renderer/locales/pt-BR/translation.json b/src/renderer/locales/pt-BR/translation.json
index c1602c42a..ebb1870f7 100644
--- a/src/renderer/locales/pt-BR/translation.json
+++ b/src/renderer/locales/pt-BR/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "Lembrar este endereço",
"rememberAddressAria": "Lembre-se deste destino rncp para este par",
"chooseAndSend": "Escolher arquivo e enviar...",
- "sending": "Enviando…",
"sendStarted": "Enviando {{file}}…",
"sendFailed": "Falha ao enviar: {{error}}",
"newOfferToast": "{{peer}} deseja enviar-lhe um arquivo: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "Esqueça o destino guardado",
"forgetAddressAria": "Remover o destino de recebimento rncp salvo para este par",
"forgotAddressToast": "Esqueci o destino rncp salvo para este par.",
- "filledFromChatToast": "Destino preenchido do chat (não salvo — marque Lembre-se de mantê-lo)."
+ "filledFromChatToast": "Destino preenchido do chat (não salvo — marque Lembre-se de mantê-lo).",
+ "offerBannerTitle": "Ofertas de arquivos recebidos",
+ "offerBannerTitleAria": "Ofertas de arquivos de entrada pendentes deste peer"
},
"shareLocation": "Compartilhar localização",
"shareLocationLabel": "📍 Localização compartilhada",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Copiar instruções",
"instructionsCopied": "Instruções copiadas.",
"receiveDestSharedToast": "Destino de recebimento rncp de {{peer}} salvo — você já pode enviar um arquivo.",
- "receiveDestShareFailed": "Não foi possível salvar o destino de recebimento do rncp do par."
+ "receiveDestShareFailed": "Não foi possível salvar o destino de recebimento do rncp do par.",
+ "peerUnreachable": "Nenhum caminho para esse destino. O par pode estar offline.",
+ "checkingReachability": "Verificando acessibilidade…",
+ "listenerLikelyOffTitle": "O recebimento de arquivos pode estar desativado",
+ "listenerLikelyOffBody": "Nenhum caminho para o destino de recebimento do arquivo, mas eles procuram bate-papo on-line. Peça-lhes para ativar o recebimento de arquivos (Remoto → Configurações → Ofertas de arquivos de entrada) e tente novamente.",
+ "listenerLikelyOffConfirm": "Enviar solicitação de ativação"
},
"enableRequest": {
"title": "Habilitar recebimento de arquivos?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Não foi possível ativar o recebimento de arquivos: {{error}}",
"saveDirRequired": "Escolha uma pasta de salvamento para ativar o recebimento.",
"identityUnknown": "Ainda não foi possível resolver o hash de identidade deste par — o modo Perguntar foi ativado, mas ele não foi adicionado à lista de permitidos. Tente novamente quando um caminho ou anúncio chegar.",
- "lxmfBody": "Ative o recebimento de arquivos (rncp) se você usar mesh-client: Remote → Settings → Inbound file offers. Ou execute rncp/rncp-rs no modo de escuta.",
"lxmfShareBody": "O recebimento de arquivos está ativado. Aqui está meu destino de recebimento rncp (mesh-client salvará para você).",
- "shareDestWarning": "Se você ativar, o mesh-client enviará seu destino de recebimento rncp para esse par para que eles possam preencher automaticamente o envio do arquivo."
+ "shareDestWarning": "Se você ativar, o mesh-client enviará seu destino de recebimento rncp para esse par para que eles possam preencher automaticamente o envio do arquivo.",
+ "lxmfBody": "Ative o recebimento do rncp (Remoto → Configurações → Ofertas de arquivos de entrada) e envie-me seu hash de recebimento do rncp."
},
"saved": {
"labelPlaceholder": "Etiqueta",
diff --git a/src/renderer/locales/ru/translation.json b/src/renderer/locales/ru/translation.json
index 2ea33da06..f9578c1aa 100644
--- a/src/renderer/locales/ru/translation.json
+++ b/src/renderer/locales/ru/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "Запомнить этот адрес",
"rememberAddressAria": "Запомнить это назначение rncp для этого однорангового узла",
"chooseAndSend": "Выберите файл и отправьте...",
- "sending": "отправка…",
"sendStarted": "Отправка {{file}}…",
"sendFailed": "Не удалось отправить: {{error}}",
"newOfferToast": "{{peer}} хочет отправить вам файл: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "Забыть сохраненный пункт назначения",
"forgetAddressAria": "Удалить сохраненный пункт назначения получения rncp для этого узла",
"forgotAddressToast": "Забыт сохраненный пункт назначения rncp для этого однорангового узла.",
- "filledFromChatToast": "Заполненный пункт назначения из чата (не сохранен — отметьте Не забудьте сохранить его)."
+ "filledFromChatToast": "Заполненный пункт назначения из чата (не сохранен — отметьте Не забудьте сохранить его).",
+ "offerBannerTitle": "Входящие файловые предложения",
+ "offerBannerTitleAria": "Ожидающие предложения входящих файлов от этого узла"
},
"shareLocation": "Поделиться местоположением",
"shareLocationLabel": "📍 Общая локация",
@@ -4881,7 +4882,12 @@
"copyInstructions": "Копировать инструкции",
"instructionsCopied": "Инструкции скопированы.",
"receiveDestSharedToast": "Сохранено rncp-назначение приёма {{peer}} — можно отправить файл.",
- "receiveDestShareFailed": "Не удалось сохранить пункт назначения приема rncp узла."
+ "receiveDestShareFailed": "Не удалось сохранить пункт назначения приема rncp узла.",
+ "peerUnreachable": "Нет пути к этому месту назначения. Узел может быть отключен от сети.",
+ "checkingReachability": "Проверка доступности…",
+ "listenerLikelyOffTitle": "Прием файлов может быть отключен",
+ "listenerLikelyOffBody": "Нет пути к месту назначения их файла, но они ищут чат в Интернете. Попросите их включить получение файлов (Удаленное управление → Настройки → Предложения входящих файлов), а затем повторите попытку.",
+ "listenerLikelyOffConfirm": "Отправить запрос на включение"
},
"enableRequest": {
"title": "Включить получение файлов?",
@@ -4898,9 +4904,9 @@
"enableFailed": "Не удалось включить получение файлов: {{error}}",
"saveDirRequired": "Выберите папку сохранения, чтобы включить получение.",
"identityUnknown": "Пока не удалось определить хеш личности этого пира — режим «Спрашивать» включён, но пир не добавлен в список разрешённых. Повторите попытку после получения пути или анонса.",
- "lxmfBody": "Включите получение файлов (rncp), если вы используете mesh-client: Remote → Settings → Inbound file offers. Или запустите rncp/rncp-rs в режиме прослушивания.",
"lxmfShareBody": "Приём файлов включён. Вот моё rncp-назначение приёма (mesh-client сохранит его для вас).",
- "shareDestWarning": "Если вы включите этот параметр, mesh-client отправит пункт назначения получения rncp этому узлу, чтобы он мог автоматически заполнить файл для отправки."
+ "shareDestWarning": "Если вы включите этот параметр, mesh-client отправит пункт назначения получения rncp этому узлу, чтобы он мог автоматически заполнить файл для отправки.",
+ "lxmfBody": "Пожалуйста, включите получение rncp (Удаленное управление → Настройки → Предложения входящих файлов) и пришлите мне хэш получения rncp."
},
"saved": {
"labelPlaceholder": "Ярлык",
diff --git a/src/renderer/locales/tr/translation.json b/src/renderer/locales/tr/translation.json
index 1f47cdb0a..89b6e06e1 100644
--- a/src/renderer/locales/tr/translation.json
+++ b/src/renderer/locales/tr/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "Bu adresi hatırla",
"rememberAddressAria": "Bu eş için bu rncp hedefini hatırla",
"chooseAndSend": "Dosya seç ve gönder…",
- "sending": "Gönderiliyor…",
"sendStarted": "{{file}} gönderiliyor…",
"sendFailed": "Gönderilemedi: {{error}}",
"newOfferToast": "{{peer}} size bir dosya göndermek istiyor: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "Kaydedilen hedefi unut",
"forgetAddressAria": "Bu eş için kaydedilen rncp alma hedefini kaldır",
"forgotAddressToast": "Bu eş için kaydedilen rncp hedefini unuttum.",
- "filledFromChatToast": "Sohbetten dolu hedef (kaydedilmedi — saklamayı unutmayın seçeneğini işaretleyin)."
+ "filledFromChatToast": "Sohbetten dolu hedef (kaydedilmedi — saklamayı unutmayın seçeneğini işaretleyin).",
+ "offerBannerTitle": "Gelen dosya teklifleri",
+ "offerBannerTitleAria": "Bu eşten gelen dosya teklifleri bekleniyor"
},
"shareLocation": "Konumu paylaş",
"shareLocationLabel": "📍 Paylaşılan konum",
@@ -4879,7 +4880,12 @@
"copyInstructions": "Talimatları kopyala",
"instructionsCopied": "Talimatlar kopyalandı.",
"receiveDestSharedToast": "{{peer}} için rncp alma hedefi kaydedildi — şimdi dosya gönderebilirsiniz.",
- "receiveDestShareFailed": "Eşin rncp alma hedefi kaydedilemedi."
+ "receiveDestShareFailed": "Eşin rncp alma hedefi kaydedilemedi.",
+ "peerUnreachable": "O hedefe giden yol yok. Eş çevrimdışı olabilir.",
+ "checkingReachability": "Erişilebilirlik kontrol ediliyor…",
+ "listenerLikelyOffTitle": "Dosya alma kapalı olabilir",
+ "listenerLikelyOffBody": "Dosyalarının varış noktasına giden yolu yok, ancak sohbet için çevrimiçi görünüyorlar. Dosya almayı etkinleştirmelerini isteyin (Uzak → Ayarlar → Gelen dosya teklifleri), ardından tekrar deneyin.",
+ "listenerLikelyOffConfirm": "Etkinleştirme isteği gönder"
},
"enableRequest": {
"title": "Dosya alımı etkinleştirilsin mi?",
@@ -4896,9 +4902,9 @@
"enableFailed": "Dosya alımı etkinleştirilemedi: {{error}}",
"saveDirRequired": "Alımı etkinleştirmek için bir kaydetme klasörü seçin.",
"identityUnknown": "Bu eşin kimlik karması henüz çözülemedi — gelen Sor modu etkinleştirildi ancak eş izin listesine eklenmedi. Bir yol veya duyuru geldikten sonra tekrar deneyin.",
- "lxmfBody": "Mesh-client kullanıyorsanız lütfen dosya almayı (rncp) etkinleştirin: Uzak → Ayarlar → Gelen dosya teklifleri. Veya rncp/rncp-rs'yi dinleme modunda çalıştırın.",
"lxmfShareBody": "Dosya alma etkinleştirildi. İşte rncp alma hedefim (mesh-client sizin için kaydedecek).",
- "shareDestWarning": "Etkinleştirirseniz mesh-client, dosya gönderimini otomatik olarak doldurabilmeleri için rncp alma hedefinizi bu eşe gönderecektir."
+ "shareDestWarning": "Etkinleştirirseniz mesh-client, dosya gönderimini otomatik olarak doldurabilmeleri için rncp alma hedefinizi bu eşe gönderecektir.",
+ "lxmfBody": "Lütfen rncp alımını etkinleştirin (Uzak → Ayarlar → Gelen dosya teklifleri) ve bana rncp alma karmanızı gönderin."
},
"saved": {
"labelPlaceholder": "Etiket",
diff --git a/src/renderer/locales/uk/translation.json b/src/renderer/locales/uk/translation.json
index 6af8b829d..55c736d56 100644
--- a/src/renderer/locales/uk/translation.json
+++ b/src/renderer/locales/uk/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "Запам'ятати цю адресу",
"rememberAddressAria": "Запам'ятати цю адресу rncp для цього співрозмовника",
"chooseAndSend": "Виберіть файл і надішліть…",
- "sending": "Заклад,",
"sendStarted": "Надсилання {{file}}…",
"sendFailed": "Не вдалося надіслати: {{error}}",
"newOfferToast": "{{peer}} хоче надіслати вам файл: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "Забути збережений пункт призначення",
"forgetAddressAria": "Видалити збережене місце призначення отримання rncp для цього вузла",
"forgotAddressToast": "Забув збережений пункт призначення rncp для цього вузла.",
- "filledFromChatToast": "Заповнене місце призначення з чату (не збережено — перевірте, щоб зберегти його)."
+ "filledFromChatToast": "Заповнене місце призначення з чату (не збережено — перевірте, щоб зберегти його).",
+ "offerBannerTitle": "Пропозиції щодо вхідних файлів",
+ "offerBannerTitleAria": "Пропозиції щодо вхідних файлів, що очікують на розгляд, від цього партнера"
},
"shareLocation": "Поділіться місцем розташування",
"shareLocationLabel": "📍 Спільне розташування",
@@ -4881,7 +4882,12 @@
"copyInstructions": "Копіювати інструкції",
"instructionsCopied": "Інструкції скопійовано.",
"receiveDestSharedToast": "Збережено rncp destination прийому {{peer}} — тепер можна надіслати файл.",
- "receiveDestShareFailed": "Не вдалося зберегти адресат отримання rncp однорангового пристрою."
+ "receiveDestShareFailed": "Не вдалося зберегти адресат отримання rncp однорангового пристрою.",
+ "peerUnreachable": "Немає шляху до цього пункту призначення. Одноранговий пристрій може бути офлайн.",
+ "checkingReachability": "Перевірка доступності…",
+ "listenerLikelyOffTitle": "Отримання файлів може бути вимкнено",
+ "listenerLikelyOffBody": "Немає шляху до пункту призначення файлу, але вони шукають онлайн-чат. Попросіть їх увімкнути отримання файлів (Віддалене → Налаштування → Пропозиції вхідних файлів), а потім повторіть спробу.",
+ "listenerLikelyOffConfirm": "Надіслати запит на ввімкнення"
},
"enableRequest": {
"title": "Увімкнути прийом файлів?",
@@ -4898,9 +4904,9 @@
"enableFailed": "Не вдалося увімкнути отримання файлу: {{error}}",
"saveDirRequired": "Виберіть папку збереження, щоб увімкнути отримання.",
"identityUnknown": "Поки не вдалося визначити хеш особи цього піра — режим «Запитувати» увімкнено, але піра не додано до списку дозволених. Спробуйте ще раз після надходження шляху або анонсу.",
- "lxmfBody": "Увімкніть отримання файлів (rncp), якщо ви використовуєте mesh-client: Remote → Settings → Inbound file offers. Або запустіть rncp/rncp-rs у режимі прослуховування.",
"lxmfShareBody": "Прийом файлів увімкнено. Ось мій rncp destination прийому (mesh-client збереже його для вас).",
- "shareDestWarning": "Якщо ввімкнути, mesh-client надсилатиме ваш адресат отримання rncp цьому вузлу, щоб він міг автоматично заповнювати надсилання файлів."
+ "shareDestWarning": "Якщо ввімкнути, mesh-client надсилатиме ваш адресат отримання rncp цьому вузлу, щоб він міг автоматично заповнювати надсилання файлів.",
+ "lxmfBody": "Будь ласка, увімкніть отримання rncp (Віддалений → Налаштування → Пропозиції вхідних файлів) і надішліть мені свій хеш отримання rncp."
},
"saved": {
"labelPlaceholder": "Мітка",
diff --git a/src/renderer/locales/zh/translation.json b/src/renderer/locales/zh/translation.json
index 4d17209a2..4dc9bfee8 100644
--- a/src/renderer/locales/zh/translation.json
+++ b/src/renderer/locales/zh/translation.json
@@ -602,7 +602,6 @@
"rememberAddress": "记住此地址",
"rememberAddressAria": "记住此节点的此rncp目标",
"chooseAndSend": "选择文件并发送…",
- "sending": "发送中…",
"sendStarted": "正在发送{{file}} …",
"sendFailed": "发送失败: {{error}}",
"newOfferToast": "{{peer}}想向您发送文件: {{file}}",
@@ -623,7 +622,9 @@
"forgetAddress": "忘记已保存的目的地",
"forgetAddressAria": "删除此对等体已保存的rncp接收目的地",
"forgotAddressToast": "忘记了此对等方的保存的rncp目的地。",
- "filledFromChatToast": "通过聊天填写目的地(未保存—选中请记住保留)。"
+ "filledFromChatToast": "通过聊天填写目的地(未保存—选中请记住保留)。",
+ "offerBannerTitle": "传入文件报价",
+ "offerBannerTitleAria": "来自该对等方的待定入站文件报价"
},
"shareLocation": "分享位置",
"shareLocationLabel": "📍 共享位置",
@@ -4879,7 +4880,12 @@
"copyInstructions": "复制说明",
"instructionsCopied": "说明已复制。",
"receiveDestSharedToast": "已保存 {{peer}} 的 rncp 接收目的地 — 现在可以发送文件。",
- "receiveDestShareFailed": "无法保存对等方的 rncp 接收目的地。"
+ "receiveDestShareFailed": "无法保存对等方的 rncp 接收目的地。",
+ "peerUnreachable": "没有通往那个目的地的路。对等方可能离线。",
+ "checkingReachability": "检查可达性...",
+ "listenerLikelyOffTitle": "文件接收可能已关闭",
+ "listenerLikelyOffBody": "没有通往文件接收目的地的路径,但他们在网上查找聊天内容。要求他们启用文件接收(远程 → 设置 → 入站文件提供),然后重试。",
+ "listenerLikelyOffConfirm": "发送启用请求"
},
"enableRequest": {
"title": "启用文件接收?",
@@ -4896,9 +4902,9 @@
"enableFailed": "无法启用文件接收: {{error}}",
"saveDirRequired": "选择一个保存文件夹以启用接收。",
"identityUnknown": "暂时无法解析此对等节点的身份哈希 — 已启用来件询问,但未将其加入允许列表。等路径或公告到达后再试一次。",
- "lxmfBody": "如果您使用mesh-client :远程→设置→入站文件提供,请启用文件接收( rncp )。或者在监听模式下运行rncp/rncp-rs。",
"lxmfShareBody": "文件接收已启用。这是我的 rncp 接收目的地(mesh-client 将为您保存)。",
- "shareDestWarning": "如果启用,mesh-client 会将您的 rncp 接收目标发送到该对等方,以便他们可以自动填充文件发送。"
+ "shareDestWarning": "如果启用,mesh-client 会将您的 rncp 接收目标发送到该对等方,以便他们可以自动填充文件发送。",
+ "lxmfBody": "请启用 rncp 接收(远程 → 设置 → 入站文件提供)并向我发送您的 rncp 接收哈希值。"
},
"saved": {
"labelPlaceholder": "标号",