This commit is contained in:
koalasat
2025-04-24 23:27:15 +02:00
parent 26904f7cc2
commit 4a8e371e55
30 changed files with 440 additions and 159 deletions

View File

@ -1075,7 +1075,7 @@ class ReviewView(APIView):
{"bad_request": "Invalid hex pubkey"},
status.HTTP_400_BAD_REQUEST,
)
if request.user.robot.nostr_pubkey is not pubkey:
if request.user.robot.nostr_pubkey != pubkey:
return Response(
{"bad_request": "Wrong hex pubkey"},
status.HTTP_400_BAD_REQUEST,

View File

@ -0,0 +1,125 @@
import React, { useContext, useState } from 'react';
import { Button, Dialog, DialogContent, Grid, TextField, Typography } from '@mui/material';
import FederationTable from '../../components/FederationTable';
import { t } from 'i18next';
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
const Coordinators = (): JSX.Element => {
const { federation, addNewCoordinator } = useContext<UseFederationStoreType>(FederationContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const [newAlias, setNewAlias] = useState<string>('');
const [newUrl, setNewUrl] = useState<string>('');
const [error, setError] = useState<string>();
const [open, setOpen] = useState<boolean>(false);
// Regular expression to match a valid .onion URL
const onionUrlPattern = /^((http|https):\/\/)?[a-zA-Z2-7]{16,56}\.onion$\/?/;
const addCoordinator: () => void = () => {
if (federation.getCoordinator(newAlias)) {
setError(t('Alias already exists'));
} else {
if (onionUrlPattern.test(newUrl)) {
let fullNewUrl = newUrl;
if (!/^((http|https):\/\/)/.test(fullNewUrl)) {
fullNewUrl = `http://${newUrl}`;
}
addNewCoordinator(newAlias, fullNewUrl);
garage.syncCoordinator(federation, newAlias);
setNewAlias('');
setNewUrl('');
} else {
setError(t('Invalid Onion URL'));
}
}
};
return (
<Grid item xs={12}>
<Grid container direction='column' justifyItems='center' alignItems='center'>
<Grid item>
<Button
onClick={() => {
setOpen(true);
}}
color='primary'
variant='contained'
>
{t('Coordinators')}
</Button>
</Grid>
</Grid>
<Dialog
open={open}
onClose={() => {
setOpen(false);
}}
aria-labelledby='recovery-dialog-title'
aria-describedby='recovery-description'
>
<DialogContent>
<Grid container direction='column' alignItems='center' spacing={1} padding={2}>
<Grid item>
<Typography variant='h5' align='center'>
{t('Coordinators')}
</Typography>
</Grid>
<Grid item xs={12}>
<FederationTable fillContainer />
</Grid>
{error ?? (
<Grid item xs={12}>
<Typography align='center' component='h2' variant='subtitle2' color='secondary'>
{error}
</Typography>
</Grid>
)}
<Grid item xs={12}>
<Grid container direction='row' alignItems='center' spacing={1} padding={2}>
<Grid item xs={4}>
<TextField
id='outlined-basic'
label={t('Alias')}
variant='outlined'
size='small'
value={newAlias}
onChange={(e) => {
setNewAlias(e.target.value);
}}
/>
</Grid>
<Grid item xs={6}>
<TextField
id='outlined-basic'
label={t('URL')}
variant='outlined'
size='small'
value={newUrl}
onChange={(e) => {
setNewUrl(e.target.value);
}}
/>
</Grid>
<Grid item xs={1}>
<Button
sx={{ maxHeight: 38 }}
disabled={false}
onClick={addCoordinator}
variant='contained'
color='primary'
size='small'
type='submit'
>
{t('Add')}
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</DialogContent>
</Dialog>
</Grid>
);
};
export default Coordinators;

View File

@ -1,42 +1,12 @@
import React, { useContext, useState } from 'react';
import { Box, Button, Grid, List, ListItem, Paper, TextField, Typography } from '@mui/material';
import React, { useContext } from 'react';
import { Grid, Paper } from '@mui/material';
import SettingsForm from '../../components/SettingsForm';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import FederationTable from '../../components/FederationTable';
import { t } from 'i18next';
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
import Coordinators from './Coordinators';
const SettingsPage = (): JSX.Element => {
const { windowSize, navbarHeight } = useContext<UseAppStoreType>(AppContext);
const { federation, addNewCoordinator } = useContext<UseFederationStoreType>(FederationContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const maxHeight = (windowSize.height - navbarHeight) * 0.85 - 3;
const [newAlias, setNewAlias] = useState<string>('');
const [newUrl, setNewUrl] = useState<string>('');
const [error, setError] = useState<string>();
// Regular expression to match a valid .onion URL
const onionUrlPattern = /^((http|https):\/\/)?[a-zA-Z2-7]{16,56}\.onion$/;
const addCoordinator: () => void = () => {
if (federation.getCoordinator(newAlias)) {
setError(t('Alias already exists'));
} else {
if (onionUrlPattern.test(newUrl)) {
let fullNewUrl = newUrl;
if (!/^((http|https):\/\/)/.test(fullNewUrl)) {
fullNewUrl = `http://${newUrl}`;
}
addNewCoordinator(newAlias, fullNewUrl);
garage.syncCoordinator(federation, newAlias);
setNewAlias('');
setNewUrl('');
} else {
setError(t('Invalid Onion URL'));
}
}
};
return (
<Paper
elevation={12}
@ -52,57 +22,7 @@ const SettingsPage = (): JSX.Element => {
<Grid item xs={12}>
<SettingsForm />
</Grid>
<Grid item xs={12}>
<FederationTable maxHeight={18} />
</Grid>
<Grid item xs={12}>
<Typography align='center' component='h2' variant='subtitle2' color='secondary'>
{error}
</Typography>
</Grid>
<Grid item xs={12}>
<List>
<ListItem>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<TextField
id='outlined-basic'
label={t('Alias')}
variant='outlined'
size='small'
value={newAlias}
onChange={(e) => {
setNewAlias(e.target.value);
}}
/>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<TextField
id='outlined-basic'
label={t('URL')}
variant='outlined'
size='small'
value={newUrl}
onChange={(e) => {
setNewUrl(e.target.value);
}}
/>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<Button
sx={{ maxHeight: 38 }}
disabled={false}
onClick={addCoordinator}
variant='contained'
color='primary'
size='small'
type='submit'
>
{t('Add')}
</Button>
</Box>
</ListItem>
</List>
</Grid>
<Coordinators />
</Grid>
</Paper>
);

View File

@ -22,6 +22,7 @@ import {
AccordionSummary,
AlertTitle,
ListItemButton,
Rating,
} from '@mui/material';
import {
@ -72,6 +73,7 @@ import { systemClient } from '../../services/System';
import type Coordinator from '../../models/Coordinator.model';
import { type Badges } from '../../models/Coordinator.model';
import { type UseFederationStoreType, FederationContext } from '../../contexts/FederationContext';
import { verifyCoordinatorToken } from '../../utils/nostr';
interface Props {
open: boolean;
@ -358,6 +360,8 @@ const CoordinatorDialog = ({ open = false, onClose, shortAlias }: Props): JSX.El
const { clientVersion, page, settings, origin } = useContext(AppContext);
const { federation } = useContext<UseFederationStoreType>(FederationContext);
const [, setRating] = useState<number[]>([0, 0]);
const [averageRating, setAvergeRating] = useState<number>(0);
const [expanded, setExpanded] = useState<'summary' | 'stats' | 'policies' | undefined>(undefined);
const [coordinator, setCoordinator] = useState<Coordinator>(
federation.getCoordinator(shortAlias ?? ''),
@ -370,10 +374,39 @@ const CoordinatorDialog = ({ open = false, onClose, shortAlias }: Props): JSX.El
useEffect(() => {
setCoordinator(federation.getCoordinator(shortAlias ?? ''));
setRating([0, 0]);
setAvergeRating(0);
}, [shortAlias]);
useEffect(() => {
if (open) federation.getCoordinator(shortAlias ?? '')?.loadInfo();
if (open) {
const coordinator = federation.getCoordinator(shortAlias ?? '');
if (settings.connection === 'nostr') {
federation.roboPool.subscribeRatings(
{
onevent: (event) => {
const verfied = verifyCoordinatorToken(event);
const coordinatorPubKey = event.tags.find((t) => t[0] === 'p')?.[1];
if (verfied && coordinatorPubKey === coordinator.nostrHexPubkey) {
const eventRating = event.tags.find((t) => t[0] === 'rating')?.[1];
if (eventRating) {
setRating((prev) => {
const sum = prev[0];
const count = prev[1] + 1;
prev = [sum + parseFloat(eventRating), count];
setAvergeRating(sum / count);
return prev;
});
}
}
},
oneose: () => {},
},
[coordinator.nostrHexPubkey],
);
}
coordinator?.loadInfo();
}
}, [open]);
return (
@ -398,6 +431,21 @@ const CoordinatorDialog = ({ open = false, onClose, shortAlias }: Props): JSX.El
<i>{String(coordinator?.motto)}</i>
</Typography>
</Grid>
<Grid container direction='column' alignItems='center' padding={0}>
<Grid item>
<Rating
readOnly
precision={0.5}
name='size-large'
value={averageRating * 5}
defaultValue={0}
disabled={settings.connection !== 'nostr'}
/>
<Typography variant='caption' color='text.secondary'>
{`(${parseFloat((averageRating * 10).toFixed(1))})`}
</Typography>
</Grid>
</Grid>
<Grid item>
<ContactButtons {...coordinator?.contact} />
</Grid>

View File

@ -1,6 +1,6 @@
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { Link, LinkOff } from '@mui/icons-material';
import { Box, Checkbox, CircularProgress, Grid, Typography, useTheme } from '@mui/material';
import { Box, Checkbox, CircularProgress, Grid, Rating, Typography, useTheme } from '@mui/material';
import { DataGrid, type GridColDef, type GridValidRowModel } from '@mui/x-data-grid';
import { useTranslation } from 'react-i18next';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
@ -8,6 +8,7 @@ import { FederationContext, type UseFederationStoreType } from '../../contexts/F
import { type Coordinator } from '../../models';
import headerStyleFix from '../DataGrid/HeaderFix';
import RobotAvatar from '../RobotAvatar';
import { verifyCoordinatorToken } from '../../utils/nostr';
interface FederationTableProps {
maxWidth?: number;
@ -22,9 +23,16 @@ const FederationTable = ({
}: FederationTableProps): JSX.Element => {
const { t } = useTranslation();
const { federation, federationUpdatedAt } = useContext<UseFederationStoreType>(FederationContext);
const { setOpen } = useContext<UseAppStoreType>(AppContext);
const { setOpen, windowSize, settings } = useContext<UseAppStoreType>(AppContext);
const theme = useTheme();
const [pageSize, setPageSize] = useState<number>(0);
const [ratings, setRatings] = useState<Record<string, number[]>>(
federation.getCoordinators().reduce((acc, coord) => {
if (coord.nostrHexPubkey) acc[coord.nostrHexPubkey] = [0, 0];
return acc;
}, {}),
);
const [useDefaultPageSize, setUseDefaultPageSize] = useState(true);
// all sizes in 'em'
const fontSize = theme.typography.fontSize;
@ -35,8 +43,11 @@ const FederationTable = ({
1,
);
const height = defaultPageSize * verticalHeightRow + verticalHeightFrame;
const mobile = windowSize.width < 44;
const [useDefaultPageSize, setUseDefaultPageSize] = useState(true);
useEffect(() => {
loadRatings();
}, []);
useEffect(() => {
if (useDefaultPageSize) {
@ -44,6 +55,29 @@ const FederationTable = ({
}
}, [federationUpdatedAt]);
const loadRatings: () => void = () => {
if (settings.connection !== 'nostr') return;
federation.roboPool.subscribeRatings({
onevent: (event) => {
const verfied = verifyCoordinatorToken(event);
const coordinatorPubKey = event.tags.find((t) => t[0] === 'p')?.[1];
if (verfied && coordinatorPubKey) {
const rating = event.tags.find((t) => t[0] === 'rating')?.[1];
if (rating) {
setRatings((prev) => {
const sum = prev[coordinatorPubKey][0];
const count = prev[coordinatorPubKey][1];
prev[coordinatorPubKey] = [sum + parseFloat(rating), count + 1];
return prev;
});
}
}
},
oneose: () => {},
});
};
const localeText = {
MuiTablePagination: { labelRowsPerPage: t('Coordinators per page:') },
noResultsOverlayLabel: t('No coordinators found.'),
@ -55,11 +89,11 @@ const FederationTable = ({
});
};
const aliasObj = useCallback((width: number) => {
const aliasObj = useCallback((_width: number) => {
return {
field: 'longAlias',
headerName: t('Coordinator'),
width: width * fontSize,
headerName: mobile ? '' : t('Rating'),
width: mobile ? 60 : 190,
renderCell: (params: any) => {
const coordinator = federation.getCoordinator(params.row.shortAlias);
return (
@ -83,15 +117,67 @@ const FederationTable = ({
small={true}
/>
</Grid>
<Grid item>
<Typography>{params.row.longAlias}</Typography>
</Grid>
{!mobile ? (
<Grid item>
<Typography>{params.row.longAlias}</Typography>
</Grid>
) : (
<></>
)}
</Grid>
);
},
};
}, []);
const ratingObj = useCallback(
(width: number) => {
return {
field: 'rating',
headerName: t('Rating'),
width: mobile ? 60 : 170,
renderCell: (params: any) => {
const coordinator = federation.getCoordinator(params.row.shortAlias);
const coordinatorRating = ratings[coordinator.nostrHexPubkey];
if (!coordinatorRating) return <></>;
const average =
coordinatorRating && coordinatorRating[1] > 0
? coordinatorRating[0] / coordinatorRating[1]
: 0;
return (
<>
{mobile ? (
<Grid container direction='column' alignItems='center' style={{ paddingTop: 10 }}>
<Typography>{`${parseFloat((average * 10).toFixed(1))}`}</Typography>
</Grid>
) : (
<>
<Rating
readOnly
precision={0.5}
name='size-large'
value={average * 5}
defaultValue={0}
disabled={settings.connection !== 'nostr'}
onClick={() => {
onClickCoordinator(params.row.shortAlias);
}}
/>
<Typography variant='caption' color='text.secondary'>
{`(${parseFloat((average * 10).toFixed(1))})`}
</Typography>
</>
)}
</>
);
},
};
},
[federationUpdatedAt],
);
const enabledObj = useCallback(
(width: number) => {
return {
@ -151,9 +237,17 @@ const FederationTable = ({
object: aliasObj,
},
},
rating: {
priority: 2,
order: 2,
normal: {
width: 12.1,
object: ratingObj,
},
},
up: {
priority: 3,
order: 2,
order: 3,
normal: {
width: 3.5,
object: upObj,
@ -161,7 +255,7 @@ const FederationTable = ({
},
enabled: {
priority: 1,
order: 3,
order: 4,
normal: {
width: 5,
object: enabledObj,

View File

@ -48,6 +48,7 @@ export const SuccessfulPrompt = ({
const { federation } = useContext<UseFederationStoreType>(FederationContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const [coordinatorToken, setCoordinatorToken] = useState<string>();
const [hostRating, setHostRating] = useState<number>();
const rateHostPlatform = function (): void {
@ -56,12 +57,22 @@ export const SuccessfulPrompt = ({
const slot = garage.getSlot();
const coordinatorPubKey = federation.getCoordinator(order.shortAlias)?.nostrHexPubkey;
if (!slot?.nostrPubKey || !slot.nostrSecKey || !coordinatorPubKey || !order.id) return;
if (
!coordinatorToken ||
!slot?.nostrPubKey ||
!slot.nostrSecKey ||
!coordinatorPubKey ||
!order.id
) {
setHostRating(0);
return;
}
const eventTemplate: Event = {
kind: 31986,
created_at: Math.floor(Date.now() / 1000),
tags: [
['sig', coordinatorToken],
['d', `${order.shortAlias}:${order.id}`],
['p', coordinatorPubKey],
['rating', String(hostRating / 5)],
@ -76,6 +87,13 @@ export const SuccessfulPrompt = ({
federation.roboPool.sendEvent(signedEvent);
};
useEffect(() => {
const slot = garage.getSlot();
if (slot?.nostrPubKey) {
slot.getRobot(order.shortAlias)?.loadReviewToken(federation, setCoordinatorToken);
}
}, []);
useEffect(() => {
rateHostPlatform();
}, [hostRating]);
@ -91,7 +109,7 @@ export const SuccessfulPrompt = ({
>
<Grid item xs={12}>
<Typography variant='body2' align='center'>
{t('Rate your peer')} <b>{order.is_maker ? order.taker_nick : order.maker_nick}</b>
{t('Rate your trade experience')}
</Typography>
</Grid>
<Grid item>
@ -108,9 +126,6 @@ export const SuccessfulPrompt = ({
<Grid item xs={12}>
<Typography variant='body2' align='center'>
{t('Rate your host')} <b>{federation.getCoordinator(order.shortAlias)?.longAlias}</b>{' '}
<Typography variant='button' align='center'>
{t('BETA')}
</Typography>
<Tooltip title={t('You need to enable nostr to rate your coordinator.')}>
<Info sx={{ width: 15 }} />
</Tooltip>

View File

@ -120,7 +120,7 @@ const getSettings = (): Settings => {
} else {
settings = view === 'pro' ? new SettingsPro() : new Settings();
}
console.log(settings.connection);
return settings;
};

View File

@ -123,6 +123,31 @@ class Robot {
this.stealthInvoices = wantsStealth;
};
loadReviewToken = (
federation: Federation,
onDataLoad: (token: string) => void = () => {},
): void => {
if (!federation) return;
const coordinator = federation.getCoordinator(this.shortAlias);
const body = {
pubkey: this.nostrPubKey,
};
apiClient
.post(coordinator.url, `${coordinator.basePath}/api/review/`, body, {
tokenSHA256: this.tokenSHA256,
})
.then((data) => {
if (data) {
onDataLoad(data.token);
}
})
.catch((e) => {
console.log(e);
});
};
}
export default Robot;

View File

@ -44,10 +44,10 @@ class BaseSettings {
: i18n.resolvedLanguage.substring(0, 2);
const connection = systemClient.getItem('settings_connection');
this.connection = connection && connection !== '' ? connection : 'api';
this.connection = connection && connection !== '' ? connection : this.connection;
const networkCookie = systemClient.getItem('settings_network');
this.network = networkCookie && networkCookie !== '' ? networkCookie : 'mainnet';
this.network = networkCookie && networkCookie !== '' ? networkCookie : this.network;
this.host = getHost();
const [client] = window.RobosatsSettings.split('-');
@ -68,7 +68,7 @@ class BaseSettings {
public language?: Language;
public freezeViewports: boolean = false;
public network: 'mainnet' | 'testnet' = 'mainnet';
public connection: 'api' | 'nostr' = 'api';
public connection: 'api' | 'nostr' = 'nostr';
public host?: string;
public unsafeClient: boolean = false;
public selfhostedClient: boolean = false;

View File

@ -131,6 +131,30 @@ class RoboPool {
this.sendMessage(JSON.stringify(requestSuccess));
};
subscribeRatings = (events: RoboPoolEvents, coordinators?: string[]): void => {
const pubkeys =
coordinators ??
[...Object.values(defaultFederation), ...Object.values(thirdParties)]
.map((f) => f.nostrHexPubkey)
.filter((item) => item !== undefined);
const requestRatings = [
'REQ',
'subscribeRatings',
{ kinds: [31986], '#p': pubkeys, since: 1745509494 },
];
this.messageHandlers.push((_url: string, messageEvent: MessageEvent) => {
const jsonMessage = JSON.parse(messageEvent.data);
if (jsonMessage[0] === 'EVENT') {
events.onevent(jsonMessage[2]);
} else if (jsonMessage[0] === 'EOSE') {
events.oneose();
}
});
this.sendMessage(JSON.stringify(requestRatings));
};
sendEvent = (event: Event): void => {
const message = ['EVENT', event];

View File

@ -1,4 +1,5 @@
import { type Event } from 'nostr-tools';
import { schnorr } from '@noble/curves/secp256k1';
import { type PublicOrder } from '../models';
import { fromUnixTime } from 'date-fns';
import Geohash from 'latlon-geohash';
@ -106,4 +107,16 @@ const eventToPublicOrder = (event: Event): { dTag: string; publicOrder: PublicOr
return { dTag: dTag[1], publicOrder };
};
export const verifyCoordinatorToken: (event: Event) => boolean = (event) => {
const d = event.tags.find((t) => t[0] === 'd')?.[1];
const orderId = d?.split(':')?.[1];
const signature = event.tags.find((t) => t[0] === 'sig')?.[1];
const hash = `${event.pubkey}${orderId ?? ''}`;
const coordinatorPubKey = event.tags.find((t) => t[0] === 'p')?.[1];
if (signature && coordinatorPubKey) {
return schnorr.verify(signature, hash, coordinatorPubKey);
}
return false;
};
export default eventToPublicOrder;

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connectant a TOR",
"Connection encrypted and anonymized using TOR.": "Connexió xifrada i anònima mitjançant TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Això garanteix la màxima privadesa, però és possible que sentis que l'aplicació es comporta lenta. Si es perd la connexió, reinicia l'aplicació.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinadors per pàgina:",
"Enabled": "Habilitat",
"No coordinators found.": "No s'han trobat coordinadors.",
"Rating": "Rating",
"Up": "Pujar",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "El client RoboSats és servit pel teu propi node, gaudeixes de la major seguretat i privacitat.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats està intentant pagar la teva factura de Lightning. Recorda que els nodes Lightning han d'estar en línia per rebre pagaments.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renovar",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats millora amb més usuaris i liquiditat. Ensenya-li RoboSats a un amic bitcoiner!",
"Sending coins to": "Enviant monedes a",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats se snaží zaplatit tvůj lightning invoice. Nezapomeň, že lightning nody musí být online, aby mohl přijímat platby.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats bude lepší s větší likviditou a uživateli. Pověz svým přátelům o Robosats!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats versucht deine Lightning-Invoice zu bezahlen. Denk daran, dass deine Lightning-Node erreichbar sein muss, um die Zahlung zu erhalten.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats wird noch besser mit mehr Nutzern und Liquidität. Erzähl einem Bitcoin-Freund von uns!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Conectando con TOR",
"Connection encrypted and anonymized using TOR.": "Conexión encriptada y anonimizada usando TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Esto asegura máxima privacidad, aunque quizá observe algo de lentitud. Si se corta la conexión, reinicie la aplicación.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "El cliente RoboSats es servido por tu propio nodo, gozas de la mayor seguridad y privacidad.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats está intentando pagar tu factura de Lightning. Recuerda que los nodos Lightning deben estar en línea para recibir pagos.",
"Taking too long?": "¿Tarda demasiado?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renovar",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats mejora con más liquidez y usuarios. ¡Háblale a un amigo bitcoiner sobre RoboSats!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats webgunea zure nodotik zerbitzatzen da beraz segurtasun eta pribatutasun sendoena eskaintzen dizu.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats zure Lightning faktura ordaintzen saiatzen ari da. Gogoratu lightning nodoak online egon behar direla ordainketak jaso ahal izateko.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats hobetu egiten da likidezia eta erabiltzaile gehiagorekin. Aipatu Robosats lagun bitcoiner bati!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connexion au réseau TOR",
"Connection encrypted and anonymized using TOR.": "Connexion chiffré et anonymisée utilisant TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Cela garantit une confidentialité maximale, mais l'application peut sembler lente. Si la connexion est perdue, redémarrez l'application.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "Le client RoboSats est servi à partir de votre propre nœud, ce qui vous garantit une sécurité et une confidentialité optimales.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats tente de payer votre facture lightning. Rappelez-vous que les nœuds lightning doivent être en ligne pour recevoir des paiements.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renouveler",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats s'améliore avec plus de liquidité et d'utilisateurs. Parlez de Robosats à un ami bitcoiner!",
"Sending coins to": "Envoi coins à",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connessione a TOR",
"Connection encrypted and anonymized using TOR.": "Connessione criptata e anonimizzata mediante TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Questo garantisce la massima privacy, ma l'app potrebbe risultare lenta. Se si perde la connessione, riavviare l'app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "Il client RoboSats è servito dal proprio nodo, garantendo la massima sicurezza e privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats sta provando a pagare la tua fattura lightning. Ricorda che i nodi lightning devono essere online per ricevere pagamenti.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Rinnova",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats migliora se ha più liquidità ed utenti. Parla di Robosats ai tuoi amici bitcoiner!",
"Sending coins to": "Invio monete a",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Torネットワークに接続中",
"Connection encrypted and anonymized using TOR.": "接続はTORを使って暗号化され、匿名化されています。",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "これにより最大限のプライバシーが確保されますが、アプリの動作が遅いと感じることがあります。接続が切断された場合は、アプリを再起動してください。",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSatsクライアントは、あなた自身のードから提供され、最高のセキュリティとプライバシーが保証されます。",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSatsはあなたのライトニングインボイスを支払おうとしています。支払いを受け取るには、ライトニングードがオンラインである必要があることを忘れないでください。",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "更新する",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSatsはより多くの流動性とユーザーでより良くなります。ビットコイナーのお友達にRoboSatsについて話してください",
"Sending coins to": "コインを送信する先",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats próbuje zapłacić fakturę za błyskawicę. Pamiętaj, że węzły pioruna muszą być online, aby otrzymywać płatności.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats staje się lepszy dzięki większej płynności i użytkownikom. Powiedz znajomemu bitcoinerowi o Robosats!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Conectando ao TOR",
"Connection encrypted and anonymized using TOR.": "Conexão criptografada e anonimizada usando TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Isso garante privacidade máxima, entretanto, você pode sentir que o aplicativo fique lento. Se a conexão for perdida, reinicie-o.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats está tentando pagar sua lightning invoice. Lembre-se de que os nós lightning devem estar online para receber pagamentos.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats fica melhor com mais liquidez e usuários. Conte a um amigo bitcoiner sobre Robosats!",
"Sending coins to": "Enviando moedas para",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Подключение к TOR",
"Connection encrypted and anonymized using TOR.": "Соединение зашифровано и анонимизировано с помощью TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Это обеспечивает максимальную конфиденциальность, однако вы можете почувствовать, что приложение работает медленно. Если соединение потеряно, перезапустите приложение.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "Клиент RoboSats обслуживается с вашего собственного нода, что обеспечивает максимальную безопасность и конфиденциальность.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats пытается оплатить Ваш Lightning инвойс. Помните, что ноды Lightning должны быть подключены к сети, чтобы получать платежи.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats становится лучше с большей ликвидностью и пользователями. Расскажите другу-биткойнеру о Robosat!",
"Sending coins to": "Отправка монет на",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats försöker betala din lightning-faktura. Kom ihåg att lightning-noder måste vara online för att kunna mottaga betalningar.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats blir bättre med mer likviditet och fler användare. Berätta om RoboSats för en Bitcoiner-vän!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Kuunganisha kwa TOR",
"Connection encrypted and anonymized using TOR.": "Unganisho limefichwa na kufanywa kuwa na siri kwa kutumia TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "Hii inahakikisha faragha ya juu kabisa, hata hivyo unaweza kuhisi programu inafanya kazi polepole. Ikiwa mawasiliano yamepotea, anza tena programu.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "Mteja wa RoboSats unatolewa kutoka kwenye node yako mwenyewe ikikupa usalama na faragha imara kabisa.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats inajaribu kulipa ankara yako ya umeme. Kumbuka kuwa nodi za umeme lazima ziwe mtandaoni ili kupokea malipo.",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats inaboreshwa na utoshelevu zaidi na watumiaji. Mwambie rafiki yako wa Bitcoin kuhusu RoboSats!",
"Sending coins to": "Inatuma sarafu kwa",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "Connecting to TOR",
"Connection encrypted and anonymized using TOR.": "Connection encrypted and anonymized using TOR.",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats client is served from your own node granting you the strongest security and privacy.",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats กำลังจ่ายเหรียญให้ lightning invoice ของท่าน lightning nodes จะต้องออนไลน์เพื่อรับเหรียญ",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "Renew",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats จะดีขึ้นเมื่อมีสภาพคล่องและผู้ใช้งานมากขึ้น ช่วยกันชวนเพื่อนของคุณมาใช้ Robosats!",
"Sending coins to": "Sending coins to",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "正在连线 TOR",
"Connection encrypted and anonymized using TOR.": "连接已用 TOR 加密和匿名化。",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "这确保最高的隐秘程度,但你可能会觉得应用程序运作缓慢。如果丢失连接,请重启应用。",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats 客户端已由你自己的节点提供服务,为你提供最强的安全性和隐私性。",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats 正在尝试支付你的闪电发票。请注意,闪电节点必须在线才能接收付款。",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "延续",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats 会随着更多的流动性和更高的用户数量而变得更好。把 RoboSats 推荐给你的比特币朋友吧!",
"Sending coins to": "将比特币发送到",

View File

@ -68,10 +68,11 @@
"Connecting to TOR": "正在連線 TOR",
"Connection encrypted and anonymized using TOR.": "連接已用 TOR 加密和匿名化。",
"This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.": "這確保最高的隱密程度,但你可能會覺得應用程序運作緩慢。如果丟失連接,請重啟應用。",
"#12": "Phrases in basic/SettingsPage/index.tsx",
"#12": "Phrases in basic/SettingsPage/Coordinators.tsx",
"Add": "Add",
"Alias": "Alias",
"Alias already exists": "Alias already exists",
"Coordinators": "Coordinators",
"Invalid Onion URL": "Invalid Onion URL",
"URL": "URL",
"#13": "Phrases in components/BookTable/BookControl.tsx",
@ -343,6 +344,7 @@
"Coordinators per page:": "Coordinators per page:",
"Enabled": "Enabled",
"No coordinators found.": "No coordinators found.",
"Rating": "Rating",
"Up": "Up",
"#36": "Phrases in components/HostAlert/SelfhostedAlert.tsx",
"RoboSats client is served from your own node granting you the strongest security and privacy.": "RoboSats客戶端已由你自己的節點提供服務為你提供最強的安全性和隱私性。",
@ -679,9 +681,8 @@
"RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.": "RoboSats 正在嘗試支付你的閃電發票。請注意,閃電節點必須在線才能接收付款。",
"Taking too long?": "Taking too long?",
"#82": "Phrases in components/TradeBox/Prompts/Successful.tsx",
"BETA": "BETA",
"Rate your host": "Rate your host",
"Rate your peer": "Rate your peer",
"Rate your trade experience": "Rate your trade experience",
"Renew": "延續",
"RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!": "RoboSats 會隨著更多的流動性和更高的用戶数量而變得更好。把 RoboSats 推薦給你的比特幣朋友吧!",
"Sending coins to": "將比特幣發送到",

View File

@ -1 +1 @@
aa19b79461dbd92673900cd50f51934ec648f8dbb79cb2e3e59929e798d41e86
4b809260d59c8109a9de49b373253432c09a10fe87aad9386b2c958fb00e0b94

View File

@ -1 +1 @@
b905e7adcee82cc7fe3ba05c8f0922c9098a872f71db4ba70c216e4396d73be8
1934f637425f7a881020d013b0b5996eac937b864de48bc8114b0d86b78ca9c9