Implement i18n 9/9 Book, Bottom Bar, Profile, Misc, Info

This commit is contained in:
Reckless_Satoshi
2022-04-04 15:56:50 -07:00
parent 41d121ce82
commit eaf596936c
13 changed files with 359 additions and 230 deletions

View File

@ -3398,6 +3398,14 @@
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.25.tgz", "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.25.tgz",
"integrity": "sha512-1sF/6cit7MYfmxrqNiVN0ijLGv10xtV8egAUwUgIW6Q/Y6d7SuuVw5TOBnG7qIFqrNjxaPNoIAZmx7yOEuZvDA==" "integrity": "sha512-1sF/6cit7MYfmxrqNiVN0ijLGv10xtV8egAUwUgIW6Q/Y6d7SuuVw5TOBnG7qIFqrNjxaPNoIAZmx7yOEuZvDA=="
}, },
"cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
"requires": {
"node-fetch": "2.6.7"
}
},
"cross-spawn": { "cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -4339,6 +4347,14 @@
"@babel/runtime": "^7.14.6" "@babel/runtime": "^7.14.6"
} }
}, },
"i18next-http-backend": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.4.0.tgz",
"integrity": "sha512-wsvx7E/CT1pHmBM99Vu57YLJpsrHbVjxGxf25EIJ/6oTjsvCkZZ6c3SA4TejcK5jIHfv9oLxQX8l+DFKZHZ0Gg==",
"requires": {
"cross-fetch": "3.1.5"
}
},
"i18next-xhr-backend": { "i18next-xhr-backend": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/i18next-xhr-backend/-/i18next-xhr-backend-3.2.2.tgz", "resolved": "https://registry.npmjs.org/i18next-xhr-backend/-/i18next-xhr-backend-3.2.2.tgz",

View File

@ -35,6 +35,7 @@
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"i18next": "^21.6.14", "i18next": "^21.6.14",
"i18next-browser-languagedetector": "^6.1.4", "i18next-browser-languagedetector": "^6.1.4",
"i18next-http-backend": "^1.4.0",
"i18next-xhr-backend": "^3.2.2", "i18next-xhr-backend": "^3.2.2",
"material-ui-image": "^3.3.2", "material-ui-image": "^3.3.2",
"react-countdown": "^2.3.2", "react-countdown": "^2.3.2",

View File

@ -53,10 +53,11 @@ class BookPage extends Component {
} }
getCurrencyCode(val){ getCurrencyCode(val){
const { t } = this.props;
if (val){ if (val){
return val == 0 ? 'ANY' : currencyDict[val.toString()] return val == 0 ? t('ANY_currency') : currencyDict[val.toString()]
}else{ }else{
return 'ANY' return t('ANY_currency')
} }
} }
@ -86,6 +87,7 @@ class BookPage extends Component {
} }
bookListTableDesktop=()=>{ bookListTableDesktop=()=>{
const { t } = this.props;
return ( return (
<div style={{ height: 422, width: '100%' }}> <div style={{ height: 422, width: '100%' }}>
<DataGrid <DataGrid
@ -95,7 +97,7 @@ class BookPage extends Component {
avatar: window.location.origin +'/static/assets/avatars/' + order.maker_nick + '.png', avatar: window.location.origin +'/static/assets/avatars/' + order.maker_nick + '.png',
robot: order.maker_nick, robot: order.maker_nick,
robot_status: order.maker_status, robot_status: order.maker_status,
type: order.type ? "Seller": "Buyer", type: order.type ? t("Seller"): t("Buyer"),
amount: order.amount, amount: order.amount,
has_range: order.has_range, has_range: order.has_range,
min_amount: order.min_amount, min_amount: order.min_amount,
@ -109,11 +111,11 @@ class BookPage extends Component {
loading={this.state.loading} loading={this.state.loading}
columns={[ columns={[
// { field: 'id', headerName: 'ID', width: 40 }, // { field: 'id', headerName: 'ID', width: 40 },
{ field: 'robot', headerName: 'Robot', width: 240, { field: 'robot', headerName: t("Robot"), width: 240,
renderCell: (params) => {return ( renderCell: (params) => {return (
<ListItemButton style={{ cursor: "pointer" }}> <ListItemButton style={{ cursor: "pointer" }}>
<ListItemAvatar> <ListItemAvatar>
<Tooltip placement="right" enterTouchDelay="0" title={params.row.robot_status}> <Tooltip placement="right" enterTouchDelay="0" title={t(params.row.robot_status)}>
<Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(params.row.robot_status)}> <Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(params.row.robot_status)}>
<div style={{ width: 45, height: 45 }}> <div style={{ width: 45, height: 45 }}>
<Image className='bookAvatar' <Image className='bookAvatar'
@ -131,24 +133,24 @@ class BookPage extends Component {
</ListItemButton> </ListItemButton>
); );
} }, } },
{ field: 'type', headerName: 'Is', width: 60 }, { field: 'type', headerName: t("Is"), width: 60 },
{ field: 'amount', headerName: 'Amount', type: 'number', width: 90, { field: 'amount', headerName: t("Amount"), type: 'number', width: 90,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div> <div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div>
)}}, )}},
{ field: 'currency', headerName: 'Currency', width: 100, { field: 'currency', headerName: t("Currency"), width: 100,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer", display:'flex',alignItems:'center', flexWrap:'wrap'}}>{params.row.currency+" "}{getFlags(params.row.currency)}</div>) <div style={{ cursor: "pointer", display:'flex',alignItems:'center', flexWrap:'wrap'}}>{params.row.currency+" "}{getFlags(params.row.currency)}</div>)
}}, }},
{ field: 'payment_method', headerName: 'Payment Method', width: 180 , { field: 'payment_method', headerName: t("Payment Method"), width: 180 ,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}><PaymentText verbose={true} size={20} text={params.row.payment_method}/></div> <div style={{ cursor: "pointer" }}><PaymentText verbose={true} size={20} text={params.row.payment_method}/></div>
)} }, )} },
{ field: 'price', headerName: 'Price', type: 'number', width: 140, { field: 'price', headerName: t("Price"), type: 'number', width: 140,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }</div> <div style={{ cursor: "pointer" }}>{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }</div>
)} }, )} },
{ field: 'premium', headerName: 'Premium', type: 'number', width: 100, { field: 'premium', headerName: t("Premium"), type: 'number', width: 100,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }</div> <div style={{ cursor: "pointer" }}>{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }</div>
)} }, )} },
@ -164,7 +166,7 @@ class BookPage extends Component {
} }
bookListTablePhone=()=>{ bookListTablePhone=()=>{
const { t } = this.props;
return ( return (
<div style={{ height: 422, width: '100%' }}> <div style={{ height: 422, width: '100%' }}>
<DataGrid <DataGrid
@ -175,7 +177,7 @@ class BookPage extends Component {
avatar: window.location.origin +'/static/assets/avatars/' + order.maker_nick + '.png', avatar: window.location.origin +'/static/assets/avatars/' + order.maker_nick + '.png',
robot: order.maker_nick, robot: order.maker_nick,
robot_status: order.maker_status, robot_status: order.maker_status,
type: order.type ? "Seller": "Buyer", type: order.type ? t("Seller"): t("Buyer"),
amount: order.amount, amount: order.amount,
has_range: order.has_range, has_range: order.has_range,
min_amount: order.min_amount, min_amount: order.min_amount,
@ -189,9 +191,9 @@ class BookPage extends Component {
columns={[ columns={[
// { field: 'id', headerName: 'ID', width: 40 }, // { field: 'id', headerName: 'ID', width: 40 },
{ field: 'robot', headerName: 'Robot', width: 64, { field: 'robot', headerName: t("Robot"), width: 64,
renderCell: (params) => {return ( renderCell: (params) => {return (
<Tooltip placement="right" enterTouchDelay="0" title={params.row.robot+" ("+params.row.robot_status+")"}> <Tooltip placement="right" enterTouchDelay="0" title={params.row.robot+" ("+t(params.row.robot_status)+")"}>
<Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(params.row.robot_status)}> <Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(params.row.robot_status)}>
<div style={{ width: 45, height: 45 }}> <div style={{ width: 45, height: 45 }}>
<Image className='bookAvatar' <Image className='bookAvatar'
@ -206,29 +208,29 @@ class BookPage extends Component {
</Tooltip> </Tooltip>
); );
} }, } },
{ field: 'type', headerName: 'Is', width: 60, hide:'true'}, { field: 'type', headerName: t("Is"), width: 60, hide:'true'},
{ field: 'amount', headerName: 'Amount', type: 'number', width: 84, { field: 'amount', headerName: t("Amount"), type: 'number', width: 84,
renderCell: (params) => {return ( renderCell: (params) => {return (
<Tooltip placement="right" enterTouchDelay="0" title={params.row.type}> <Tooltip placement="right" enterTouchDelay="0" title={t(params.row.type)}>
<div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div> <div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div>
</Tooltip> </Tooltip>
)} }, )} },
{ field: 'currency', headerName: 'Currency', width: 85, { field: 'currency', headerName: t("Currency"), width: 85,
renderCell: (params) => {return ( renderCell: (params) => {return (
// <Tooltip placement="left" enterTouchDelay="0" title={params.row.payment_method}> // <Tooltip placement="left" enterTouchDelay="0" title={params.row.payment_method}>
<div style={{ cursor: "pointer", display:'flex',alignItems:'center', flexWrap:'wrap'}}>{params.row.currency+" "}{getFlags(params.row.currency)}</div> <div style={{ cursor: "pointer", display:'flex',alignItems:'center', flexWrap:'wrap'}}>{params.row.currency+" "}{getFlags(params.row.currency)}</div>
// </Tooltip> // </Tooltip>
)} }, )} },
{ field: 'payment_method', headerName: 'Payment Method', width: 180, hide:'true'}, { field: 'payment_method', headerName: t("Payment Method"), width: 180, hide:'true'},
{ field: 'payment_icons', headerName: 'Pay', width: 75 , { field: 'payment_icons', headerName: t("Pay"), width: 75 ,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{position:'relative', left:'-4px', cursor: "pointer", align:"center"}}><PaymentText size={16} text={params.row.payment_method}/></div> <div style={{position:'relative', left:'-4px', cursor: "pointer", align:"center"}}><PaymentText size={16} text={params.row.payment_method}/></div>
)} }, )} },
{ field: 'price', headerName: 'Price', type: 'number', width: 140, hide:'true', { field: 'price', headerName: t("Price"), type: 'number', width: 140, hide:'true',
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }</div> <div style={{ cursor: "pointer" }}>{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }</div>
)} }, )} },
{ field: 'premium', headerName: 'Premium', type: 'number', width: 85, { field: 'premium', headerName: t("Premium"), type: 'number', width: 85,
renderCell: (params) => {return ( renderCell: (params) => {return (
<Tooltip placement="left" enterTouchDelay="0" title={this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }> <Tooltip placement="left" enterTouchDelay="0" title={this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }>
<div style={{ cursor: "pointer" }}>{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }</div> <div style={{ cursor: "pointer" }}>{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }</div>
@ -247,6 +249,7 @@ class BookPage extends Component {
} }
render() { render() {
const { t } = this.props;
return ( return (
<Grid className='orderBook' container spacing={1} sx={{minWidth:400}}> <Grid className='orderBook' container spacing={1} sx={{minWidth:400}}>
{/* <Grid item xs={12} align="center"> {/* <Grid item xs={12} align="center">
@ -256,21 +259,21 @@ class BookPage extends Component {
<Grid item xs={6} align="right"> <Grid item xs={6} align="right">
<FormControl align="center"> <FormControl align="center">
<FormHelperText align="center"> <FormHelperText align="center">
I want to {t("I want to")}
</FormHelperText> </FormHelperText>
<Select <Select
sx={{width:90}} sx={{width:90}}
autoWidth={true} autoWidth={true}
label="Select Order Type" label={t("Select Order Type")}
required="true" required="true"
value={this.props.type} value={this.props.type}
inputProps={{ inputProps={{
style: {textAlign:"center"} style: {textAlign:"center"}
}} }}
onChange={this.handleTypeChange} onChange={this.handleTypeChange}
> <MenuItem value={2}>ANY</MenuItem> > <MenuItem value={2}>{t("ANY_type")}</MenuItem>
<MenuItem value={1}>BUY</MenuItem> <MenuItem value={1}>{t("BUY")}</MenuItem>
<MenuItem value={0}>SELL</MenuItem> <MenuItem value={0}>{t("SELL")}</MenuItem>
</Select> </Select>
</FormControl> </FormControl>
</Grid> </Grid>
@ -278,19 +281,19 @@ class BookPage extends Component {
<Grid item xs={6} align="left"> <Grid item xs={6} align="left">
<FormControl align="center"> <FormControl align="center">
<FormHelperText align="center"> <FormHelperText align="center">
and {this.props.type == 0 ? ' receive' : (this.props.type == 1 ? ' pay with' : ' use' )} {this.props.type == 0 ? t("and receive") : (this.props.type == 1 ? t("and pay with") : t("and use") )}
</FormHelperText> </FormHelperText>
<Select <Select
//autoWidth={true} //autoWidth={true}
sx={{width:110}} sx={{width:110}}
label="Select Payment Currency" label={t("Select Payment Currency")}
required="true" required="true"
value={this.props.currency} value={this.props.currency}
inputProps={{ inputProps={{
style: {textAlign:"center"} style: {textAlign:"center"}
}} }}
onChange={this.handleCurrencyChange} onChange={this.handleCurrencyChange}
> <MenuItem value={0}>🌍 ANY</MenuItem> > <MenuItem value={0}>{t("🌍 ANY")}</MenuItem>
{ {
Object.entries(currencyDict) Object.entries(currencyDict)
.map( ([key, value]) => <MenuItem value={parseInt(key)}><div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>{getFlags(value)}{" "+value}</div></MenuItem> ) .map( ([key, value]) => <MenuItem value={parseInt(key)}><div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>{getFlags(value)}{" "+value}</div></MenuItem> )
@ -301,7 +304,15 @@ class BookPage extends Component {
{ this.state.not_found ? "" : { this.state.not_found ? "" :
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="h5" variant="h5"> <Typography component="h5" variant="h5">
You are {this.props.type == 0 ? <b> selling </b> : (this.props.type == 1 ? <b> buying </b> :" looking at all ")} BTC for {this.props.currencyCode} {this.props.type == 0 ?
t("You are SELLING BTC for {{currencyCode}}",{currencyCode:this.props.currencyCode})
:
(this.props.type == 1 ?
t("You are BUYING BTC for {{currencyCode}}",{currencyCode:this.props.currencyCode})
:
t("You are looking at all")
)
}
</Typography> </Typography>
</Grid> </Grid>
} }
@ -310,15 +321,19 @@ class BookPage extends Component {
(<Grid item xs={12} align="center"> (<Grid item xs={12} align="center">
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="h5" variant="h5"> <Typography component="h5" variant="h5">
No orders found to {this.props.type == 0 ? ' sell ' :' buy ' } BTC for {this.props.currencyCode} {this.props.type == 0 ?
t("No orders found to sell BTC for {{currencyCode}}",{currencyCode:this.props.currencyCode})
:
t("No orders found to buy BTC for {{currencyCode}}",{currencyCode:this.props.currencyCode})
}
</Typography> </Typography>
</Grid> </Grid>
<br/> <br/>
<Grid item> <Grid item>
<Button size="large" variant="contained" color='primary' to='/make/' component={Link}>Make Order</Button> <Button size="large" variant="contained" color='primary' to='/make/' component={Link}>{t("Make Order")}</Button>
</Grid> </Grid>
<Typography color="primary" component="body1" variant="body1"> <Typography color="primary" component="body1" variant="body1">
Be the first one to create an order {t("Be the first one to create an order")}
<br/> <br/>
<br/> <br/>
</Typography> </Typography>
@ -342,7 +357,7 @@ class BookPage extends Component {
} }
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button color="secondary" variant="contained" to="/" component={Link}> <Button color="secondary" variant="contained" to="/" component={Link}>
Back {t("Back")}
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>

View File

@ -3,6 +3,7 @@ import { withTranslation, Trans} from "react-i18next";
import {FormControlLabel, Link, Switch, CircularProgress, Badge, Tooltip, TextField, ListItemAvatar, Button, Avatar,Paper, Grid, IconButton, Typography, Select, MenuItem, List, ListItemText, ListItem, ListItemIcon, ListItemButton, Divider, Dialog, DialogContent} from "@mui/material"; import {FormControlLabel, Link, Switch, CircularProgress, Badge, Tooltip, TextField, ListItemAvatar, Button, Avatar,Paper, Grid, IconButton, Typography, Select, MenuItem, List, ListItemText, ListItem, ListItemIcon, ListItemButton, Divider, Dialog, DialogContent} from "@mui/material";
import MediaQuery from 'react-responsive' import MediaQuery from 'react-responsive'
import { Link as LinkRouter } from 'react-router-dom' import { Link as LinkRouter } from 'react-router-dom'
import Flags from 'country-flag-icons/react/3x2'
// Icons // Icons
import SettingsIcon from '@mui/icons-material/Settings'; import SettingsIcon from '@mui/icons-material/Settings';
@ -105,7 +106,7 @@ class BottomBar extends Component {
}; };
StatsDialog =() =>{ StatsDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openStatsForNerds} open={this.state.openStatsForNerds}
@ -114,12 +115,12 @@ class BottomBar extends Component {
aria-describedby="stats-for-nerds-description" aria-describedby="stats-for-nerds-description"
> >
<DialogContent> <DialogContent>
<Typography component="h5" variant="h5">Stats For Nerds</Typography> <Typography component="h5" variant="h5">{t("Stats For Nerds")}</Typography>
<List dense> <List dense>
<Divider/> <Divider/>
<ListItem> <ListItem>
<ListItemIcon><BoltIcon/></ListItemIcon> <ListItemIcon><BoltIcon/></ListItemIcon>
<ListItemText primary={this.state.lnd_version} secondary="LND version"/> <ListItemText primary={this.state.lnd_version} secondary={t("LND version")}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -155,7 +156,7 @@ class BottomBar extends Component {
<Divider/> <Divider/>
<ListItem> <ListItem>
<ListItemIcon><GitHubIcon/></ListItemIcon> <ListItemIcon><GitHubIcon/></ListItemIcon>
<ListItemText secondary="Currently running commit hash"> <ListItemText secondary={t("Currently running commit hash")}>
<Link target="_blank" href={"https://github.com/Reckless-Satoshi/robosats/tree/" <Link target="_blank" href={"https://github.com/Reckless-Satoshi/robosats/tree/"
+ this.state.robosats_running_commit_hash}>{this.state.robosats_running_commit_hash.slice(0, 12)+"..."} + this.state.robosats_running_commit_hash}>{this.state.robosats_running_commit_hash.slice(0, 12)+"..."}
</Link> </Link>
@ -165,13 +166,13 @@ class BottomBar extends Component {
<Divider/> <Divider/>
<ListItem> <ListItem>
<ListItemIcon><EqualizerIcon/></ListItemIcon> <ListItemIcon><EqualizerIcon/></ListItemIcon>
<ListItemText primary={pn(this.state.last_day_volume)+" Sats"} secondary="24h contracted volume"/> <ListItemText primary={pn(this.state.last_day_volume)+" Sats"} secondary={t("24h contracted volume")}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
<ListItem> <ListItem>
<ListItemIcon><EqualizerIcon/></ListItemIcon> <ListItemIcon><EqualizerIcon/></ListItemIcon>
<ListItemText primary={pn(this.state.lifetime_volume)+" BTC"} secondary="Lifetime contracted volume"/> <ListItemText primary={pn(this.state.lifetime_volume)+" BTC"} secondary={t("Lifetime contracted volume")}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -179,12 +180,12 @@ class BottomBar extends Component {
<ListItemIcon><PublicIcon/></ListItemIcon> <ListItemIcon><PublicIcon/></ListItemIcon>
<ListItemText primary={ <ListItemText primary={
<div style={{display:'flex', alignItems:'center', justifyContent:'left', flexWrap:'wrap'}}> <div style={{display:'flex', alignItems:'center', justifyContent:'left', flexWrap:'wrap'}}>
<span>Made with </span> <span>{t("Made with")+" "}</span>
<FavoriteIcon sx={{ color: "#FF0000", height: '22px',width: '22px'}}/> <FavoriteIcon sx={{ color: "#FF0000", height: '22px',width: '22px'}}/>
<span> and </span> <span>{" "+t("and")+" "}</span>
<BoltIcon sx={{ color: "#fcba03", height: '23px',width: '23px'}}/> <BoltIcon sx={{ color: "#fcba03", height: '23px',width: '23px'}}/>
</div>} </div>}
secondary="... somewhere on Earth!"/> secondary={t("... somewhere on Earth!")}/>
</ListItem> </ListItem>
</List> </List>
@ -201,6 +202,7 @@ class BottomBar extends Component {
}; };
CommunityDialog =() =>{ CommunityDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
@ -210,36 +212,43 @@ class BottomBar extends Component {
aria-describedby="community-description" aria-describedby="community-description"
> >
<DialogContent> <DialogContent>
<Typography component="h5" variant="h5">Community</Typography> <Typography component="h5" variant="h5">{t("Community")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> Support is only offered via public channels. <p>{t("Support is only offered via public channels. Join our Telegram community if you have questions or want to hang out with other cool robots. Please, use our Github Issues if you find a bug or want to see new features!")}</p>
Join our Telegram community if you have
questions or want to hang out with other cool robots.
Please, use our Github Issues if you find a bug or want
to see new features!
</p>
</Typography> </Typography>
<List> <List>
<Divider/> <Divider/>
<ListItemButton component="a" target="_blank" href="https://t.me/robosats"> <ListItemButton component="a" target="_blank" href="https://t.me/robosats">
<ListItemIcon><SendIcon/></ListItemIcon> <ListItemIcon><SendIcon/></ListItemIcon>
<ListItemText primary="Join the RoboSats group" <ListItemText primary={t("Join the RoboSats group")}
secondary="Telegram (English / Main)"/> secondary={t("Telegram (English / Main)")}/>
</ListItemButton> </ListItemButton>
<Divider/> <Divider/>
<ListItemButton component="a" target="_blank" href="https://t.me/robosats_es"> <ListItem>
<ListItemIcon><SendIcon/></ListItemIcon> <ListItemIcon><SendIcon/></ListItemIcon>
<ListItemText primary="Unase al grupo RoboSats" <ListItemText secondary={t("RoboSats Telegram Communities")}>
secondary="Telegram (Español)"/> <Tooltip title={t("Join RoboSats Spanish speaking community!")}>
</ListItemButton> <IconButton component="a" target="_blank" href="https://t.me/robosats_es"><Flags.ES width={30} height={30} style={{filter: 'drop-shadow(2px 2px 2px #444444)'}}/></IconButton>
</Tooltip>
<Tooltip title={t("Join RoboSats Russian speaking community!")}>
<IconButton component="a" target="_blank" href="https://t.me/robosats_ru"><Flags.RU width={30} height={30} style={{filter: 'drop-shadow(2px 2px 2px #444444)'}}/></IconButton>
</Tooltip>
<Tooltip title={t("Join RoboSats Chinesse speaking community!")}>
<IconButton component="a" target="_blank" href="https://t.me/robosats_cn"><Flags.CN width={30} height={30} style={{filter: 'drop-shadow(2px 2px 2px #444444)'}}/></IconButton>
</Tooltip>
<Tooltip title={t("Join RoboSats English speaking community!")}>
<IconButton component="a" target="_blank" href="https://t.me/robosats"><Flags.US width={30} height={30} style={{filter: 'drop-shadow(2px 2px 2px #444444)'}}/></IconButton>
</Tooltip>
</ListItemText>
</ListItem>
<Divider/> <Divider/>
<ListItemButton component="a" target="_blank" href="https://github.com/Reckless-Satoshi/robosats/issues"> <ListItemButton component="a" target="_blank" href="https://github.com/Reckless-Satoshi/robosats/issues">
<ListItemIcon><GitHubIcon/></ListItemIcon> <ListItemIcon><GitHubIcon/></ListItemIcon>
<ListItemText primary="Tell us about a new feature or a bug" <ListItemText primary={t("Tell us about a new feature or a bug")}
secondary="Github Issues - The Robotic Satoshis Open Source Project"/> secondary={t("Github Issues - The Robotic Satoshis Open Source Project")}/>
</ListItemButton> </ListItemButton>
</List> </List>
@ -286,6 +295,7 @@ class BottomBar extends Component {
} }
dialogProfile =() =>{ dialogProfile =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openProfile} open={this.state.openProfile}
@ -294,11 +304,11 @@ class BottomBar extends Component {
aria-describedby="profile-description" aria-describedby="profile-description"
> >
<DialogContent> <DialogContent>
<Typography component="h5" variant="h5">Your Profile</Typography> <Typography component="h5" variant="h5">{t("Your Profile")}</Typography>
<List> <List>
<Divider/> <Divider/>
<ListItem className="profileNickname"> <ListItem className="profileNickname">
<ListItemText secondary="Your robot"> <ListItemText secondary={t("Your robot")}>
<Typography component="h6" variant="h6"> <Typography component="h6" variant="h6">
{this.props.nickname ? {this.props.nickname ?
<div style={{position:'relative',left:'-7px'}}> <div style={{position:'relative',left:'-7px'}}>
@ -326,12 +336,12 @@ class BottomBar extends Component {
<NumbersIcon color="primary"/> <NumbersIcon color="primary"/>
</Badge> </Badge>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={'One active order #'+this.state.active_order_id} secondary="Your current order"/> <ListItemText primary={t("One active order #{{orderID}}",{orderID: this.state.active_order_id})} secondary={t("Your current order")}/>
</ListItemButton> </ListItemButton>
: :
<ListItem> <ListItem>
<ListItemIcon><NumbersIcon/></ListItemIcon> <ListItemIcon><NumbersIcon/></ListItemIcon>
<ListItemText primary="No active orders" secondary="Your current order"/> <ListItemText primary={t("No active orders")} secondary={t("Your current order")}/>
</ListItem> </ListItem>
} }
@ -339,17 +349,17 @@ class BottomBar extends Component {
<ListItemIcon> <ListItemIcon>
<PasswordIcon/> <PasswordIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText secondary="Your token (will not remain here)"> <ListItemText secondary={t("Your token (will not remain here)")}>
{this.props.token ? {this.props.token ?
<TextField <TextField
disabled disabled
label='Back it up!' label={t("Back it up!")}
value={this.props.token } value={this.props.token }
variant='filled' variant='filled'
size='small' size='small'
InputProps={{ InputProps={{
endAdornment: endAdornment:
<Tooltip disableHoverListener enterTouchDelay="0" title="Copied!"> <Tooltip disableHoverListener enterTouchDelay="0" title={t("Copied!")}>
<IconButton onClick= {()=>navigator.clipboard.writeText(this.props.token)}> <IconButton onClick= {()=>navigator.clipboard.writeText(this.props.token)}>
<ContentCopy /> <ContentCopy />
</IconButton> </IconButton>
@ -357,7 +367,7 @@ class BottomBar extends Component {
}} }}
/> />
: :
'Cannot remember'} t("Cannot remember")}
</ListItemText> </ListItemText>
</ListItem> </ListItem>
@ -368,7 +378,7 @@ class BottomBar extends Component {
<Switch <Switch
checked={this.state.showRewards} checked={this.state.showRewards}
onChange={()=> this.setState({showRewards: !this.state.showRewards})}/>} onChange={()=> this.setState({showRewards: !this.state.showRewards})}/>}
label="Rewards and compensations" label={t("Rewards and compensations")}
/> />
</Grid> </Grid>
@ -377,15 +387,14 @@ class BottomBar extends Component {
<ListItemIcon> <ListItemIcon>
<PersonAddAltIcon/> <PersonAddAltIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText secondary="Share to earn 100 Sats per trade"> <ListItemText secondary={t("Share to earn 100 Sats per trade")}>
<TextField <TextField
label='Your referral link' label={t("Your referral link")}
value={this.getHost()+'/ref/'+this.state.referral_code} value={this.getHost()+'/ref/'+this.state.referral_code}
// variant='filled'
size='small' size='small'
InputProps={{ InputProps={{
endAdornment: endAdornment:
<Tooltip disableHoverListener enterTouchDelay="0" title="Copied!"> <Tooltip disableHoverListener enterTouchDelay="0" title={t("Copied!")}>
<IconButton onClick= {()=>navigator.clipboard.writeText('http://'+this.getHost()+'/ref/'+this.state.referral_code)}> <IconButton onClick= {()=>navigator.clipboard.writeText('http://'+this.getHost()+'/ref/'+this.state.referral_code)}>
<ContentCopy /> <ContentCopy />
</IconButton> </IconButton>
@ -400,13 +409,13 @@ class BottomBar extends Component {
<EmojiEventsIcon/> <EmojiEventsIcon/>
</ListItemIcon> </ListItemIcon>
{!this.state.openClaimRewards ? {!this.state.openClaimRewards ?
<ListItemText secondary="Your earned rewards"> <ListItemText secondary={t("Your earned rewards")}>
<Grid container xs={12}> <Grid container xs={12}>
<Grid item xs={9}> <Grid item xs={9}>
<Typography>{this.state.earned_rewards+" Sats"}</Typography> <Typography>{this.state.earned_rewards+" Sats"}</Typography>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<Button disabled={this.state.earned_rewards==0? true : false} onClick={() => this.setState({openClaimRewards:true})} variant="contained" size="small">Claim</Button> <Button disabled={this.state.earned_rewards==0? true : false} onClick={() => this.setState({openClaimRewards:true})} variant="contained" size="small">{t("Claim")}</Button>
</Grid> </Grid>
</Grid> </Grid>
</ListItemText> </ListItemText>
@ -417,8 +426,7 @@ class BottomBar extends Component {
<TextField <TextField
error={this.state.badInvoice} error={this.state.badInvoice}
helperText={this.state.badInvoice ? this.state.badInvoice : "" } helperText={this.state.badInvoice ? this.state.badInvoice : "" }
label={"Invoice for " + this.state.earned_rewards + " Sats"} label={t("Invoice for {{amountSats}} Sats", {amountSats: this.state.earned_rewards})}
//variant="standard"
size="small" size="small"
value={this.state.rewardInvoice} value={this.state.rewardInvoice}
onChange={e => { onChange={e => {
@ -427,7 +435,7 @@ class BottomBar extends Component {
/> />
</Grid> </Grid>
<Grid item alignItems="stretch" style={{ display: "flex" }}> <Grid item alignItems="stretch" style={{ display: "flex" }}>
<Button sx={{maxHeight:38}} onClick={this.handleSubmitInvoiceClicked} variant="contained" color="primary" size="small" > Submit </Button> <Button sx={{maxHeight:38}} onClick={this.handleSubmitInvoiceClicked} variant="contained" color="primary" size="small">{t("Submit")}</Button>
</Grid> </Grid>
</Grid> </Grid>
</form> </form>
@ -442,7 +450,7 @@ class BottomBar extends Component {
{this.state.withdrawn? {this.state.withdrawn?
<div style={{display: 'flex', justifyContent: 'center'}}> <div style={{display: 'flex', justifyContent: 'center'}}>
<Typography color="primary" variant="body2"><b>There it goes, thank you!🥇</b></Typography> <Typography color="primary" variant="body2"><b>{t("There it goes, thank you!🥇")}</b></Typography>
</div> </div>
:""} :""}
@ -455,6 +463,7 @@ class BottomBar extends Component {
} }
bottomBarDesktop =()=>{ bottomBarDesktop =()=>{
const { t } = this.props;
return( return(
<Paper elevation={6} style={{height:40}}> <Paper elevation={6} style={{height:40}}>
<this.StatsDialog/> <this.StatsDialog/>
@ -466,9 +475,9 @@ bottomBarDesktop =()=>{
<Grid item xs={1.9}> <Grid item xs={1.9}>
<div style={{display: this.props.avatarLoaded ? '':'none'}}> <div style={{display: this.props.avatarLoaded ? '':'none'}}>
<ListItemButton onClick={this.handleClickOpenProfile} > <ListItemButton onClick={this.handleClickOpenProfile} >
<Tooltip open={this.state.earned_rewards > 0 ? true: false} title="You can claim satoshis!"> <Tooltip open={this.state.earned_rewards > 0 ? true: false} title={t("You can claim satoshis!")}>
<Tooltip open={(this.state.active_order_id > 0 & !this.state.profileShown & this.props.avatarLoaded) ? true: false} <Tooltip open={(this.state.active_order_id > 0 & !this.state.profileShown & this.props.avatarLoaded) ? true: false}
title="You have an active order"> title={t("You have an active order")}>
<ListItemAvatar sx={{ width: 30, height: 30 }} > <ListItemAvatar sx={{ width: 30, height: 30 }} >
<Badge badgeContent={(this.state.active_order_id > 0 & !this.state.profileShown) ? "": null} color="primary"> <Badge badgeContent={(this.state.active_order_id > 0 & !this.state.profileShown) ? "": null} color="primary">
<Avatar className='flippedSmallAvatar' sx={{margin: 0, top: -13}} <Avatar className='flippedSmallAvatar' sx={{margin: 0, top: -13}}
@ -496,7 +505,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.num_public_buy_orders} primary={this.state.num_public_buy_orders}
secondary="Public Buy Orders" /> secondary={t("Public Buy Orders")} />
</ListItem> </ListItem>
</Grid> </Grid>
@ -509,7 +518,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.num_public_sell_orders} primary={this.state.num_public_sell_orders}
secondary="Public Sell Orders" /> secondary={t("Public Sell Orders")} />
</ListItem> </ListItem>
</Grid> </Grid>
@ -522,7 +531,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.active_robots_today} primary={this.state.active_robots_today}
secondary="Today Active Robots" /> secondary={t("Today Active Robots")}/>
</ListItem> </ListItem>
</Grid> </Grid>
@ -535,7 +544,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.last_day_nonkyc_btc_premium+"%"} primary={this.state.last_day_nonkyc_btc_premium+"%"}
secondary="24h Avg Premium" /> secondary={t("24h Avg Premium")} />
</ListItem> </ListItem>
</Grid> </Grid>
@ -548,7 +557,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={(this.state.maker_fee + this.state.taker_fee)*100} primary={(this.state.maker_fee + this.state.taker_fee)*100}
secondary="Trade Fee" /> secondary={t("Trade Fee")} />
</ListItem> </ListItem>
</Grid> </Grid>
@ -557,7 +566,7 @@ bottomBarDesktop =()=>{
<this.LangSelect/> <this.LangSelect/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<Tooltip enterTouchDelay="250" title="Show community and support links"> <Tooltip enterTouchDelay="250" title={t("Show community and support links")}>
<IconButton <IconButton
color="primary" color="primary"
aria-label="Community" aria-label="Community"
@ -567,7 +576,7 @@ bottomBarDesktop =()=>{
</Tooltip> </Tooltip>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<Tooltip enterTouchDelay="250" title="Show stats for nerds"> <Tooltip enterTouchDelay="250" title={t("Show stats for nerds")}>
<IconButton color="primary" <IconButton color="primary"
aria-label="Stats for Nerds" aria-label="Stats for Nerds"
onClick={this.handleClickOpenStatsForNerds} > onClick={this.handleClickOpenStatsForNerds} >
@ -614,6 +623,7 @@ bottomBarDesktop =()=>{
}; };
exchangeSummaryDialog =() =>{ exchangeSummaryDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openExchangeSummary} open={this.state.openExchangeSummary}
@ -622,7 +632,7 @@ bottomBarDesktop =()=>{
aria-describedby="exchange-summary-description" aria-describedby="exchange-summary-description"
> >
<DialogContent> <DialogContent>
<Typography component="h5" variant="h5">Exchange Summary</Typography> <Typography component="h5" variant="h5">{t("Exchange Summary")}</Typography>
<List dense> <List dense>
<ListItem > <ListItem >
<ListItemIcon size="small"> <ListItemIcon size="small">
@ -632,7 +642,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.num_public_buy_orders} primary={this.state.num_public_buy_orders}
secondary="Public buy orders" /> secondary={t("Public buy orders")} />
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -644,7 +654,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.num_public_sell_orders} primary={this.state.num_public_sell_orders}
secondary="Public sell orders" /> secondary={t("Public sell orders")} />
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -656,7 +666,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={pn(this.state.book_liquidity)+" Sats"} primary={pn(this.state.book_liquidity)+" Sats"}
secondary="Book liquidity" /> secondary={t("Book liquidity")}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -668,7 +678,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.active_robots_today} primary={this.state.active_robots_today}
secondary="Today active robots" /> secondary={t("Today active robots")} />
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -680,7 +690,7 @@ bottomBarDesktop =()=>{
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
primary={this.state.last_day_nonkyc_btc_premium+"%"} primary={this.state.last_day_nonkyc_btc_premium+"%"}
secondary="24h non-KYC average premium" /> secondary={t("24h non-KYC bitcoin premium")} />
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -693,7 +703,7 @@ bottomBarDesktop =()=>{
<ListItemText <ListItemText
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
secondary="Maker fee"> secondary={t("Maker fee")}>
{(this.state.maker_fee*100).toFixed(3)}% {(this.state.maker_fee*100).toFixed(3)}%
</ListItemText> </ListItemText>
</Grid> </Grid>
@ -701,7 +711,7 @@ bottomBarDesktop =()=>{
<ListItemText <ListItemText
primaryTypographyProps={{fontSize: '14px'}} primaryTypographyProps={{fontSize: '14px'}}
secondaryTypographyProps={{fontSize: '12px'}} secondaryTypographyProps={{fontSize: '12px'}}
secondary="Taker fee"> secondary={t("Taker fee")}>
{(this.state.taker_fee*100).toFixed(3)}% {(this.state.taker_fee*100).toFixed(3)}%
</ListItemText> </ListItemText>
</Grid> </Grid>
@ -715,6 +725,7 @@ bottomBarDesktop =()=>{
} }
bottomBarPhone =()=>{ bottomBarPhone =()=>{
const { t } = this.props;
return( return(
<Paper elevation={6} style={{height:40}}> <Paper elevation={6} style={{height:40}}>
<this.StatsDialog/> <this.StatsDialog/>
@ -725,9 +736,9 @@ bottomBarPhone =()=>{
<Grid item xs={1.6}> <Grid item xs={1.6}>
<div style={{display: this.props.avatarLoaded ? '':'none'}}> <div style={{display: this.props.avatarLoaded ? '':'none'}}>
<Tooltip open={this.state.earned_rewards > 0 ? true: false} title="You can claim satoshis!"> <Tooltip open={this.state.earned_rewards > 0 ? true: false} title={t("You can claim satoshis!")}>
<Tooltip open={(this.state.active_order_id > 0 & !this.state.profileShown & this.props.avatarLoaded) ? true: false} <Tooltip open={(this.state.active_order_id > 0 & !this.state.profileShown & this.props.avatarLoaded) ? true: false}
title="You have an active order"> title={t("You have an active order")}>
<IconButton onClick={this.handleClickOpenProfile} sx={{margin: 0, bottom: 17, right: 8}} > <IconButton onClick={this.handleClickOpenProfile} sx={{margin: 0, bottom: 17, right: 8}} >
<Badge badgeContent={(this.state.active_order_id >0 & !this.state.profileShown) ? "": null} color="primary"> <Badge badgeContent={(this.state.active_order_id >0 & !this.state.profileShown) ? "": null} color="primary">
<Avatar className='phoneFlippedSmallAvatar' <Avatar className='phoneFlippedSmallAvatar'
@ -746,7 +757,7 @@ bottomBarPhone =()=>{
</Grid> </Grid>
<Grid item xs={1.6} align="center"> <Grid item xs={1.6} align="center">
<Tooltip enterTouchDelay="300" title="Number of public BUY orders"> <Tooltip enterTouchDelay="300" title={t("Number of public BUY orders")}>
<IconButton onClick={this.handleClickOpenExchangeSummary} > <IconButton onClick={this.handleClickOpenExchangeSummary} >
<Badge badgeContent={this.state.num_public_buy_orders} color="action"> <Badge badgeContent={this.state.num_public_buy_orders} color="action">
<InventoryIcon /> <InventoryIcon />
@ -756,7 +767,7 @@ bottomBarPhone =()=>{
</Grid> </Grid>
<Grid item xs={1.6} align="center"> <Grid item xs={1.6} align="center">
<Tooltip enterTouchDelay="300" title="Number of public SELL orders"> <Tooltip enterTouchDelay="300" title={t("Number of public SELL orders")}>
<IconButton onClick={this.handleClickOpenExchangeSummary} > <IconButton onClick={this.handleClickOpenExchangeSummary} >
<Badge badgeContent={this.state.num_public_sell_orders} color="action"> <Badge badgeContent={this.state.num_public_sell_orders} color="action">
<SellIcon /> <SellIcon />
@ -766,7 +777,7 @@ bottomBarPhone =()=>{
</Grid> </Grid>
<Grid item xs={1.6} align="center"> <Grid item xs={1.6} align="center">
<Tooltip enterTouchDelay="300" title="Today active robots"> <Tooltip enterTouchDelay="300" title={t("Today active robots")}>
<IconButton onClick={this.handleClickOpenExchangeSummary} > <IconButton onClick={this.handleClickOpenExchangeSummary} >
<Badge badgeContent={this.state.active_robots_today} color="action"> <Badge badgeContent={this.state.active_robots_today} color="action">
<SmartToyIcon /> <SmartToyIcon />
@ -776,7 +787,7 @@ bottomBarPhone =()=>{
</Grid> </Grid>
<Grid item xs={1.8} align="center"> <Grid item xs={1.8} align="center">
<Tooltip enterTouchDelay="300" title="24h non-KYC bitcoin premium"> <Tooltip enterTouchDelay="300" title={t("24h non-KYC bitcoin premium")}>
<IconButton onClick={this.handleClickOpenExchangeSummary} > <IconButton onClick={this.handleClickOpenExchangeSummary} >
<Badge badgeContent={this.state.last_day_nonkyc_btc_premium+"%"} color="action"> <Badge badgeContent={this.state.last_day_nonkyc_btc_premium+"%"} color="action">
<PriceChangeIcon /> <PriceChangeIcon />
@ -790,7 +801,7 @@ bottomBarPhone =()=>{
<this.LangSelect/> <this.LangSelect/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<Tooltip enterTouchDelay="250" title="Show community and support links"> <Tooltip enterTouchDelay="250" title={t("Show community and support links")}>
<IconButton <IconButton
color="primary" color="primary"
aria-label="Community" aria-label="Community"
@ -800,7 +811,7 @@ bottomBarPhone =()=>{
</Tooltip> </Tooltip>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<Tooltip enterTouchDelay="250" title="Show stats for nerds"> <Tooltip enterTouchDelay="250" title={t("Show stats for nerds")}>
<IconButton color="primary" <IconButton color="primary"
aria-label="Stats for Nerds" aria-label="Stats for Nerds"
onClick={this.handleClickOpenStatsForNerds} > onClick={this.handleClickOpenStatsForNerds} >

View File

@ -6,6 +6,7 @@ import MediaQuery from 'react-responsive'
class InfoDialog extends Component { class InfoDialog extends Component {
render() { render() {
const { t } = this.props;
return ( return (
<div> <div>
<DialogContent> <DialogContent>
@ -13,13 +14,13 @@ class InfoDialog extends Component {
<MediaQuery minWidth={475}> <MediaQuery minWidth={475}>
<Grid container xs={12}> <Grid container xs={12}>
<Grid item xs={8}> <Grid item xs={8}>
<Typography component="h4" variant="h4">What is <i>RoboSats</i>?</Typography> <Typography component="h4" variant="h4">{t("What is <RoboSats?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p>It is a BTC/FIAT peer-to-peer exchange over lightning. <br/> It simplifies <p>{t("It is a BTC/FIAT peer-to-peer exchange over lightning.")} <br/>
matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.</p> {t("It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.")}</p>
<p>RoboSats is an open source project <Link <p>{t("RoboSats is an open source project ")} <Link
href='https://github.com/reckless-satoshi/robosats'>(GitHub).</Link> href='https://github.com/reckless-satoshi/robosats'>{t("(GitHub).")}</Link>
</p> </p>
</Typography> </Typography>
</Grid> </Grid>
@ -35,127 +36,75 @@ class InfoDialog extends Component {
</MediaQuery> </MediaQuery>
<MediaQuery maxWidth={474}> <MediaQuery maxWidth={474}>
<Typography component="h4" variant="h4">What is <i>RoboSats</i>?</Typography> <Typography component="h4" variant="h4">{t("What is RoboSats?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p>It is a BTC/FIAT peer-to-peer exchange over lightning. It simplifies <p>{t("It is a BTC/FIAT peer-to-peer exchange over lightning.")+" "} {t("It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.")}</p>
matchmaking and minimizes the need for trust. RoboSats focuses in privacy and speed.</p>
<img <img
width='100%' width='100%'
src={window.location.origin +'/static/assets/images/robosats_0.1.0_banner.png'} src={window.location.origin +'/static/assets/images/robosats_0.1.0_banner.png'}
/> />
<p>RoboSats is an open source project <Link <p>{t("RoboSats is an open source project")} <Link
href='https://github.com/reckless-satoshi/robosats'>(GitHub).</Link> href='https://github.com/reckless-satoshi/robosats'>{t("(GitHub).")}</Link>
</p> </p>
</Typography> </Typography>
</MediaQuery> </MediaQuery>
<Typography component="h5" variant="h5">How does it work?</Typography> <Typography component="h5" variant="h5">{t("How does it work?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> AnonymousAlice01 wants to sell bitcoin. She posts a sell order. <p> {t("AnonymousAlice01 wants to sell bitcoin. She posts a sell order. BafflingBob02 wants to buy bitcoin and he takes Alice's order. Both have to post a small bond using lightning to prove they are real robots. Then, Alice posts the trade collateral also using a lightning hold invoice. RoboSats locks the invoice until Alice confirms she received the fiat, then the satoshis are released to Bob. Enjoy your satoshis, Bob!")}</p>
BafflingBob02 wants to buy bitcoin and he takes Alice's order.
Both have to post a small bond using lightning to prove they are real
robots. Then, Alice posts the trade collateral also using a lightning
hold invoice. <i>RoboSats</i> locks the invoice until Alice confirms she
received the fiat, then the satoshis are released to Bob. Enjoy your satoshis,
Bob!</p>
<p>At no point, AnonymousAlice01 and BafflingBob02 have to entrust the <p>{t("At no point, AnonymousAlice01 and BafflingBob02 have to entrust the bitcoin funds to each other. In case they have a conflict, RoboSats staff will help resolving the dispute.")}
bitcoin funds to each other. In case they have a conflict, <i>RoboSats</i> staff {t("You can find a step-by-step description of the trade pipeline in ")}
will help resolving the dispute. You can find a step-by-step <Link href='https://github.com/Reckless-Satoshi/robosats/blob/main/README.md#how-it-works'>{t("How it works")}</Link>
description of the trade pipeline in <Link href='https://github.com/Reckless-Satoshi/robosats/blob/main/README.md#how-it-works'>How it works</Link> {t("You can also check the full guide in ")}
You can also check the full guide in <Link href='https://github.com/Reckless-Satoshi/robosats/blob/main/docs/how-to-use.md'>How to use</Link></p> <Link href='https://github.com/Reckless-Satoshi/robosats/blob/main/docs/how-to-use.md'>{t("How to use")}</Link></p>
</Typography> </Typography>
<Typography component="h5" variant="h5">What payment methods are accepted?</Typography> <Typography component="h5" variant="h5">{t("What payment methods are accepted?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p>Basically all of them as long as they are fast. You can write down your preferred payment <p>{t("All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.")} </p>
method(s). You will have to match with a peer who also accepts that method. The step to
exchange fiat has a expiry time of 24 hours before a dispute is automatically
open. We highly recommend using instant fiat payment rails. </p>
</Typography> </Typography>
<Typography component="h5" variant="h5">Are there trade limits?</Typography> <Typography component="h5" variant="h5">{t("Are there trade limits?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p>Maximum single trade size is 800,000 Satoshis to minimize lightning <p>{t("Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).", {maxAmount: '800,000'})} </p>
routing failure. There is no limits to the number of trades per day. A robot
can only have one order at a time. However, you can use multiple
robots simultaneously in different browsers (remember to back up your robot tokens!). </p>
</Typography> </Typography>
<Typography component="h5" variant="h5">Is <i>RoboSats</i> private?</Typography> <Typography component="h5" variant="h5">{t("Is RoboSats private?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> RoboSats will never ask you for your name, country or ID. RoboSats does <p> {t("RoboSats will never ask you for your name, country or ID. RoboSats does not custody your funds and does not care who you are. RoboSats does not collect or custody any personal data. For best anonymity use Tor Browser and access the .onion hidden service.")} </p>
not custody your funds, and doesn't care who you are. For best anonymity <p>{t("Your trading peer is the only one who can potentially guess anything about you. Keep your chat short and concise. Avoid providing non-essential information other than strictly necessary for the fiat payment.")} </p>
use Tor Browser and access the .onion hidden service. </p>
<p>Your trading peer is the only one who can potentially guess
anything about you. Keep your chat short and concise. Avoid
providing non-essential information other than strictly necessary
for the fiat payment. </p>
</Typography> </Typography>
<Typography component="h5" variant="h5">What are the risks?</Typography> <Typography component="h5" variant="h5">{t("What are the risks?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> This is an experimental application, things could go wrong. <p> {t("This is an experimental application, things could go wrong. Trade small amounts!")}</p>
Trade small amounts! </p> <p> {t("The seller faces the same charge-back risk as with any other peer-to-peer service. Paypal or credit cards are not recommended.")}</p>
<p>The seller faces the same charge-back risk as with any
other peer-to-peer service. Paypal or credit cards are
not recommended.</p>
</Typography> </Typography>
<Typography component="h5" variant="h5">What is the trust model?</Typography> <Typography component="h5" variant="h5">{t("What is the trust model?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> The buyer and the seller never have to trust each other. <p> {t("The buyer and the seller never have to trust each other. Some trust on RoboSats is needed since linking the seller's hold invoice and buyer payment is not atomic (yet). In addition, disputes are solved by the RoboSats staff.")}</p>
Some trust on <i>RoboSats</i> is needed since linking the <p> {t("To be totally clear. Trust requirements are minimized. However, there is still one way RoboSats could run away with your satoshis: by not releasing the satoshis to the buyer. It could be argued that such move is not in RoboSats' interest as it would damage the reputation for a small payout. However, you should hesitate and only trade small quantities at a time. For large amounts use an onchain escrow service such as Bisq")}</p>
seller's hold invoice and buyer payment is not atomic (yet). <p> {t("You can build more trust on RoboSats by inspecting the source code.")} <Link href='https://github.com/reckless-satoshi/robosats'> {t("Project source code")} </Link> </p>
In addition, disputes are solved by the <i>RoboSats</i> staff.
</p>
<p> To be totally clear. Trust requirements are minimized. However, there is still
one way <i>RoboSats </i> could run away with your satoshis: by not releasing
the satoshis to the buyer. It could be argued that such move is not in <i>RoboSats' </i>
interest as it would damage the reputation for a small payout.
However, you should hesitate and only trade small quantities at a
time. For large amounts use an onchain escrow service such as <i>Bisq</i>
</p>
<p> You can build more trust on <i>RoboSats</i> by <Link href='https://github.com/reckless-satoshi/robosats'>
inspecting the source code. </Link> </p>
</Typography> </Typography>
<Typography component="h5" variant="h5">What happens if <i>RoboSats</i> suddenly disappears?</Typography> <Typography component="h5" variant="h5">{t("What happens if RoboSats suddenly disappears?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> Your sats will return to you. Any hold invoice that is not <p> {t("Your sats will return to you. Any hold invoice that is not settled would be automatically returned even if RoboSats goes down forever. This is true for both, locked bonds and trading escrows. However, there is a small window between the seller confirms FIAT RECEIVED and the moment the buyer receives the satoshis when the funds could be permanently lost if RoboSats disappears. This window is about 1 second long. Make sure to have enough inbound liquidity to avoid routing failures. If you have any problem, reach out trough the RoboSats public channels.")}</p>
settled would be automatically returned even if <i>RoboSats</i> goes down
forever. This is true for both, locked bonds and trading escrows. However,
there is a small window between the seller confirms FIAT RECEIVED and the moment
the buyer receives the satoshis when the funds could be permanently lost if
<i> RoboSats</i> disappears. This window is about 1 second long. Make sure to have enough
inbound liquidity to avoid routing failures. If you have any problem, reach out
trough the <i>RoboSats</i> public channels.
</p>
</Typography> </Typography>
<Typography component="h5" variant="h5">Is <i>RoboSats</i> legal in my country?</Typography> <Typography component="h5" variant="h5">{t("Is RoboSats legal in my country?")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> In many countries using <i>RoboSats</i> is no different than using Ebay <p> {t("In many countries using RoboSats is no different than using Ebay or Craiglist. Your regulation may vary. It is your responsibility to comply.")}</p>
or Craiglist. Your regulation may vary. It is your responsibility
to comply.
</p>
</Typography> </Typography>
<Typography component="h5" variant="h5">Disclaimer</Typography> <Typography component="h5" variant="h5">{t("Disclaimer")}</Typography>
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p> This lightning application is provided as is. It is in active <p> {t("This lightning application is provided as is. It is in active development: trade with the utmost caution. There is no private support. Support is only offered via public channels ")}<Link href='https://t.me/robosats'>{t("(Telegram)")}</Link>{t(". RoboSats will never contact you. RoboSats will definitely never ask for your robot token.")}</p>
development: trade with the utmost caution. There is no private
support. Support is only offered via public channels <Link href='https://t.me/robosats'>
(Telegram)</Link>. <i>RoboSats</i> will never contact you. <i>
RoboSats</i> will definitely never ask for your robot token.
</p>
</Typography> </Typography>
<DialogActions> <DialogActions>
<Button onClick={this.props.handleCloseInfo}>Close</Button> <Button onClick={this.props.handleCloseInfo}>{t("Close")}</Button>
</DialogActions> </DialogActions>
</DialogContent> </DialogContent>
</div> </div>

View File

@ -1,22 +1,21 @@
import i18n from "i18next"; import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector"; import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next"; import { initReactI18next } from "react-i18next";
import XHR from "i18next-xhr-backend"; import HttpApi from 'i18next-http-backend';
import translationEN from "./locales/en/translation.json"; import translationEN from "./locales/en.json";
import translationES from "./locales/es/translation.json"; import translationES from "./locales/es.json";
import translationDE from "./locales/de/translation.json"; import translationDE from "./locales/de.json";
import translationRU from "./locales/ru/translation.json"; import translationRU from "./locales/ru.json";
import translationCN from "./locales/cn/translation.json"; import translationCN from "./locales/cn.json";
i18n i18n
.use(XHR) .use(HttpApi)
.use(LanguageDetector) .use(LanguageDetector)
.use(initReactI18next) .use(initReactI18next)
.init({ .init({
resources: { resources: {
en: {translations: translationEN}, en: {translations: translationEN},
'en-US': {translations: translationEN},
es: {translations: translationES}, es: {translations: translationES},
ru: {translations: translationRU}, ru: {translations: translationRU},
de: {translations: translationDE}, de: {translations: translationDE},

View File

@ -5,6 +5,7 @@
"phone_unsafe_alert": "You will not be able to complete a trade. Use <1>Tor Browser</1> and visit the <3>Onion</3> site.", "phone_unsafe_alert": "You will not be able to complete a trade. Use <1>Tor Browser</1> and visit the <3>Onion</3> site.",
"Hide":"Hide", "Hide":"Hide",
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation", "USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
"Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange", "Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange",
"This is your trading avatar":"This is your trading avatar", "This is your trading avatar":"This is your trading avatar",
@ -18,6 +19,7 @@
"Info":"Info", "Info":"Info",
"View Book":"View Book", "View Book":"View Book",
"MAKER PAGE - MakerPage.js": "This is the page where users can create new orders", "MAKER PAGE - MakerPage.js": "This is the page where users can create new orders",
"Order":"Order", "Order":"Order",
"Customize":"Customize", "Customize":"Customize",
@ -63,6 +65,92 @@
"Must be less than {{maxSats}": "Must be less than {{maxSats}}", "Must be less than {{maxSats}": "Must be less than {{maxSats}}",
"Must be more than {{minSats}}": "Must be more than {{minSats}}", "Must be more than {{minSats}}": "Must be more than {{minSats}}",
"BOOK PAGE - BookPage.js":"The Book Order page",
"Seller":"Seller",
"Buyer":"Buyer",
"I want to":"I want to",
"Select Order Type":"Select Order Type",
"ANY_type":"ANY",
"ANY_currency":"ANY",
"BUY":"BUY",
"SELL":"SELL",
"and receive":"and receive",
"and pay with":"and pay with",
"and use":"and use",
"Select Payment Currency":"Select Payment Currency",
"🌍 ANY":"🌍 ANY",
"Robot":"Robot",
"Is":"Is",
"Currency":"Currency",
"Payment Method":"Payment Method",
"Price":"Price",
"Premium":"Premium",
"You are SELLING BTC for {{currencyCode}}":"You are SELLING BTC for {{currencyCode}}",
"You are BUYING BTC for {{currencyCode}}":"You are BUYING BTC for {{currencyCode}}",
"You are looking at all":"You are looking at all",
"No orders found to sell BTC for {{currencyCode}}":"No orders found to sell BTC for {{currencyCode}}",
"No orders found to buy BTC for {{currencyCode}}":"No orders found to buy BTC for {{currencyCode}}",
"Be the first one to create an order":"Be the first one to create an order",
"BOTTOM BAR AND MISC - BottomBar.js":"Bottom Bar user profile and miscelaneous dialogs",
"Stats For Nerds":"Stats For Nerds",
"LND version":"LND version",
"Currently running commit hash":"Currently running commit hash",
"24h contracted volume":"24h contracted volume",
"Lifetime contracted volume":"Lifetime contracted volume",
"Made with":"Made with",
"and":"and",
"... somewhere on Earth!":"... somewhere on Earth!",
"Community":"Community",
"Support is only offered via public channels. Join our Telegram community if you have questions or want to hang out with other cool robots. Please, use our Github Issues if you find a bug or want to see new features!":"Support is only offered via public channels. Join our Telegram community if you have questions or want to hang out with other cool robots. Please, use our Github Issues if you find a bug or want to see new features!",
"Join the RoboSats group":"Join the RoboSats group",
"Telegram (English / Main)":"Telegram (English / Main)",
"RoboSats Telegram Communities":"RoboSats Telegram Communities",
"Join RoboSats Spanish speaking community!":"Join RoboSats Spanish speaking community!",
"Join RoboSats Russian speaking community!":"Join RoboSats Russian speaking community!",
"Join RoboSats Chinesse speaking community!":"Join RoboSats Chinesse speaking community!",
"Join RoboSats English speaking community!":"Join RoboSats English speaking community!",
"Tell us about a new feature or a bug":"Tell us about a new feature or a bug",
"Github Issues - The Robotic Satoshis Open Source Project":"Github Issues - The Robotic Satoshis Open Source Project",
"Your Profile":"Your Profile",
"Your robot":"Your robot",
"One active order #{{orderID}}":"One active order #{{orderID}}",
"Your current order":"Your current order",
"No active orders":"No active orders",
"Your token (will not remain here)":"Your token (will not remain here)",
"Back it up!":"Back it up!",
"Cannot remember":"Cannot remember",
"Rewards and compensations":"Rewards and compensations",
"Share to earn 100 Sats per trade":"Share to earn 100 Sats per trade",
"Your referral link":"Your referral link",
"Your earned rewards":"Your earned rewards",
"Claim":"Claim",
"Invoice for {{amountSats}} Sats":"Invoice for {{amountSats}} Sats",
"Submit":"Submit",
"There it goes, thank you!🥇":"There it goes, thank you!🥇",
"You have an active order":"You have an active order",
"You can claim satoshis!":"You can claim satoshis!",
"Public Buy Orders":"Public Buy Orders",
"Public Sell Orders":"Public Sell Orders",
"Today Active Robots":"Today Active Robots",
"24h Avg Premium":"24h Avg Premium",
"Trade Fee":"Trade Fee",
"Show community and support links":"Show community and support links",
"Show stats for nerds":"Show stats for nerds",
"Exchange Summary":"Exchange Summary",
"Public buy orders":"Public buy orders",
"Public sell orders":"Public sell orders",
"Book liquidity":"Book liquidity",
"Today active robots":"Today active robots",
"24h non-KYC bitcoin premium":"24h non-KYC bitcoin premium",
"Maker fee":"Maker fee",
"Taker fee":"Taker fee",
"Number of public BUY orders":"Number of public BUY orders",
"Number of public SELL orders":"Number of public SELL orders",
"ORDER PAGE - OrderPage.js": "Order details page", "ORDER PAGE - OrderPage.js": "Order details page",
"Order Box":"Order Box", "Order Box":"Order Box",
"Contract":"Contract", "Contract":"Contract",
@ -125,6 +213,7 @@
"Cancel":"Cancel", "Cancel":"Cancel",
"Collaborative Cancel":"Collaborative Cancel", "Collaborative Cancel":"Collaborative Cancel",
"CHAT BOX - Chat.js":"Chat Box", "CHAT BOX - Chat.js":"Chat Box",
"You":"You", "You":"You",
"Peer":"Peer", "Peer":"Peer",
@ -135,9 +224,6 @@
"Send":"Send", "Send":"Send",
"The chat has no memory: if you leave, messages are lost.":"The chat has no memory: if you leave, messages are lost.", "The chat has no memory: if you leave, messages are lost.":"The chat has no memory: if you leave, messages are lost.",
"Learn easy PGP encryption.":"Learn easy PGP encryption.", "Learn easy PGP encryption.":"Learn easy PGP encryption.",
"CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline", "CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline",
"Contract Box":"Contract Box", "Contract Box":"Contract Box",
@ -220,6 +306,42 @@
"You have won the dispute":"You have won the dispute", "You have won the dispute":"You have won the dispute",
"You can claim the dispute resolution amount (escrow and fidelity bond) from your profile rewards. If there is anything the staff can help with, do not hesitate to contact to robosats@protonmail.com (or via your provided burner contact method).":"You can claim the dispute resolution amount (escrow and fidelity bond) from your profile rewards. If there is anything the staff can help with, do not hesitate to contact to robosats@protonmail.com (or via your provided burner contact method).", "You can claim the dispute resolution amount (escrow and fidelity bond) from your profile rewards. If there is anything the staff can help with, do not hesitate to contact to robosats@protonmail.com (or via your provided burner contact method).":"You can claim the dispute resolution amount (escrow and fidelity bond) from your profile rewards. If there is anything the staff can help with, do not hesitate to contact to robosats@protonmail.com (or via your provided burner contact method).",
"You have lost the dispute":"You have lost the dispute", "You have lost the dispute":"You have lost the dispute",
"Unfortunately you have lost the dispute. If you think this is a mistake you can ask to re-open the case via email to robosats@protonmail.com. However, chances of it being investigated again are low.":"Unfortunately you have lost the dispute. If you think this is a mistake you can ask to re-open the case via email to robosats@protonmail.com. However, chances of it being investigated again are low." "Unfortunately you have lost the dispute. If you think this is a mistake you can ask to re-open the case via email to robosats@protonmail.com. However, chances of it being investigated again are low.":"Unfortunately you have lost the dispute. If you think this is a mistake you can ask to re-open the case via email to robosats@protonmail.com. However, chances of it being investigated again are low.",
"INFO DIALOG - InfoDiagog.js":"App information and clarifications and terms of use",
"Close":"Close",
"What is RoboSats?":"What is <RoboSats?",
"It is a BTC/FIAT peer-to-peer exchange over lightning.":"It is a BTC/FIAT peer-to-peer exchange over lightning.",
"RoboSats is an open source project ":"RoboSats is an open source project ",
"It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.":"It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.",
"(GitHub).":"(GitHub).",
"How does it work?":"How does it work?",
"AnonymousAlice01 wants to sell bitcoin. She posts a sell order. BafflingBob02 wants to buy bitcoin and he takes Alice's order. Both have to post a small bond using lightning to prove they are real robots. Then, Alice posts the trade collateral also using a lightning hold invoice. RoboSats locks the invoice until Alice confirms she received the fiat, then the satoshis are released to Bob. Enjoy your satoshis, Bob!":"AnonymousAlice01 wants to sell bitcoin. She posts a sell order. BafflingBob02 wants to buy bitcoin and he takes Alice's order. Both have to post a small bond using lightning to prove they are real robots. Then, Alice posts the trade collateral also using a lightning hold invoice. RoboSats locks the invoice until Alice confirms she received the fiat, then the satoshis are released to Bob. Enjoy your satoshis, Bob!",
"At no point, AnonymousAlice01 and BafflingBob02 have to entrust the bitcoin funds to each other. In case they have a conflict, RoboSats staff will help resolving the dispute.":"At no point, AnonymousAlice01 and BafflingBob02 have to entrust the bitcoin funds to each other. In case they have a conflict, RoboSats staff will help resolving the dispute.",
"You can find a step-by-step description of the trade pipeline in ":"You can find a step-by-step description of the trade pipeline in ",
"How it works":"How it works",
"You can also check the full guide in ":"You can also check the full guide in ",
"How to use":"How to use",
"What payment methods are accepted?":"What payment methods are accepted?",
"All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.":"All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.",
"Are there trade limits?":"Are there trade limits?",
"Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).":"Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).",
"Is RoboSats private?":"Is RoboSats private?",
"RoboSats will never ask you for your name, country or ID. RoboSats does not custody your funds and does not care who you are. RoboSats does not collect or custody any personal data. For best anonymity use Tor Browser and access the .onion hidden service.":"RoboSats will never ask you for your name, country or ID. RoboSats does not custody your funds and does not care who you are. RoboSats does not collect or custody any personal data. For best anonymity use Tor Browser and access the .onion hidden service.",
"Your trading peer is the only one who can potentially guess anything about you. Keep your chat short and concise. Avoid providing non-essential information other than strictly necessary for the fiat payment.":"Your trading peer is the only one who can potentially guess anything about you. Keep your chat short and concise. Avoid providing non-essential information other than strictly necessary for the fiat payment.",
"What are the risks?":"What are the risks?",
"This is an experimental application, things could go wrong. Trade small amounts!":"This is an experimental application, things could go wrong. Trade small amounts!",
"The seller faces the same charge-back risk as with any other peer-to-peer service. Paypal or credit cards are not recommended.":"The seller faces the same charge-back risk as with any other peer-to-peer service. Paypal or credit cards are not recommended.",
"What is the trust model?":"What is the trust model?",
"The buyer and the seller never have to trust each other. Some trust on RoboSats is needed since linking the seller's hold invoice and buyer payment is not atomic (yet). In addition, disputes are solved by the RoboSats staff.":"The buyer and the seller never have to trust each other. Some trust on RoboSats is needed since linking the seller's hold invoice and buyer payment is not atomic (yet). In addition, disputes are solved by the RoboSats staff.",
"To be totally clear. Trust requirements are minimized. However, there is still one way RoboSats could run away with your satoshis: by not releasing the satoshis to the buyer. It could be argued that such move is not in RoboSats' interest as it would damage the reputation for a small payout. However, you should hesitate and only trade small quantities at a time. For large amounts use an onchain escrow service such as Bisq":"To be totally clear. Trust requirements are minimized. However, there is still one way RoboSats could run away with your satoshis: by not releasing the satoshis to the buyer. It could be argued that such move is not in RoboSats' interest as it would damage the reputation for a small payout. However, you should hesitate and only trade small quantities at a time. For large amounts use an onchain escrow service such as Bisq",
"You can build more trust on RoboSats by inspecting the source code.":"You can build more trust on RoboSats by inspecting the source code.",
"What happens if RoboSats suddenly disappears?":"What happens if RoboSats suddenly disappears?",
"Your sats will return to you. Any hold invoice that is not settled would be automatically returned even if RoboSats goes down forever. This is true for both, locked bonds and trading escrows. However, there is a small window between the seller confirms FIAT RECEIVED and the moment the buyer receives the satoshis when the funds could be permanently lost if RoboSats disappears. This window is about 1 second long. Make sure to have enough inbound liquidity to avoid routing failures. If you have any problem, reach out trough the RoboSats public channels.":"Your sats will return to you. Any hold invoice that is not settled would be automatically returned even if RoboSats goes down forever. This is true for both, locked bonds and trading escrows. However, there is a small window between the seller confirms FIAT RECEIVED and the moment the buyer receives the satoshis when the funds could be permanently lost if RoboSats disappears. This window is about 1 second long. Make sure to have enough inbound liquidity to avoid routing failures. If you have any problem, reach out trough the RoboSats public channels.",
"In many countries using RoboSats is no different than using Ebay or Craiglist. Your regulation may vary. It is your responsibility to comply.":"In many countries using RoboSats is no different than using Ebay or Craiglist. Your regulation may vary. It is your responsibility to comply.",
"Is RoboSats legal in my country?":"Is RoboSats legal in my country?",
"Disclaimer":"Disclaimer",
"This lightning application is provided as is. It is in active development: trade with the utmost caution. There is no private support. Support is only offered via public channels ":"This lightning application is provided as is. It is in active development: trade with the utmost caution. There is no private support. Support is only offered via public channels ",
"(Telegram)":"(Telegram)",
". RoboSats will never contact you. RoboSats will definitely never ask for your robot token.":". RoboSats will never contact you. RoboSats will definitely never ask for your robot token."
} }

File diff suppressed because one or more lines are too long

View File

@ -94,6 +94,26 @@
!*** ./src/components/PaymentIcons.js ***! !*** ./src/components/PaymentIcons.js ***!
\****************************************/ \****************************************/
/*!****************************************!*\
!*** ./src/components/locales/cn.json ***!
\****************************************/
/*!****************************************!*\
!*** ./src/components/locales/de.json ***!
\****************************************/
/*!****************************************!*\
!*** ./src/components/locales/en.json ***!
\****************************************/
/*!****************************************!*\
!*** ./src/components/locales/es.json ***!
\****************************************/
/*!****************************************!*\
!*** ./src/components/locales/ru.json ***!
\****************************************/
/*!*****************************************!*\ /*!*****************************************!*\
!*** ./node_modules/react-dom/index.js ***! !*** ./node_modules/react-dom/index.js ***!
\*****************************************/ \*****************************************/
@ -570,26 +590,6 @@
!*** ./src/components/icons/RoboSatsNoTextIcon.js ***! !*** ./src/components/icons/RoboSatsNoTextIcon.js ***!
\****************************************************/ \****************************************************/
/*!****************************************************!*\
!*** ./src/components/locales/cn/translation.json ***!
\****************************************************/
/*!****************************************************!*\
!*** ./src/components/locales/de/translation.json ***!
\****************************************************/
/*!****************************************************!*\
!*** ./src/components/locales/en/translation.json ***!
\****************************************************/
/*!****************************************************!*\
!*** ./src/components/locales/es/translation.json ***!
\****************************************************/
/*!****************************************************!*\
!*** ./src/components/locales/ru/translation.json ***!
\****************************************************/
/*!*****************************************************!*\ /*!*****************************************************!*\
!*** ./node_modules/@mui/icons-material/Article.js ***! !*** ./node_modules/@mui/icons-material/Article.js ***!
\*****************************************************/ \*****************************************************/
@ -1042,6 +1042,14 @@
!*** ./node_modules/date-fns/esm/startOfYear/index.js ***! !*** ./node_modules/date-fns/esm/startOfYear/index.js ***!
\********************************************************/ \********************************************************/
/*!********************************************************!*\
!*** ./node_modules/i18next-http-backend/esm/index.js ***!
\********************************************************/
/*!********************************************************!*\
!*** ./node_modules/i18next-http-backend/esm/utils.js ***!
\********************************************************/
/*!********************************************************!*\ /*!********************************************************!*\
!*** ./node_modules/react-qr-reader/lib/createBlob.js ***! !*** ./node_modules/react-qr-reader/lib/createBlob.js ***!
\********************************************************/ \********************************************************/
@ -1242,6 +1250,10 @@
!*** ./node_modules/@mui/utils/esm/useIsFocusVisible.js ***! !*** ./node_modules/@mui/utils/esm/useIsFocusVisible.js ***!
\**********************************************************/ \**********************************************************/
/*!**********************************************************!*\
!*** ./node_modules/i18next-http-backend/esm/request.js ***!
\**********************************************************/
/*!***********************************************************!*\ /*!***********************************************************!*\
!*** ./node_modules/@babel/runtime/helpers/esm/typeof.js ***! !*** ./node_modules/@babel/runtime/helpers/esm/typeof.js ***!
\***********************************************************/ \***********************************************************/
@ -1358,6 +1370,10 @@
!*** ./node_modules/@popperjs/core/lib/utils/debounce.js ***! !*** ./node_modules/@popperjs/core/lib/utils/debounce.js ***!
\***********************************************************/ \***********************************************************/
/*!***********************************************************!*\
!*** ./node_modules/cross-fetch/dist/browser-ponyfill.js ***!
\***********************************************************/
/*!***********************************************************!*\ /*!***********************************************************!*\
!*** ./node_modules/date-fns/esm/_lib/setUTCDay/index.js ***! !*** ./node_modules/date-fns/esm/_lib/setUTCDay/index.js ***!
\***********************************************************/ \***********************************************************/
@ -1458,6 +1474,10 @@
!*** ./node_modules/date-fns/esm/subMilliseconds/index.js ***! !*** ./node_modules/date-fns/esm/subMilliseconds/index.js ***!
\************************************************************/ \************************************************************/
/*!************************************************************!*\
!*** ./node_modules/i18next-http-backend/esm/getFetch.cjs ***!
\************************************************************/
/*!************************************************************!*\ /*!************************************************************!*\
!*** ./node_modules/tiny-warning/dist/tiny-warning.esm.js ***! !*** ./node_modules/tiny-warning/dist/tiny-warning.esm.js ***!
\************************************************************/ \************************************************************/
@ -2774,10 +2794,6 @@
!*** ./node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js ***! !*** ./node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js ***!
\************************************************************************/ \************************************************************************/
/*!************************************************************************!*\
!*** ./node_modules/i18next-xhr-backend/dist/esm/i18nextXHRBackend.js ***!
\************************************************************************/
/*!*************************************************************************!*\ /*!*************************************************************************!*\
!*** ./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js ***! !*** ./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js ***!
\*************************************************************************/ \*************************************************************************/