Internationalization (#85)

* Implement react i18n-next

* Add XHR i18n backend, include currencies_dict in APP

* Implement i18n 2/9. Add site description

* Implement i18n 3/9 TradeBox. Fix explicit pricing when amount range is enabled.

* Implement i18n 4/9 MakerPage.

* Implement i18n 5/9 OrderPage

* Implement i18n 6/9 Chat

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

* Add Contributing translation guidelines
This commit is contained in:
Reckless_Satoshi 2022-04-05 14:25:53 +00:00 committed by GitHub
parent 083c537700
commit 96c6358d4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 2592 additions and 639 deletions

View File

@ -2657,9 +2657,9 @@
} }
}, },
"ansi-regex": { "ansi-regex": {
"version": "4.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
}, },
"ansi-styles": { "ansi-styles": {
"version": "3.2.1", "version": "3.2.1",
@ -2966,9 +2966,9 @@
} }
}, },
"bplist-parser": { "bplist-parser": {
"version": "0.3.0", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.0.tgz", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
"integrity": "sha512-zgmaRvT6AN1JpPPV+S0a1/FAtoxSreYDccZGIqEMSvZl9DMe70mJ7MFzpxa1X+gHVdkToE2haRUHHMiW1OdejA==", "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
"requires": { "requires": {
"big-integer": "1.6.x" "big-integer": "1.6.x"
} }
@ -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",
@ -3415,14 +3423,15 @@
"integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA=" "integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA="
}, },
"css-select": { "css-select": {
"version": "2.1.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
"integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"requires": { "requires": {
"boolbase": "^1.0.0", "boolbase": "^1.0.0",
"css-what": "^3.2.1", "css-what": "^6.0.1",
"domutils": "^1.7.0", "domhandler": "^4.3.1",
"nth-check": "^1.0.2" "domutils": "^2.8.0",
"nth-check": "^2.0.1"
} }
}, },
"css-tree": { "css-tree": {
@ -3444,9 +3453,9 @@
} }
}, },
"css-what": { "css-what": {
"version": "3.4.2", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
}, },
"csstype": { "csstype": {
"version": "2.6.19", "version": "2.6.19",
@ -3580,33 +3589,36 @@
} }
}, },
"dom-serializer": { "dom-serializer": {
"version": "0.2.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"requires": { "requires": {
"domelementtype": "^2.0.1", "domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0" "entities": "^2.0.0"
},
"dependencies": {
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
}
} }
}, },
"domelementtype": { "domelementtype": {
"version": "1.3.1", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
},
"domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"requires": {
"domelementtype": "^2.2.0"
}
}, },
"domutils": { "domutils": {
"version": "1.7.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"requires": { "requires": {
"dom-serializer": "0", "dom-serializer": "^1.0.1",
"domelementtype": "1" "domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
} }
}, },
"ee-first": { "ee-first": {
@ -4273,6 +4285,19 @@
} }
} }
}, },
"html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="
},
"html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"requires": {
"void-elements": "3.1.0"
}
},
"http-errors": { "http-errors": {
"version": "1.8.1", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
@ -4296,6 +4321,48 @@
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
}, },
"i18next": {
"version": "21.6.14",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.14.tgz",
"integrity": "sha512-XL6WyD+xlwQwbieXRlXhKWoLb/rkch50/rA+vl6untHnJ+aYnkQ0YDZciTWE78PPhOpbi2gR0LTJCJpiAhA+uQ==",
"requires": {
"@babel/runtime": "^7.17.2"
},
"dependencies": {
"@babel/runtime": {
"version": "7.17.8",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz",
"integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
}
}
},
"i18next-browser-languagedetector": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.4.tgz",
"integrity": "sha512-wukWnFeU7rKIWT66VU5i8I+3Zc4wReGcuDK2+kuFhtoxBRGWGdvYI9UQmqNL/yQH1KogWwh+xGEaIPH8V/i2Zg==",
"requires": {
"@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": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/i18next-xhr-backend/-/i18next-xhr-backend-3.2.2.tgz",
"integrity": "sha512-OtRf2Vo3IqAxsttQbpjYnmMML12IMB5e0fc5B7qKJFLScitYaXa1OhMX0n0X/3vrfFlpHL9Ro/H+ps4Ej2j7QQ==",
"requires": {
"@babel/runtime": "^7.5.5"
}
},
"image-size": { "image-size": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz",
@ -5751,9 +5818,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
}, },
"mixin-deep": { "mixin-deep": {
"version": "1.3.2", "version": "1.3.2",
@ -5839,9 +5906,9 @@
} }
}, },
"node-fetch": { "node-fetch": {
"version": "2.6.6", "version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": { "requires": {
"whatwg-url": "^5.0.0" "whatwg-url": "^5.0.0"
} }
@ -5881,11 +5948,11 @@
} }
}, },
"nth-check": { "nth-check": {
"version": "1.0.2", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
"requires": { "requires": {
"boolbase": "~1.0.0" "boolbase": "^1.0.0"
} }
}, },
"nullthrows": { "nullthrows": {
@ -6143,9 +6210,9 @@
} }
}, },
"plist": { "plist": {
"version": "3.0.4", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
"integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==", "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
"requires": { "requires": {
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"xmlbuilder": "^9.0.7" "xmlbuilder": "^9.0.7"
@ -6355,6 +6422,16 @@
"scheduler": "^0.20.2" "scheduler": "^0.20.2"
} }
}, },
"react-i18next": {
"version": "11.16.2",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.16.2.tgz",
"integrity": "sha512-1iuZduvARUelL5ux663FvIoDZExwFO+9QtRAAt4uvs1/aun4cUZt8XBrVg7iiDgNls9cOSORAhE7Ri5KA9RMvg==",
"requires": {
"@babel/runtime": "^7.14.5",
"html-escaper": "^2.0.2",
"html-parse-stringify": "^3.0.1"
}
},
"react-is": { "react-is": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@ -6601,11 +6678,11 @@
} }
}, },
"react-native-svg": { "react-native-svg": {
"version": "12.1.1", "version": "12.3.0",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.1.1.tgz", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.3.0.tgz",
"integrity": "sha512-NIAJ8jCnXGCqGWXkkJ1GTzO4a3Md5at5sagYV8Vh4MXYnL4z5Rh428Wahjhh+LIjx40EE5xM5YtwyJBqOIba2Q==", "integrity": "sha512-ESG1g1j7/WLD7X3XRFTQHVv0r6DpbHNNcdusngAODIxG88wpTWUZkhcM3A2HJTb+BbXTFDamHv7FwtRKWQ/ALg==",
"requires": { "requires": {
"css-select": "^2.1.0", "css-select": "^4.2.1",
"css-tree": "^1.0.0-alpha.39" "css-tree": "^1.0.0-alpha.39"
} }
}, },
@ -7345,13 +7422,24 @@
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
}, },
"simple-plist": { "simple-plist": {
"version": "1.3.0", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.0.tgz", "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz",
"integrity": "sha512-uYWpeGFtZtVt2NhG4AHgpwx323zxD85x42heMJBan1qAiqqozIlaGrwrEt6kRjXWRWIXsuV1VLCvVmZan2B5dg==", "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==",
"requires": { "requires": {
"bplist-creator": "0.1.0", "bplist-creator": "0.1.0",
"bplist-parser": "0.3.0", "bplist-parser": "0.3.1",
"plist": "^3.0.4" "plist": "^3.0.5"
},
"dependencies": {
"plist": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
"integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
"requires": {
"base64-js": "^1.5.1",
"xmlbuilder": "^9.0.7"
}
}
} }
}, },
"sisteransi": { "sisteransi": {
@ -7993,6 +8081,11 @@
"resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
"integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="
}, },
"void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha1-YU9/v42AHwu18GYfWy9XhXUOTwk="
},
"walker": { "walker": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",

View File

@ -33,16 +33,22 @@
"@mui/x-data-grid": "^5.2.2", "@mui/x-data-grid": "^5.2.2",
"country-flag-icons": "^1.4.25", "country-flag-icons": "^1.4.25",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"i18next": "^21.6.14",
"i18next-browser-languagedetector": "^6.1.4",
"i18next-http-backend": "^1.4.0",
"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",
"react-i18next": "^11.16.2",
"react-native": "^0.66.4", "react-native": "^0.66.4",
"react-native-svg": "^12.1.1", "react-native-svg": "^12.3.0",
"react-qr-code": "^2.0.3", "react-qr-code": "^2.0.3",
"react-qr-reader": "^2.2.1", "react-qr-reader": "^2.2.1",
"react-responsive": "^9.0.0-beta.6", "react-responsive": "^9.0.0-beta.6",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-world-flags": "^1.4.0", "react-world-flags": "^1.4.0",
"reconnecting-websocket": "^4.4.0", "reconnecting-websocket": "^4.4.0",
"simple-plist": "^1.3.1",
"websocket": "^1.0.34" "websocket": "^1.0.34"
} }
} }

View File

@ -5,6 +5,9 @@ import { CssBaseline, IconButton} from "@mui/material";
import { ThemeProvider, createTheme } from '@mui/material/styles'; import { ThemeProvider, createTheme } from '@mui/material/styles';
import UnsafeAlert from "./UnsafeAlert"; import UnsafeAlert from "./UnsafeAlert";
import { I18nextProvider } from "react-i18next";
import i18n from "./i18n";
import DarkModeIcon from '@mui/icons-material/DarkMode'; import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode'; import LightModeIcon from '@mui/icons-material/LightMode';
@ -12,18 +15,11 @@ export default class App extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
nickname: null,
token: null,
dark: false, dark: false,
} }
} }
setAppState=(newState)=>{ lightTheme = createTheme({});
this.setState(newState)
}
lightTheme = createTheme({
});
darkTheme = createTheme({ darkTheme = createTheme({
palette: { palette: {
@ -36,14 +32,16 @@ export default class App extends Component {
render() { render() {
return ( return (
<ThemeProvider theme={this.state.dark ? this.darkTheme : this.lightTheme}> <I18nextProvider i18n={i18n}>
<CssBaseline/> <ThemeProvider theme={this.state.dark ? this.darkTheme : this.lightTheme}>
<IconButton sx={{position:'fixed',right:'0px'}} onClick={()=>this.setState({dark:!this.state.dark})}> <CssBaseline/>
{this.state.dark ? <LightModeIcon/>:<DarkModeIcon/>} <IconButton sx={{position:'fixed',right:'0px'}} onClick={()=>this.setState({dark:!this.state.dark})}>
</IconButton> {this.state.dark ? <LightModeIcon/>:<DarkModeIcon/>}
<UnsafeAlert className="unsafeAlert"/> </IconButton>
<HomePage setAppState={this.setAppState}/> <UnsafeAlert className="unsafeAlert"/>
</ThemeProvider> <HomePage/>
</ThemeProvider>
</I18nextProvider>
); );
} }
} }

View File

@ -1,22 +1,23 @@
import React, { Component , useState } from "react"; import React, { Component } from "react";
import { withTranslation, Trans} from "react-i18next";
import { Badge, Tooltip, Paper, Button, ListItemButton, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, ListItemText, ListItemAvatar, IconButton} from "@mui/material"; import { Badge, Tooltip, Paper, Button, ListItemButton, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, ListItemText, ListItemAvatar, IconButton} from "@mui/material";
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { DataGrid } from '@mui/x-data-grid'; import { DataGrid } from '@mui/x-data-grid';
import currencyDict from '../../static/assets/currencies.json';
import MediaQuery from 'react-responsive' import MediaQuery from 'react-responsive'
import Image from 'material-ui-image' import Image from 'material-ui-image'
import getFlags from './getFlags' import getFlags from './getFlags'
import PaymentText from './PaymentText' import PaymentText from './PaymentText'
export default class BookPage extends Component { class BookPage extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
orders: new Array({id:0,}), orders: new Array({id:0,}),
currencies_dict: {"0":"ANY"},
loading: true, loading: true,
pageSize: 6, pageSize: 6,
}; };
this.getCurrencyDict()
this.getOrderDetails(this.props.type, this.props.currency) this.getOrderDetails(this.props.type, this.props.currency)
} }
@ -51,20 +52,12 @@ export default class BookPage extends Component {
this.getOrderDetails(this.props.type, currency); this.getOrderDetails(this.props.type, currency);
} }
getCurrencyDict() {
fetch('/static/assets/currencies.json')
.then((response) => response.json())
.then((data) =>
this.setState({
currencies_dict: data
}));
}
getCurrencyCode(val){ getCurrencyCode(val){
const { t } = this.props;
if (val){ if (val){
return val == 0 ? 'ANY' : this.state.currencies_dict[val.toString()] return val == 0 ? t('ANY_currency') : currencyDict[val.toString()]
}else{ }else{
return 'ANY' return t('ANY_currency')
} }
} }
@ -94,6 +87,7 @@ export default 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
@ -103,7 +97,7 @@ export default 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,
@ -117,11 +111,11 @@ export default 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'
@ -139,24 +133,24 @@ export default 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 othersText={t("Others")} 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>
)} }, )} },
@ -172,7 +166,7 @@ export default 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
@ -183,7 +177,7 @@ export default 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,
@ -197,9 +191,9 @@ export default 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'
@ -214,29 +208,29 @@ export default 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 othersText={t("Others")} 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>
@ -255,6 +249,7 @@ export default 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">
@ -264,21 +259,21 @@ export default 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>
@ -286,21 +281,21 @@ export default 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_currency")}</MenuItem>
{ {
Object.entries(this.state.currencies_dict) 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> )
} }
</Select> </Select>
@ -309,7 +304,15 @@ export default 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>
} }
@ -318,15 +321,19 @@ export default 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>
@ -350,10 +357,12 @@ export default 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>
); );
}; };
} }
export default withTranslation()(BookPage);

View File

@ -1,7 +1,9 @@
import React, { Component } from 'react' import React, { Component } from 'react'
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';
@ -54,7 +56,7 @@ function getCookie(name) {
return cookieValue; return cookieValue;
} }
export default class BottomBar extends Component { class BottomBar extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -104,7 +106,7 @@ export default class BottomBar extends Component {
}; };
StatsDialog =() =>{ StatsDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openStatsForNerds} open={this.state.openStatsForNerds}
@ -113,12 +115,12 @@ export default 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/>
@ -154,7 +156,7 @@ export default 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>
@ -164,13 +166,13 @@ export default 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/>
@ -178,12 +180,12 @@ export default 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>
@ -200,6 +202,7 @@ export default class BottomBar extends Component {
}; };
CommunityDialog =() =>{ CommunityDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
@ -209,36 +212,43 @@ export default 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 Chinese 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>
@ -285,6 +295,7 @@ export default class BottomBar extends Component {
} }
dialogProfile =() =>{ dialogProfile =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openProfile} open={this.state.openProfile}
@ -293,11 +304,11 @@ export default 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'}}>
@ -325,12 +336,12 @@ export default 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>
} }
@ -338,17 +349,17 @@ export default 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>
@ -356,7 +367,7 @@ export default class BottomBar extends Component {
}} }}
/> />
: :
'Cannot remember'} t("Cannot remember")}
</ListItemText> </ListItemText>
</ListItem> </ListItem>
@ -367,7 +378,7 @@ export default 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>
@ -376,15 +387,14 @@ export default 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>
@ -399,13 +409,13 @@ export default 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>
@ -416,8 +426,7 @@ export default 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 => {
@ -426,7 +435,7 @@ export default 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>
@ -441,7 +450,7 @@ export default 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>
:""} :""}
@ -454,6 +463,7 @@ export default 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/>
@ -465,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}}
@ -495,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>
@ -508,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>
@ -521,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>
@ -534,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>
@ -547,23 +557,16 @@ 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>
<Grid container item xs={1}> <Grid container item xs={1}>
<Grid item xs={6}> <Grid item xs={6}>
<Select <this.LangSelect/>
size = 'small'
defaultValue={1}
inputProps={{
style: {textAlign:"center"}
}}>
<MenuItem value={1}>EN</MenuItem>
</Select>
</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"
@ -573,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} >
@ -587,6 +590,29 @@ bottomBarDesktop =()=>{
</Paper> </Paper>
) )
} }
handleChangeLang=(e)=>{
const { i18n} = this.props;
console.log(i18n)
i18n.changeLanguage(e.target.value)
}
LangSelect = () => {
const { i18n} = this.props;
return(
<Select
size = 'small'
value = {i18n.resolvedLanguage.substring(0,2)}
inputProps={{
style: {textAlign:"center"}
}}
onChange={this.handleChangeLang}>
<MenuItem value={'en'}>EN</MenuItem>
<MenuItem disabled={true} value={'es'}>ES</MenuItem>
<MenuItem disabled={true} value={'de'}>DE</MenuItem>
<MenuItem disabled={true} value={'ru'}>RU</MenuItem>
<MenuItem disabled={true} value={'zh'}>ZH</MenuItem>
</Select>
)
}
handleClickOpenExchangeSummary = () => { handleClickOpenExchangeSummary = () => {
this.getInfo(); this.getInfo();
@ -597,6 +623,7 @@ bottomBarDesktop =()=>{
}; };
exchangeSummaryDialog =() =>{ exchangeSummaryDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openExchangeSummary} open={this.state.openExchangeSummary}
@ -605,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">
@ -615,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/>
@ -627,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/>
@ -639,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/>
@ -651,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/>
@ -663,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/>
@ -676,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>
@ -684,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>
@ -698,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/>
@ -708,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'
@ -729,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 />
@ -739,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 />
@ -749,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 />
@ -759,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 />
@ -770,17 +798,10 @@ bottomBarPhone =()=>{
<Grid container item xs={3.8}> <Grid container item xs={3.8}>
<Grid item xs={6}> <Grid item xs={6}>
<Select <this.LangSelect/>
size = 'small'
defaultValue={1}
inputProps={{
style: {textAlign:"center"}
}}>
<MenuItem value={1}>EN</MenuItem>
</Select>
</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"
@ -790,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} >
@ -819,3 +840,4 @@ bottomBarPhone =()=>{
) )
} }
} }
export default withTranslation()(BottomBar);

View File

@ -1,8 +1,9 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { withTranslation, Trans} from "react-i18next";
import {Button, Link, Badge, TextField, Grid, Container, Card, CardHeader, Paper, Avatar, FormHelperText, Typography} from "@mui/material"; import {Button, Link, Badge, TextField, Grid, Container, Card, CardHeader, Paper, Avatar, FormHelperText, Typography} from "@mui/material";
import ReconnectingWebSocket from 'reconnecting-websocket'; import ReconnectingWebSocket from 'reconnecting-websocket';
export default class Chat extends Component { class Chat extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
} }
@ -79,6 +80,7 @@ export default class Chat extends Component {
} }
render() { render() {
const { t } = this.props;
return ( return (
<Container component="main" maxWidth="xs" > <Container component="main" maxWidth="xs" >
<Grid container xs={12} spacing={0.5}> <Grid container xs={12} spacing={0.5}>
@ -86,7 +88,7 @@ export default class Chat extends Component {
<Grid item xs={5.5}> <Grid item xs={5.5}>
<Paper elevation={1} style={this.state.connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}> <Paper elevation={1} style={this.state.connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
<Typography variant='caption' sx={{color: '#111111'}}> <Typography variant='caption' sx={{color: '#111111'}}>
You: {this.state.connected ? 'connected': 'disconnected'} {t("You")+": "}{this.state.connected ? t("connected"): t("disconnected")}
</Typography> </Typography>
</Paper> </Paper>
</Grid> </Grid>
@ -94,7 +96,7 @@ export default class Chat extends Component {
<Grid item xs={5.5}> <Grid item xs={5.5}>
<Paper elevation={1} style={this.state.peer_connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}> <Paper elevation={1} style={this.state.peer_connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
<Typography variant='caption' sx={{color: '#111111'}}> <Typography variant='caption' sx={{color: '#111111'}}>
Peer: {this.state.peer_connected ? 'connected': 'disconnected'} {t("Peer")+": "}{this.state.peer_connected ? t("connected"): t("disconnected")}
</Typography> </Typography>
</Paper> </Paper>
</Grid> </Grid>
@ -142,10 +144,10 @@ export default class Chat extends Component {
<Grid containter alignItems="stretch" style={{ display: "flex" }}> <Grid containter alignItems="stretch" style={{ display: "flex" }}>
<Grid item alignItems="stretch" style={{ display: "flex"}}> <Grid item alignItems="stretch" style={{ display: "flex"}}>
<TextField <TextField
label="Type a message" label={t("Type a message")}
variant="standard" variant="standard"
size="small" size="small"
helperText={this.state.connected ? null : "Connecting..."} helperText={this.state.connected ? null : t("Connecting...")}
value={this.state.value} value={this.state.value}
onChange={e => { onChange={e => {
this.setState({ value: e.target.value }); this.setState({ value: e.target.value });
@ -155,14 +157,16 @@ export default class Chat extends Component {
/> />
</Grid> </Grid>
<Grid item alignItems="stretch" style={{ display: "flex" }}> <Grid item alignItems="stretch" style={{ display: "flex" }}>
<Button disabled={!this.state.connected} type="submit" variant="contained" color="primary" > Send </Button> <Button disabled={!this.state.connected} type="submit" variant="contained" color="primary">{t("Send")} </Button>
</Grid> </Grid>
</Grid> </Grid>
</form> </form>
<FormHelperText> <FormHelperText>
The chat has no memory: if you leave, messages are lost. <Link target="_blank" href="https://github.com/Reckless-Satoshi/robosats/blob/main/docs/sensitive-data-PGP-guide.md/"> Learn easy PGP encryption.</Link> {t("The chat has no memory: if you leave, messages are lost.")} <Link target="_blank" href="https://github.com/Reckless-Satoshi/robosats/blob/main/docs/sensitive-data-PGP-guide.md/"> {t("Learn easy PGP encryption.")}</Link>
</FormHelperText> </FormHelperText>
</Container> </Container>
) )
} }
} }
export default withTranslation()(Chat);

View File

@ -1,11 +1,12 @@
import {Typography, Link, DialogActions, DialogContent, Button, Grid} from "@mui/material"
import React, { Component } from 'react' import React, { Component } from 'react'
import { withTranslation, Trans} from "react-i18next";
import {Typography, Link, DialogActions, DialogContent, Button, Grid} from "@mui/material"
import Image from 'material-ui-image' import Image from 'material-ui-image'
import MediaQuery from 'react-responsive' import MediaQuery from 'react-responsive'
export default class InfoDialog extends Component { class InfoDialog extends Component {
render() { render() {
const { t } = this.props;
return ( return (
<div> <div>
<DialogContent> <DialogContent>
@ -13,13 +14,13 @@ export default 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,130 +36,80 @@ export default 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>
) )
} }
} }
export default withTranslation()(InfoDialog);

View File

@ -1,13 +1,18 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { withTranslation, Trans} from "react-i18next";
import { InputAdornment, LinearProgress, Link, Checkbox, Slider, Box, Tab, Tabs, SliderThumb, Tooltip, Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material" import { InputAdornment, LinearProgress, Link, Checkbox, Slider, Box, Tab, Tabs, SliderThumb, Tooltip, Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material"
import { LocalizationProvider, TimePicker} from '@mui/lab'; import { LocalizationProvider, TimePicker} from '@mui/lab';
import DateFnsUtils from "@date-io/date-fns"; import DateFnsUtils from "@date-io/date-fns";
import { Link as LinkRouter } from 'react-router-dom' import { Link as LinkRouter } from 'react-router-dom'
import { styled } from '@mui/material/styles'; import { styled } from '@mui/material/styles';
import getFlags from './getFlags'; import getFlags from './getFlags';
import AutocompletePayments from './autocompletePayments'; import AutocompletePayments from './autocompletePayments';
import LockIcon from '@mui/icons-material/Lock'; import LockIcon from '@mui/icons-material/Lock';
import HourglassTopIcon from '@mui/icons-material/HourglassTop'; import HourglassTopIcon from '@mui/icons-material/HourglassTop';
import currencyDict from '../../static/assets/currencies.json';
function getCookie(name) { function getCookie(name) {
let cookieValue = null; let cookieValue = null;
@ -36,7 +41,7 @@ function pn(x) {
return parts.join("."); return parts.join(".");
} }
export default class MakerPage extends Component { class MakerPage extends Component {
defaultCurrency = 1; defaultCurrency = 1;
defaultCurrencyCode = 'USD'; defaultCurrencyCode = 'USD';
defaultPaymentMethod = "not specified"; defaultPaymentMethod = "not specified";
@ -57,7 +62,6 @@ export default class MakerPage extends Component {
payment_method: this.defaultPaymentMethod, payment_method: this.defaultPaymentMethod,
premium: 0, premium: 0,
satoshis: null, satoshis: null,
currencies_dict: {"1":"USD"},
showAdvanced: false, showAdvanced: false,
allowBondless: false, allowBondless: false,
publicExpiryTime: new Date(0, 0, 0, 23, 59), publicExpiryTime: new Date(0, 0, 0, 23, 59),
@ -69,7 +73,6 @@ export default class MakerPage extends Component {
maxAmount: null, maxAmount: null,
loadingLimits: false, loadingLimits: false,
} }
this.getCurrencyDict()
} }
getLimits() { getLimits() {
@ -173,11 +176,14 @@ export default class MakerPage extends Component {
} }
handlePremiumChange=(e)=>{ handlePremiumChange=(e)=>{
const { t } = this.props;
var max = 999;
var min = -100;
if(e.target.value > 999){ if(e.target.value > 999){
var bad_premium = "Must be less than 999%" var bad_premium = t("Must be less than {{max}}%", {max:max})
} }
if(e.target.value < -100){ if(e.target.value <= -100){
var bad_premium = "Must be more than -100%" var bad_premium = t("Must be more than {{min}}%", {min:min})
} }
this.setState({ this.setState({
@ -187,11 +193,12 @@ export default class MakerPage extends Component {
} }
handleSatoshisChange=(e)=>{ handleSatoshisChange=(e)=>{
const { t } = this.props;
if(e.target.value > this.maxTradeSats){ if(e.target.value > this.maxTradeSats){
var bad_sats = "Must be less than " + pn(this.maxTradeSats) var bad_sats = t("Must be less than {{maxSats}",{maxSats: pn(this.maxTradeSats)})
} }
if(e.target.value < this.minTradeSats){ if(e.target.value < this.minTradeSats){
var bad_sats = "Must be more than "+pn(this.minTradeSats) var bad_sats = t("Must be more than {{minSats}}",{minSats: pn(this.minTradeSats)})
} }
this.setState({ this.setState({
@ -207,10 +214,12 @@ export default class MakerPage extends Component {
} }
handleClickExplicit=(e)=>{ handleClickExplicit=(e)=>{
this.setState({ if(!this.state.enableAmountRange){
is_explicit: true, this.setState({
}); is_explicit: true,
this.handleSatoshisChange(); });
this.handleSatoshisChange();
}
} }
handleCreateOfferButtonPressed=()=>{ handleCreateOfferButtonPressed=()=>{
@ -240,18 +249,8 @@ export default class MakerPage extends Component {
& (data.id ? this.props.history.push('/order/' + data.id) :""))); & (data.id ? this.props.history.push('/order/' + data.id) :"")));
} }
getCurrencyDict() {
fetch('/static/assets/currencies.json')
.then((response) => response.json())
.then((data) =>
this.setState({
currencies_dict: data
}));
}
getCurrencyCode(val){ getCurrencyCode(val){
return this.state.currencies_dict[val.toString()] return currencyDict[val.toString()]
} }
handleInputBondSizeChange = (event) => { handleInputBondSizeChange = (event) => {
@ -259,25 +258,26 @@ export default class MakerPage extends Component {
}; };
StandardMakerOptions = () => { StandardMakerOptions = () => {
const { t } = this.props;
return( return(
<Paper elevation={12} style={{ padding: 8, width:'260px', align:'center'}}> <Paper elevation={12} style={{ padding: 8, width:'260px', align:'center'}}>
<Grid item xs={12} align="center" spacing={1}> <Grid item xs={12} align="center" spacing={1}>
<div style={{position:'relative', left:'5px'}}> <div style={{position:'relative', left:'5px'}}>
<FormControl component="fieldset"> <FormControl component="fieldset">
<FormHelperText> <FormHelperText>
Buy or Sell Bitcoin? {t("Buy or Sell Bitcoin?")}
</FormHelperText> </FormHelperText>
<RadioGroup row defaultValue="0" onChange={this.handleTypeChange}> <RadioGroup row defaultValue="0" onChange={this.handleTypeChange}>
<FormControlLabel <FormControlLabel
value="0" value="0"
control={<Radio color="primary"/>} control={<Radio color="primary"/>}
label="Buy" label={t("Buy")}
labelPlacement="Top" labelPlacement="Top"
/> />
<FormControlLabel <FormControlLabel
value="1" value="1"
control={<Radio color="secondary"/>} control={<Radio color="secondary"/>}
label="Sell" label={t("Sell")}
labelPlacement="Top" labelPlacement="Top"
/> />
</RadioGroup> </RadioGroup>
@ -287,13 +287,13 @@ export default class MakerPage extends Component {
<Grid containter xs={12} alignItems="stretch" style={{ display: "flex" }}> <Grid containter xs={12} alignItems="stretch" style={{ display: "flex" }}>
<div style={{maxWidth:150}}> <div style={{maxWidth:150}}>
<Tooltip placement="top" enterTouchDelay="500" enterDelay="700" enterNextDelay="2000" title="Amount of fiat to exchange for bitcoin"> <Tooltip placement="top" enterTouchDelay="500" enterDelay="700" enterNextDelay="2000" title={t("Amount of fiat to exchange for bitcoin")}>
<TextField <TextField
disabled = {this.state.enableAmountRange} disabled = {this.state.enableAmountRange}
variant = {this.state.enableAmountRange ? 'filled' : 'outlined'} variant = {this.state.enableAmountRange ? 'filled' : 'outlined'}
error={this.state.amount <= 0 & this.state.amount != "" } error={this.state.amount <= 0 & this.state.amount != "" }
helperText={this.state.amount <= 0 & this.state.amount != "" ? 'Invalid' : null} helperText={this.state.amount <= 0 & this.state.amount != "" ? t("Invalid") : null}
label="Amount" label={t("Amount")}
type="number" type="number"
required="true" required="true"
value={this.state.amount} value={this.state.amount}
@ -314,7 +314,7 @@ export default class MakerPage extends Component {
style: {textAlign:"center"} style: {textAlign:"center"}
}} }}
onChange={this.handleCurrencyChange}> onChange={this.handleCurrencyChange}>
{Object.entries(this.state.currencies_dict) {Object.entries(currencyDict)
.map( ([key, value]) => <MenuItem value={parseInt(key)}> .map( ([key, value]) => <MenuItem value={parseInt(key)}>
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>{getFlags(value)}{" "+value}</div> <div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>{getFlags(value)}{" "+value}</div>
</MenuItem> )} </MenuItem> )}
@ -323,13 +323,15 @@ export default class MakerPage extends Component {
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Tooltip placement="top" enterTouchDelay="300" enterDelay="700" enterNextDelay="2000" title="Enter your preferred fiat payment methods. Fast methods are highly recommended."> <Tooltip placement="top" enterTouchDelay="300" enterDelay="700" enterNextDelay="2000" title={t("Enter your preferred fiat payment methods. Fast methods are highly recommended.")}>
<AutocompletePayments <AutocompletePayments
onAutocompleteChange={this.handlePaymentMethodChange} onAutocompleteChange={this.handlePaymentMethodChange}
optionsType={this.state.currency==1000 ? "swap":"fiat"} optionsType={this.state.currency==1000 ? "swap":"fiat"}
error={this.state.badPaymentMethod} error={this.state.badPaymentMethod}
helperText={this.state.badPaymentMethod ? "Must be shorter than 65 characters":""} helperText={this.state.badPaymentMethod ? t("Must be shorter than 65 characters"):""}
label={this.state.currency==1000 ? "Swap Destination(s)" : "Fiat Payment Method(s)"} label={this.state.currency==1000 ? t("Swap Destination(s)") : t("Fiat Payment Method(s)")}
listHeaderText={t("You can add any method")}
addNewButtonText={t("Add New")}
/> />
</Tooltip> </Tooltip>
</Grid> </Grid>
@ -338,25 +340,25 @@ export default class MakerPage extends Component {
<FormControl component="fieldset"> <FormControl component="fieldset">
<FormHelperText > <FormHelperText >
<div align='center'> <div align='center'>
Choose a Pricing Method {t("Choose a Pricing Method")}
</div> </div>
</FormHelperText> </FormHelperText>
<RadioGroup row defaultValue="relative"> <RadioGroup row defaultValue="relative">
<Tooltip placement="top" enterTouchDelay="0" enterDelay="1000" enterNextDelay="2000" title="Let the price move with the market"> <Tooltip placement="top" enterTouchDelay="0" enterDelay="1000" enterNextDelay="2000" title={t("Let the price move with the market")}>
<FormControlLabel <FormControlLabel
value="relative" value="relative"
control={<Radio color="primary"/>} control={<Radio color="primary"/>}
label="Relative" label={t("Relative")}
labelPlacement="Top" labelPlacement="Top"
onClick={this.handleClickRelative} onClick={this.handleClickRelative}
/> />
</Tooltip> </Tooltip>
<Tooltip placement="top" enterTouchDelay="0" enterDelay="1000" enterNextDelay="2000" title="Set a fix amount of satoshis"> <Tooltip placement="top" enterTouchDelay="0" enterDelay="1000" enterNextDelay="2000" title={t("Set a fix amount of satoshis")}>
<FormControlLabel <FormControlLabel
disabled={this.state.enableAmountRange} disabled={this.state.enableAmountRange}
value="explicit" value="explicit"
control={<Radio color="secondary"/>} control={<Radio color="secondary"/>}
label="Explicit" label={t("Explicit")}
labelPlacement="Top" labelPlacement="Top"
onClick={this.handleClickExplicit} onClick={this.handleClickExplicit}
/> />
@ -369,20 +371,18 @@ export default class MakerPage extends Component {
<div style={{display: this.state.is_explicit ? '':'none'}}> <div style={{display: this.state.is_explicit ? '':'none'}}>
<TextField <TextField
sx={{width:240}} sx={{width:240}}
label="Satoshis" label={t("Satoshis")}
error={this.state.badSatoshis} error={this.state.badSatoshis}
helperText={this.state.badSatoshis} helperText={this.state.badSatoshis}
type="number" type="number"
required="true" required="true"
value={this.state.satoshis} value={this.state.satoshis}
inputProps={{ inputProps={{
// TODO read these from .env file
min:this.minTradeSats , min:this.minTradeSats ,
max:this.maxTradeSats , max:this.maxTradeSats ,
style: {textAlign:"center"} style: {textAlign:"center"}
}} }}
onChange={this.handleSatoshisChange} onChange={this.handleSatoshisChange}
// defaultValue={this.defaultSatoshis}
/> />
</div> </div>
<div style={{display: this.state.is_explicit ? 'none':''}}> <div style={{display: this.state.is_explicit ? 'none':''}}>
@ -390,9 +390,8 @@ export default class MakerPage extends Component {
sx={{width:240}} sx={{width:240}}
error={this.state.badPremium} error={this.state.badPremium}
helperText={this.state.badPremium} helperText={this.state.badPremium}
label="Premium over Market (%)" label={t("Premium over Market (%)")}
type="number" type="number"
// defaultValue={this.defaultPremium}
inputProps={{ inputProps={{
min: -100, min: -100,
max: 999, max: 999,
@ -492,10 +491,10 @@ export default class MakerPage extends Component {
} }
rangeText =()=> { rangeText =()=> {
const { t } = this.props;
return ( return (
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}> <div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
<span style={{width: 40}}>From</span> <span style={{width: 40}}>{t("From")}</span>
<TextField <TextField
variant="standard" variant="standard"
type="number" type="number"
@ -505,7 +504,7 @@ export default class MakerPage extends Component {
error={this.minAmountError()} error={this.minAmountError()}
sx={{width: this.state.minAmount.toString().length * 9, maxWidth: 40}} sx={{width: this.state.minAmount.toString().length * 9, maxWidth: 40}}
/> />
<span style={{width: 20}}>to</span> <span style={{width: 20}}>{t("to")}</span>
<TextField <TextField
variant="standard" variant="standard"
size="small" size="small"
@ -522,6 +521,7 @@ export default class MakerPage extends Component {
} }
AdvancedMakerOptions = () => { AdvancedMakerOptions = () => {
const { t } = this.props;
return( return(
<Paper elevation={12} style={{ padding: 8, width:'280px', align:'center'}}> <Paper elevation={12} style={{ padding: 8, width:'280px', align:'center'}}>
@ -530,10 +530,10 @@ export default class MakerPage extends Component {
<Grid item xs={12} align="center" spacing={1}> <Grid item xs={12} align="center" spacing={1}>
<FormControl align="center"> <FormControl align="center">
<FormHelperText> <FormHelperText>
<Tooltip enterTouchDelay="0" placement="top" align="center"title={"Let the taker chose an amount within the range"}> <Tooltip enterTouchDelay="0" placement="top" align="center" title={t("Let the taker chose an amount within the range")}>
<div align="center" style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}> <div align="center" style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
<Checkbox onChange={(e)=>this.setState({enableAmountRange:e.target.checked}) & (e.target.checked ? this.getLimits() : null)}/> <Checkbox onChange={(e)=>this.setState({enableAmountRange:e.target.checked, is_explicit: false}) & (e.target.checked ? this.getLimits() : null)}/>
{this.state.enableAmountRange & this.state.minAmount != null? <this.rangeText/> : "Enable Amount Range"} {this.state.enableAmountRange & this.state.minAmount != null? <this.rangeText/> : t("Enable Amount Range")}
</div> </div>
</Tooltip> </Tooltip>
</FormHelperText> </FormHelperText>
@ -583,7 +583,7 @@ export default class MakerPage extends Component {
</InputAdornment>) </InputAdornment>)
}} }}
renderInput={(props) => <TextField {...props} />} renderInput={(props) => <TextField {...props} />}
label="Public Duration (HH:mm)" label={t("Public Duration (HH:mm)")}
value={this.state.publicExpiryTime} value={this.state.publicExpiryTime}
onChange={this.handleChangePublicDuration} onChange={this.handleChangePublicDuration}
minTime={new Date(0, 0, 0, 0, 10)} minTime={new Date(0, 0, 0, 0, 10)}
@ -594,10 +594,10 @@ export default class MakerPage extends Component {
<Grid item xs={12} align="center" spacing={1}> <Grid item xs={12} align="center" spacing={1}>
<FormControl align="center"> <FormControl align="center">
<Tooltip enterDelay="800" enterTouchDelay="0" placement="top" title={"Set the skin-in-the-game, increase for higher safety assurance"}> <Tooltip enterDelay="800" enterTouchDelay="0" placement="top" title={t("Set the skin-in-the-game, increase for higher safety assurance")}>
<FormHelperText> <FormHelperText>
<div align="center" style={{display:'flex',flexWrap:'wrap', transform: 'translate(20%, 0)'}}> <div align="center" style={{display:'flex',flexWrap:'wrap', transform: 'translate(20%, 0)'}}>
Fidelity Bond Size <LockIcon sx={{height:20,width:20}}/> {t("Fidelity Bond Size")} <LockIcon sx={{height:20,width:20}}/>
</div> </div>
</FormHelperText> </FormHelperText>
</Tooltip> </Tooltip>
@ -618,9 +618,9 @@ export default class MakerPage extends Component {
</Grid> </Grid>
<Grid item xs={12} align="center" spacing={1}> <Grid item xs={12} align="center" spacing={1}>
<Tooltip enterTouchDelay="0" title={"COMING SOON - High risk! Limited to "+ this.maxBondlessSats/1000 +"K Sats"}> <Tooltip enterTouchDelay="0" title={t("COMING SOON - High risk! Limited to {{limitSats}}K Sats",{ limitSats: this.maxBondlessSats/1000})}>
<FormControlLabel <FormControlLabel
label={<a>Allow bondless taker (<Link href="https://git.robosats.com" target="_blank">info</Link>)</a>} label={t("Allow bondless takers")}
control={ control={
<Checkbox <Checkbox
disabled disabled
@ -640,7 +640,7 @@ export default class MakerPage extends Component {
makeOrderBox=()=>{ makeOrderBox=()=>{
const [value, setValue] = React.useState(this.state.showAdvanced); const [value, setValue] = React.useState(this.state.showAdvanced);
const { t } = this.props;
const handleChange = (event, newValue) => { const handleChange = (event, newValue) => {
this.setState({showAdvanced:newValue}) this.setState({showAdvanced:newValue})
setValue(newValue); setValue(newValue);
@ -649,8 +649,8 @@ export default class MakerPage extends Component {
<Box sx={{width: this.state.showAdvanced? '270px':'252px'}}> <Box sx={{width: this.state.showAdvanced? '270px':'252px'}}>
<Box sx={{ borderBottom: 1, borderColor: 'divider', position:'relative',left:'5px'}}> <Box sx={{ borderBottom: 1, borderColor: 'divider', position:'relative',left:'5px'}}>
<Tabs value={value? value:0} onChange={handleChange} variant="fullWidth" > <Tabs value={value? value:0} onChange={handleChange} variant="fullWidth" >
<Tab label="Order" {...this.a11yProps(0)} /> <Tab label={t("Order")} {...this.a11yProps(0)} />
<Tab label="Customize" {...this.a11yProps(1)} /> <Tab label={t("Customize")} {...this.a11yProps(1)} />
</Tabs> </Tabs>
</Box> </Box>
@ -666,6 +666,7 @@ export default class MakerPage extends Component {
) )
} }
render() { render() {
const { t } = this.props;
return ( return (
<Grid container xs={12} align="center" spacing={1} sx={{minWidth:380}}> <Grid container xs={12} align="center" spacing={1} sx={{minWidth:380}}>
{/* <Grid item xs={12} align="center" sx={{minWidth:380}}> {/* <Grid item xs={12} align="center" sx={{minWidth:380}}>
@ -685,11 +686,11 @@ export default class MakerPage extends Component {
(this.state.is_explicit & (this.state.badSatoshis != null || this.state.satoshis == null)) || (this.state.is_explicit & (this.state.badSatoshis != null || this.state.satoshis == null)) ||
(!this.state.is_explicit & this.state.badPremium != null)) (!this.state.is_explicit & this.state.badPremium != null))
? ?
<Tooltip enterTouchDelay="0" title="You must fill the form correctly"> <Tooltip enterTouchDelay="0" title={t("You must fill the order correctly")}>
<div><Button disabled color="primary" variant="contained" onClick={this.handleCreateOfferButtonPressed} >Create Order</Button></div> <div><Button disabled color="primary" variant="contained" onClick={this.handleCreateOfferButtonPressed}>{t("Create Order")}</Button></div>
</Tooltip> </Tooltip>
: :
<Button color="primary" variant="contained" onClick={this.handleCreateOfferButtonPressed} >Create Order</Button> <Button color="primary" variant="contained" onClick={this.handleCreateOfferButtonPressed}>{t("Create Order")}</Button>
} }
</Grid> </Grid>
@ -701,18 +702,31 @@ export default class MakerPage extends Component {
: ""} : ""}
<Typography component="subtitle2" variant="subtitle2"> <Typography component="subtitle2" variant="subtitle2">
<div align='center'> <div align='center'>
Create a BTC {this.state.type==0 ? "buy":"sell"} order for {this.state.enableAmountRange & this.state.minAmount != null? {this.state.type==0 ?
" "+this.state.minAmount+"-"+this.state.maxAmount : pn(this.state.amount)} {this.state.currencyCode} t("Create a BTC buy order for ")
{this.state.is_explicit ? " of " + pn(this.state.satoshis) + " Satoshis" : :
(this.state.premium == 0 ? " at market price" : t("Create a BTC sell order for ")
(this.state.premium > 0 ? " at a " + this.state.premium + "% premium":" at a " + -this.state.premium + "% discount") }
{this.state.enableAmountRange & this.state.minAmount != null?
this.state.minAmount+"-"+this.state.maxAmount
:
pn(this.state.amount)}
{" " + this.state.currencyCode}
{this.state.is_explicit ?
t(" of {{satoshis}} Satoshis",{satoshis: pn(this.state.satoshis)})
:
(this.state.premium == 0 ? t(" at market price") :
(this.state.premium > 0 ?
t(" at a {{premium}}% premium", {premium: this.state.premium})
:
t(" at a {{discount}}% discount", {discount: -this.state.premium}))
) )
} }
</div> </div>
</Typography> </Typography>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button color="secondary" variant="contained" to="/" component={LinkRouter}> <Button color="secondary" variant="contained" to="/" component={LinkRouter}>
Back {t("Back")}
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>
@ -720,3 +734,5 @@ export default class MakerPage extends Component {
); );
} }
} }
export default withTranslation()(MakerPage);

View File

@ -1,7 +1,9 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { withTranslation, Trans} from "react-i18next";
import {TextField,Chip, Tooltip, Badge, Tab, Tabs, Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material" import {TextField,Chip, Tooltip, Badge, Tab, Tabs, Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
import Countdown, { zeroPad, calcTimeDelta } from 'react-countdown'; import Countdown, { zeroPad, calcTimeDelta } from 'react-countdown';
import MediaQuery from 'react-responsive' import MediaQuery from 'react-responsive'
import currencyDict from '../../static/assets/currencies.json';
import PaymentText from './PaymentText' import PaymentText from './PaymentText'
import TradeBox from "./TradeBox"; import TradeBox from "./TradeBox";
@ -13,6 +15,7 @@ import NumbersIcon from '@mui/icons-material/Numbers';
import PriceChangeIcon from '@mui/icons-material/PriceChange'; import PriceChangeIcon from '@mui/icons-material/PriceChange';
import PaymentsIcon from '@mui/icons-material/Payments'; import PaymentsIcon from '@mui/icons-material/Payments';
import ArticleIcon from '@mui/icons-material/Article'; import ArticleIcon from '@mui/icons-material/Article';
import { t } from "i18next";
function getCookie(name) { function getCookie(name) {
let cookieValue = null; let cookieValue = null;
@ -38,13 +41,12 @@ function pn(x) {
return parts.join("."); return parts.join(".");
} }
export default class OrderPage extends Component { class OrderPage extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
is_explicit: false, is_explicit: false,
delay: 60000, // Refresh every 60 seconds by default delay: 60000, // Refresh every 60 seconds by default
currencies_dict: {"1":"USD"},
total_secs_exp: 300, total_secs_exp: 300,
loading: true, loading: true,
openCancel: false, openCancel: false,
@ -53,7 +55,6 @@ export default class OrderPage extends Component {
showContractBox: 1, showContractBox: 1,
}; };
this.orderId = this.props.match.params.orderId; this.orderId = this.props.match.params.orderId;
this.getCurrencyDict();
this.getOrderDetails(); this.getOrderDetails();
// Refresh delays according to Order status // Refresh delays according to Order status
@ -127,9 +128,10 @@ export default class OrderPage extends Component {
// Countdown Renderer callback with condition // Countdown Renderer callback with condition
countdownRenderer = ({ total, hours, minutes, seconds, completed }) => { countdownRenderer = ({ total, hours, minutes, seconds, completed }) => {
const { t } = this.props;
if (completed) { if (completed) {
// Render a completed state // Render a completed state
return (<span> The order has expired</span>); return (<span> {t("The order has expired")}</span>);
} else { } else {
var col = 'inherit' var col = 'inherit'
@ -148,13 +150,14 @@ export default class OrderPage extends Component {
// Countdown Renderer callback with condition // Countdown Renderer callback with condition
countdownPenaltyRenderer = ({ minutes, seconds, completed }) => { countdownPenaltyRenderer = ({ minutes, seconds, completed }) => {
const { t } = this.props;
if (completed) { if (completed) {
// Render a completed state // Render a completed state
return (<span> Penalty lifted, good to go!</span>); return (<span> {t("Penalty lifted, good to go!")}</span>);
} else { } else {
return ( return (
<span> You cannot take an order yet! Wait {zeroPad(minutes)}m {zeroPad(seconds)}s </span> <span> {t("You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s",{timeMin: zeroPad(minutes), timeSec: zeroPad(seconds) })} </span>
); );
} }
}; };
@ -168,27 +171,29 @@ export default class OrderPage extends Component {
} }
amountHelperText=()=>{ amountHelperText=()=>{
const { t } = this.props;
if(this.state.takeAmount < this.state.min_amount & this.state.takeAmount != ""){ if(this.state.takeAmount < this.state.min_amount & this.state.takeAmount != ""){
return "Too low" return t("Too low")
}else if (this.state.takeAmount > this.state.max_amount & this.state.takeAmount != ""){ }else if (this.state.takeAmount > this.state.max_amount & this.state.takeAmount != ""){
return "Too high" return t("Too high")
}else{ }else{
return null return null
} }
} }
takeOrderButton = () => { takeOrderButton = () => {
const { t } = this.props;
if(this.state.has_range){ if(this.state.has_range){
return( return(
<Grid containter xs={12} align="center" alignItems="stretch" justifyContent="center" style={{ display: "flex"}}> <Grid containter xs={12} align="center" alignItems="stretch" justifyContent="center" style={{ display: "flex"}}>
<this.InactiveMakerDialog/> <this.InactiveMakerDialog/>
<div style={{maxWidth:120}}> <div style={{maxWidth:120}}>
<Tooltip placement="top" enterTouchDelay="500" enterDelay="700" enterNextDelay="2000" title="Enter amount of fiat to exchange for bitcoin"> <Tooltip placement="top" enterTouchDelay="500" enterDelay="700" enterNextDelay="2000" title={t("Enter amount of fiat to exchange for bitcoin")}>
<Paper elevation={5} sx={{maxHeight:40}}> <Paper elevation={5} sx={{maxHeight:40}}>
<TextField <TextField
error={(this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount) & this.state.takeAmount != "" } error={(this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount) & this.state.takeAmount != "" }
helperText={this.amountHelperText()} helperText={this.amountHelperText()}
label={"Amount "+this.state.currencyCode} label={t("Amount {{currencyCode}}", {currencyCode: this.state.currencyCode})}
size="small" size="small"
type="number" type="number"
required="true" required="true"
@ -204,11 +209,11 @@ export default class OrderPage extends Component {
</Tooltip> </Tooltip>
</div> </div>
<div style={{height:38, top:'1px', position:'relative', display: (this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount || this.state.takeAmount == "" || this.state.takeAmount == null) ? '':'none'}}> <div style={{height:38, top:'1px', position:'relative', display: (this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount || this.state.takeAmount == "" || this.state.takeAmount == null) ? '':'none'}}>
<Tooltip placement="top" enterTouchDelay="0" enterDelay="500" enterNextDelay="1200" title="You must specify an amount first"> <Tooltip placement="top" enterTouchDelay="0" enterDelay="500" enterNextDelay="1200" title={t("You must specify an amount first")}>
<Paper elevation={4}> <Paper elevation={4}>
<Button sx={{height:38}} variant='contained' color='primary' <Button sx={{height:38}} variant='contained' color='primary'
disabled={true}> disabled={true}>
Take Order {t("Take Order")}
</Button> </Button>
</Paper> </Paper>
</Tooltip> </Tooltip>
@ -217,7 +222,7 @@ export default class OrderPage extends Component {
<Paper elevation={4}> <Paper elevation={4}>
<Button sx={{height:38}} variant='contained' color='primary' <Button sx={{height:38}} variant='contained' color='primary'
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}> onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
Take Order {t("Take Order")}
</Button> </Button>
</Paper> </Paper>
</div> </div>
@ -229,7 +234,7 @@ export default class OrderPage extends Component {
<this.InactiveMakerDialog/> <this.InactiveMakerDialog/>
<Button variant='contained' color='primary' <Button variant='contained' color='primary'
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}> onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
Take Order {t("Take Order")}
</Button> </Button>
</> </>
) )
@ -243,8 +248,8 @@ export default class OrderPage extends Component {
return ( <this.takeOrderButton/>); return ( <this.takeOrderButton/>);
} else{ } else{
return( return(
<Tooltip enterTouchDelay="0" title="Wait until you can take an order"><div> <Tooltip enterTouchDelay="0" title={t("Wait until you can take an order")}><div>
<Button disabled={true} variant='contained' color='primary'>Take Order</Button> <Button disabled={true} variant='contained' color='primary'>{t("Take Order")}</Button>
</div></Tooltip>) </div></Tooltip>)
} }
}; };
@ -274,7 +279,6 @@ export default class OrderPage extends Component {
takeOrder=()=>{ takeOrder=()=>{
this.setState({loading:true}) this.setState({loading:true})
console.log(this.state.takeAmount)
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
@ -288,22 +292,13 @@ export default class OrderPage extends Component {
.then((data) => this.completeSetState(data)); .then((data) => this.completeSetState(data));
} }
getCurrencyDict() {
fetch('/static/assets/currencies.json')
.then((response) => response.json())
.then((data) =>
this.setState({
currencies_dict: data
}));
}
// set delay to the one matching the order status. If null order status, delay goes to 9999999. // set delay to the one matching the order status. If null order status, delay goes to 9999999.
setDelay = (status)=>{ setDelay = (status)=>{
return status >= 0 ? this.statusToDelay[status.toString()] : 99999999; return status >= 0 ? this.statusToDelay[status.toString()] : 99999999;
} }
getCurrencyCode(val){ getCurrencyCode(val){
let code = val ? this.state.currencies_dict[val.toString()] : "" let code = val ? currencyDict[val.toString()] : ""
return code return code
} }
@ -330,6 +325,7 @@ export default class OrderPage extends Component {
}; };
CancelDialog =() =>{ CancelDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openCancel} open={this.state.openCancel}
@ -338,16 +334,16 @@ export default class OrderPage extends Component {
aria-describedby="cancel-dialog-description" aria-describedby="cancel-dialog-description"
> >
<DialogTitle id="cancel-dialog-title"> <DialogTitle id="cancel-dialog-title">
{"Cancel the order?"} {t("Cancel the order?")}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText id="cancel-dialog-description"> <DialogContentText id="cancel-dialog-description">
If the order is cancelled now you will lose your bond. {t("If the order is cancelled now you will lose your bond.")}
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={this.handleClickCloseConfirmCancelDialog} autoFocus>Go back</Button> <Button onClick={this.handleClickCloseConfirmCancelDialog} autoFocus>{t("Go back")}</Button>
<Button onClick={this.handleClickConfirmCancelButton}> Confirm Cancel </Button> <Button onClick={this.handleClickConfirmCancelButton}>{t("Confirm Cancel")}</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
@ -361,6 +357,7 @@ export default class OrderPage extends Component {
}; };
InactiveMakerDialog =() =>{ InactiveMakerDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openInactiveMaker} open={this.state.openInactiveMaker}
@ -369,17 +366,16 @@ export default class OrderPage extends Component {
aria-describedby="inactive-maker-description" aria-describedby="inactive-maker-description"
> >
<DialogTitle id="inactive-maker-dialog-title"> <DialogTitle id="inactive-maker-dialog-title">
{"The maker is away"} {t("The maker is away")}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText id="cancel-dialog-description"> <DialogContentText id="cancel-dialog-description">
By taking this order you risk wasting your time. {t("By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.")}
If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={this.handleClickCloseInactiveMakerDialog} autoFocus>Go back</Button> <Button onClick={this.handleClickCloseInactiveMakerDialog} autoFocus>{t("Go back")}</Button>
<Button onClick={this.takeOrder}> Take Order </Button> <Button onClick={this.takeOrder}>{t("Take Order")}</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
@ -406,6 +402,7 @@ export default class OrderPage extends Component {
}; };
CollaborativeCancelDialog =() =>{ CollaborativeCancelDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openCollaborativeCancel} open={this.state.openCollaborativeCancel}
@ -414,41 +411,41 @@ export default class OrderPage extends Component {
aria-describedby="collaborative-cancel-dialog-description" aria-describedby="collaborative-cancel-dialog-description"
> >
<DialogTitle id="cancel-dialog-title"> <DialogTitle id="cancel-dialog-title">
{"Collaborative cancel the order?"} {t("Collaborative cancel the order?")}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText id="cancel-dialog-description"> <DialogContentText id="cancel-dialog-description">
The trade escrow has been posted. The order can be cancelled only if both, maker and {t("The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.")}
taker, agree to cancel.
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={this.handleClickCloseCollaborativeCancelDialog} autoFocus>Go back</Button> <Button onClick={this.handleClickCloseCollaborativeCancelDialog} autoFocus>{t("Go back")}</Button>
<Button onClick={this.handleClickConfirmCollaborativeCancelButton}> Ask for Cancel </Button> <Button onClick={this.handleClickConfirmCollaborativeCancelButton}>{t("Ask for Cancel")}</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
} }
BackButton = () => { BackButton = () => {
const { t } = this.props;
// If order has expired, show back button. // If order has expired, show back button.
if (this.state.status == 5){ if (this.state.status == 5){
return( return(
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button variant='contained' color='secondary' onClick={this.props.history.goBack}>Back</Button> <Button variant='contained' color='secondary' onClick={this.props.history.goBack}>{t("Back")}</Button>
</Grid> </Grid>
)} )}
return(null) return(null)
} }
CancelButton = () => { CancelButton = () => {
const { t } = this.props;
// If maker and Waiting for Bond. Or if taker and Waiting for bond. // If maker and Waiting for Bond. Or if taker and Waiting for bond.
// Simply allow to cancel without showing the cancel dialog. // Simply allow to cancel without showing the cancel dialog.
if ((this.state.is_maker & [0,1].includes(this.state.status)) || this.state.is_taker & this.state.status == 3){ if ((this.state.is_maker & [0,1].includes(this.state.status)) || this.state.is_taker & this.state.status == 3){
return( return(
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button variant='contained' color='secondary' onClick={this.handleClickConfirmCancelButton}>Cancel</Button> <Button variant='contained' color='secondary' onClick={this.handleClickConfirmCancelButton}>{t("Cancel")}</Button>
</Grid> </Grid>
)} )}
// If the order does not yet have an escrow deposited. Show dialog // If the order does not yet have an escrow deposited. Show dialog
@ -458,7 +455,7 @@ export default class OrderPage extends Component {
<div id="openDialogCancelButton"> <div id="openDialogCancelButton">
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<this.CancelDialog/> <this.CancelDialog/>
<Button variant='contained' color='secondary' onClick={this.handleClickOpenConfirmCancelDialog}>Cancel</Button> <Button variant='contained' color='secondary' onClick={this.handleClickOpenConfirmCancelDialog}>{t("Cancel")}</Button>
</Grid> </Grid>
</div> </div>
)} )}
@ -469,7 +466,7 @@ export default class OrderPage extends Component {
return( return(
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<this.CollaborativeCancelDialog/> <this.CollaborativeCancelDialog/>
<Button variant='contained' color='secondary' onClick={this.handleClickOpenCollaborativeCancelDialog}>Collaborative Cancel</Button> <Button variant='contained' color='secondary' onClick={this.handleClickOpenCollaborativeCancelDialog}>{t("Collaborative Cancel")}</Button>
</Grid> </Grid>
)} )}
@ -485,19 +482,20 @@ export default class OrderPage extends Component {
} }
orderBox=()=>{ orderBox=()=>{
const { t } = this.props;
return( return(
<Grid container spacing={1} > <Grid container spacing={1} >
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<MediaQuery minWidth={920}> <MediaQuery minWidth={920}>
<Typography component="h5" variant="h5"> <Typography component="h5" variant="h5">
Order Box {t("Order Box")}
</Typography> </Typography>
</MediaQuery> </MediaQuery>
<Paper elevation={12} style={{ padding: 8,}}> <Paper elevation={12} style={{ padding: 8,}}>
<List dense="true"> <List dense="true">
<ListItem > <ListItem >
<ListItemAvatar sx={{ width: 56, height: 56 }}> <ListItemAvatar sx={{ width: 56, height: 56 }}>
<Tooltip placement="top" enterTouchDelay="0" title={this.state.maker_status} > <Tooltip placement="top" enterTouchDelay="0" title={t(this.state.maker_status)} >
<Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(this.state.maker_status)}> <Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(this.state.maker_status)}>
<Avatar className="flippedSmallAvatar" <Avatar className="flippedSmallAvatar"
alt={this.state.maker_nick} alt={this.state.maker_nick}
@ -506,7 +504,7 @@ export default class OrderPage extends Component {
</Badge> </Badge>
</Tooltip> </Tooltip>
</ListItemAvatar> </ListItemAvatar>
<ListItemText primary={this.state.maker_nick + (this.state.type ? " (Seller)" : " (Buyer)")} secondary="Order maker" align="right"/> <ListItemText primary={this.state.maker_nick + (this.state.type ? " "+t("(Seller)") : " "+t("(Buyer)") )} secondary={t("Order maker")} align="right"/>
</ListItem> </ListItem>
{this.state.is_participant ? {this.state.is_participant ?
@ -515,9 +513,9 @@ export default class OrderPage extends Component {
<> <>
<Divider /> <Divider />
<ListItem align="left"> <ListItem align="left">
<ListItemText primary={this.state.taker_nick + (this.state.type ? " (Buyer)" : " (Seller)")} secondary="Order taker"/> <ListItemText primary={this.state.taker_nick + (this.state.type ? " "+t("(Buyer)") : " "+t("(Seller)"))} secondary={t("Order taker")}/>
<ListItemAvatar > <ListItemAvatar >
<Tooltip enterTouchDelay="0" title={this.state.taker_status} > <Tooltip enterTouchDelay="0" title={t(this.state.taker_status)} >
<Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(this.state.taker_status)}> <Badge variant="dot" overlap="circular" badgeContent="" color={this.statusBadgeColor(this.state.taker_status)}>
<Avatar className="smallAvatar" <Avatar className="smallAvatar"
alt={this.state.taker_nick} alt={this.state.taker_nick}
@ -530,16 +528,16 @@ export default class OrderPage extends Component {
</>: </>:
"" ""
} }
<Divider><Chip label='Order Details'/></Divider> <Divider><Chip label={t("Order Details")}/></Divider>
<ListItem> <ListItem>
<ListItemIcon> <ListItemIcon>
<ArticleIcon/> <ArticleIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={this.state.status_message} secondary="Order status"/> <ListItemText primary={t(this.state.status_message)} secondary={t("Order status")}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
</> </>
:<Divider><Chip label='Order Details'/></Divider> :<Divider><Chip label={t("Order Details")}/></Divider>
} }
<ListItem> <ListItem>
@ -550,10 +548,10 @@ export default class OrderPage extends Component {
</ListItemIcon> </ListItemIcon>
{this.state.has_range & this.state.amount == null ? {this.state.has_range & this.state.amount == null ?
<ListItemText primary={parseFloat(Number(this.state.min_amount).toPrecision(2)) <ListItemText primary={parseFloat(Number(this.state.min_amount).toPrecision(2))
+"-" + parseFloat(Number(this.state.max_amount).toPrecision(2)) +" "+this.state.currencyCode} secondary="Amount range"/> +"-" + parseFloat(Number(this.state.max_amount).toPrecision(2)) +" "+this.state.currencyCode} secondary={t("Amount range")}/>
: :
<ListItemText primary={parseFloat(parseFloat(this.state.amount).toFixed(4)) <ListItemText primary={parseFloat(parseFloat(this.state.amount).toFixed(4))
+" "+this.state.currencyCode} secondary="Amount"/> +" "+this.state.currencyCode} secondary={t("Amount")}/>
} }
</ListItem> </ListItem>
@ -563,7 +561,7 @@ export default class OrderPage extends Component {
<ListItemIcon> <ListItemIcon>
<PaymentsIcon/> <PaymentsIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={<PaymentText size={20} verbose={true} text={this.state.payment_method}/>} secondary={this.state.currency==1000 ? "Swap destination":"Accepted payment methods"}/> <ListItemText primary={<PaymentText size={20} othersText={t("Others")} verbose={true} text={this.state.payment_method}/>} secondary={this.state.currency==1000 ? t("Swap destination"):t("Accepted payment methods")}/>
</ListItem> </ListItem>
<Divider /> <Divider />
@ -573,12 +571,12 @@ export default class OrderPage extends Component {
<PriceChangeIcon/> <PriceChangeIcon/>
</ListItemIcon> </ListItemIcon>
{this.state.price_now? {this.state.price_now?
<ListItemText primary={pn(this.state.price_now)+" "+this.state.currencyCode+"/BTC - Premium: "+this.state.premium_now+"%"} secondary="Price and Premium"/> <ListItemText primary={t("{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%", {price: pn(this.state.price_now), currencyCode:this.state.currencyCode, premium: this.state.premium_now})} secondary={t("Price and Premium")}/>
: :
(this.state.is_explicit ? (this.state.is_explicit ?
<ListItemText primary={pn(this.state.satoshis)} secondary="Amount of Satoshis"/> <ListItemText primary={pn(this.state.satoshis)} secondary={t("Amount of Satoshis")}/>
: :
<ListItemText primary={parseFloat(parseFloat(this.state.premium).toFixed(2))+"%"} secondary="Premium over market price"/> <ListItemText primary={parseFloat(parseFloat(this.state.premium).toFixed(2))+"%"} secondary={t("Premium over market price")}/>
) )
} }
</ListItem> </ListItem>
@ -588,14 +586,14 @@ export default class OrderPage extends Component {
<ListItemIcon> <ListItemIcon>
<NumbersIcon/> <NumbersIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={this.orderId} secondary="Order ID"/> <ListItemText primary={this.orderId} secondary={t("Order ID")}/>
</ListItem> </ListItem>
<Divider /> <Divider />
<ListItem> <ListItem>
<ListItemIcon> <ListItemIcon>
<AccessTimeIcon/> <AccessTimeIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText secondary="Expires in"> <ListItemText secondary={t("Expires in")}>
<Countdown date={new Date(this.state.expires_at)} renderer={this.countdownRenderer} /> <Countdown date={new Date(this.state.expires_at)} renderer={this.countdownRenderer} />
</ListItemText> </ListItemText>
</ListItem> </ListItem>
@ -620,7 +618,7 @@ export default class OrderPage extends Component {
<Divider /> <Divider />
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Alert severity="warning" sx={{maxWidth:360}}> <Alert severity="warning" sx={{maxWidth:360}}>
{this.state.is_maker ? this.state.taker_nick : this.state.maker_nick} is asking for a collaborative cancel {t("{{nickname}} is asking for a collaborative cancel", {nickname: this.state.is_maker ? this.state.taker_nick : this.state.maker_nick})}
</Alert> </Alert>
</Grid> </Grid>
</> </>
@ -632,7 +630,7 @@ export default class OrderPage extends Component {
<Divider /> <Divider />
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Alert severity="warning" sx={{maxWidth:360}}> <Alert severity="warning" sx={{maxWidth:360}}>
You asked for a collaborative cancellation {t("You asked for a collaborative cancellation")}
</Alert> </Alert>
</Grid> </Grid>
</> </>
@ -654,7 +652,7 @@ export default class OrderPage extends Component {
<Countdown date={new Date(this.state.penalty)} renderer={this.countdownTakeOrderRenderer} /> <Countdown date={new Date(this.state.penalty)} renderer={this.countdownTakeOrderRenderer} />
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button variant='contained' color='secondary' onClick={this.props.history.goBack}>Back</Button> <Button variant='contained' color='secondary' onClick={this.props.history.goBack}>{t("Back")}</Button>
</Grid> </Grid>
</Grid> </Grid>
} }
@ -684,7 +682,7 @@ export default class OrderPage extends Component {
} }
doubleOrderPagePhone=()=>{ doubleOrderPagePhone=()=>{
const { t } = this.props;
const [value, setValue] = React.useState(this.state.showContractBox); const [value, setValue] = React.useState(this.state.showContractBox);
const handleChange = (event, newValue) => { const handleChange = (event, newValue) => {
@ -696,8 +694,8 @@ export default class OrderPage extends Component {
<Box sx={{ width: '100%'}}> <Box sx={{ width: '100%'}}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}> <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={value} onChange={handleChange} variant="fullWidth" > <Tabs value={value} onChange={handleChange} variant="fullWidth" >
<Tab label="Order" {...this.a11yProps(0)} /> <Tab label={t("Order")} {...this.a11yProps(0)} />
<Tab label="Contract" {...this.a11yProps(1)} /> <Tab label={t("Contract")} {...this.a11yProps(1)} />
</Tabs> </Tabs>
</Box> </Box>
<Grid container spacing={2}> <Grid container spacing={2}>
@ -715,13 +713,15 @@ export default class OrderPage extends Component {
} }
orderDetailsPage (){ orderDetailsPage (){
const { t } = this.props;
return( return(
this.state.bad_request ? this.state.bad_request ?
<div align='center'> <div align='center'>
<Typography component="subtitle2" variant="subtitle2" color="secondary" > <Typography component="subtitle2" variant="subtitle2" color="secondary" >
{this.state.bad_request}<br/> {/* IMPLEMENT I18N for bad_request */}
{t(this.state.bad_request)}<br/>
</Typography> </Typography>
<Button variant='contained' color='secondary' onClick={this.props.history.goBack}>Back</Button> <Button variant='contained' color='secondary' onClick={this.props.history.goBack}>{t("Back")}</Button>
</div> </div>
: :
(this.state.is_participant ? (this.state.is_participant ?
@ -750,3 +750,5 @@ export default class OrderPage extends Component {
); );
} }
} }
export default withTranslation()(OrderPage);

View File

@ -1,4 +1,3 @@
import { TextField } from '@mui/material';
import React, { Component } from 'react'; import React, { Component } from 'react';
import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize'; import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize';

View File

@ -1,7 +1,6 @@
import PaymentIcon from './PaymentIcons'
import React, { Component } from 'react' import React, { Component } from 'react'
import PaymentIcon from './PaymentIcons'
import {Tooltip} from "@mui/material" import {Tooltip} from "@mui/material"
import { intlFormat } from 'date-fns';
const someMethods = [ const someMethods = [
{name: "Revolut",icon:'revolut'}, {name: "Revolut",icon:'revolut'},
@ -69,7 +68,7 @@ export default class PaymentText extends Component {
chars_left = chars_left.replace(' ','') chars_left = chars_left.replace(' ','')
if(chars_left.length > 0){rows.push( if(chars_left.length > 0){rows.push(
<Tooltip placement="top" enterTouchDelay="0" title={this.props.verbose ? "Others": "Other: "+ custom_methods} > <Tooltip placement="top" enterTouchDelay="0" title={this.props.verbose ? this.props.othersText: this.props.othersText+": "+ custom_methods} >
<div style={{position:'relative', display: 'inline-block',width: this.props.size+2, maxHeight: this.props.size, top:'-1px'}}> <div style={{position:'relative', display: 'inline-block',width: this.props.size+2, maxHeight: this.props.size, top:'-1px'}}>
<PaymentIcon width={this.props.size*1.1} height={this.props.size*1.1} icon={"custom"}/> <PaymentIcon width={this.props.size*1.1} height={this.props.size*1.1} icon={"custom"}/>
</div> </div>

View File

@ -1,4 +1,5 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { withTranslation, Trans} from "react-i18next";
import { IconButton, Box, Link, Paper, Rating, Button, Tooltip, CircularProgress, Grid, Typography, TextField, List, ListItem, ListItemText, Divider, ListItemIcon, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material" import { IconButton, Box, Link, Paper, Rating, Button, Tooltip, CircularProgress, Grid, Typography, TextField, List, ListItem, ListItemText, Divider, ListItemIcon, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
import QRCode from "react-qr-code"; import QRCode from "react-qr-code";
import Countdown, { zeroPad} from 'react-countdown'; import Countdown, { zeroPad} from 'react-countdown';
@ -40,7 +41,7 @@ function pn(x) {
return parts.join("."); return parts.join(".");
} }
export default class TradeBox extends Component { class TradeBox extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -53,6 +54,8 @@ export default class TradeBox extends Component {
} }
} }
Sound = ({soundFileName}) => ( Sound = ({soundFileName}) => (
// Four filenames: "locked-invoice", "taker-found", "open-chat", "successful" // Four filenames: "locked-invoice", "taker-found", "open-chat", "successful"
<audio autoPlay src={`/static/assets/sounds/${soundFileName}.mp3`} /> <audio autoPlay src={`/static/assets/sounds/${soundFileName}.mp3`} />
@ -129,6 +132,7 @@ export default class TradeBox extends Component {
} }
ConfirmDisputeDialog =() =>{ ConfirmDisputeDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openConfirmDispute} open={this.state.openConfirmDispute}
@ -137,19 +141,16 @@ export default class TradeBox extends Component {
aria-describedby="open-dispute-dialog-description" aria-describedby="open-dispute-dialog-description"
> >
<DialogTitle id="open-dispute-dialog-title"> <DialogTitle id="open-dispute-dialog-title">
{"Do you want to open a dispute?"} {t("Do you want to open a dispute?")}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText id="alert-dialog-description"> <DialogContentText id="alert-dialog-description">
The RoboSats staff will examine the statements and evidence provided. You need to build {t("The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.")}
a complete case, as the staff cannot read the chat. It is best to provide a burner contact
method with your statement. The satoshis in the trade escrow will be sent to the dispute winner,
while the dispute loser will lose the bond.
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={this.handleClickCloseConfirmDispute} autoFocus>Disagree</Button> <Button onClick={this.handleClickCloseConfirmDispute} autoFocus>{t("Disagree")}</Button>
<Button onClick={this.handleClickAgreeDisputeButton}> Agree and open dispute </Button> <Button onClick={this.handleClickAgreeDisputeButton}>{t("Agree and open dispute")}</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
@ -168,6 +169,7 @@ export default class TradeBox extends Component {
}; };
ConfirmFiatReceivedDialog =() =>{ ConfirmFiatReceivedDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openConfirmFiatReceived} open={this.state.openConfirmFiatReceived}
@ -176,40 +178,42 @@ export default class TradeBox extends Component {
aria-describedby="fiat-received-dialog-description" aria-describedby="fiat-received-dialog-description"
> >
<DialogTitle id="open-dispute-dialog-title"> <DialogTitle id="open-dispute-dialog-title">
{"Confirm you received " +this.props.data.currencyCode+ "?"} {t("Confirm you received {{currencyCode}}?", {currencyCode: this.props.data.currencyCode})}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText id="alert-dialog-description"> <DialogContentText id="alert-dialog-description">
Confirming that you received the fiat will finalize the trade. The satoshis {t("Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.",{currencyCode: this.props.data.currencyCode})}
in the escrow will be released to the buyer. Only confirm after the {this.props.data.currencyCode+ " "}
has arrived to your account. In addition, if you have received {this.props.data.currencyCode+ " "}
and do not confirm the receipt, you risk losing your bond.
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={this.handleClickCloseConfirmFiatReceived} autoFocus>Go back</Button> <Button onClick={this.handleClickCloseConfirmFiatReceived} autoFocus>{t("Go back")}</Button>
<Button onClick={this.handleClickTotallyConfirmFiatReceived}> Confirm </Button> <Button onClick={this.handleClickTotallyConfirmFiatReceived}>{t("Confirm")}</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
} }
showQRInvoice=()=>{ showQRInvoice=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
Robots show commitment to their peers {t("Robots show commitment to their peers")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
{this.props.data.is_maker ? {this.props.data.is_maker ?
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b>Lock {pn(this.props.data.bond_satoshis)} Sats to PUBLISH order </b> {" " + this.stepXofY()} <b>
{t("Lock {{amountSats}} Sats to PUBLISH order", {amountSats: pn(this.props.data.bond_satoshis)})}
</b> {" " + this.stepXofY()}
</Typography> </Typography>
: :
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b>Lock {pn(this.props.data.bond_satoshis)} Sats to TAKE the order </b> {" " + this.stepXofY()} <b>
{t("Lock {{amountSats}} Sats to TAKE order", {amountSats: pn(this.props.data.bond_satoshis)})}
</b> {" " + this.stepXofY()}
</Typography> </Typography>
} }
</Grid> </Grid>
@ -217,8 +221,8 @@ export default class TradeBox extends Component {
<Box sx={{bgcolor:'#ffffff', width:'315px', position:'relative', left:'-5px'}} > <Box sx={{bgcolor:'#ffffff', width:'315px', position:'relative', left:'-5px'}} >
<QRCode value={this.props.data.bond_invoice} size={305} style={{position:'relative', top:'3px'}}/> <QRCode value={this.props.data.bond_invoice} size={305} style={{position:'relative', top:'3px'}}/>
</Box> </Box>
<Tooltip disableHoverListener enterTouchDelay="0" title="Copied!"> <Tooltip disableHoverListener enterTouchDelay="0" title={t("Copied!")}>
<Button size="small" color="inherit" onClick={() => {navigator.clipboard.writeText(this.props.data.bond_invoice)}} align="center"> <ContentCopy/> Copy to clipboard</Button> <Button size="small" color="inherit" onClick={() => {navigator.clipboard.writeText(this.props.data.bond_invoice)}} align="center"> <ContentCopy/>{t("Copy to clipboard")}</Button>
</Tooltip> </Tooltip>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
@ -228,7 +232,7 @@ export default class TradeBox extends Component {
size="small" size="small"
defaultValue={this.props.data.bond_invoice} defaultValue={this.props.data.bond_invoice}
disabled="true" disabled="true"
helperText="This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute." helperText={t("This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.")}
color = "secondary" color = "secondary"
/> />
</Grid> </Grid>
@ -237,12 +241,13 @@ export default class TradeBox extends Component {
} }
showBondIsLocked=()=>{ showBondIsLocked=()=>{
const {t} = this.props
return ( return (
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1" align="center"> <Typography color="primary" component="subtitle1" variant="subtitle1" align="center">
<div style={{display:'flex', alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}> <div style={{display:'flex', alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}>
<LockIcon/> <LockIcon/>
{" Your " + (this.props.data.is_maker ? 'maker' : 'taker')+" bond is locked"} {this.props.data.is_maker ? t("Your maker bond is locked") : t("Your taker bond is locked")}
</div> </div>
</Typography> </Typography>
</Grid> </Grid>
@ -250,12 +255,13 @@ export default class TradeBox extends Component {
} }
showBondIsSettled=()=>{ showBondIsSettled=()=>{
const { t } = this.props;
return ( return (
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="error" component="subtitle1" variant="subtitle1" align="center"> <Typography color="error" component="subtitle1" variant="subtitle1" align="center">
<div style={{display:'flex',alignItems:'center', justifyContent:'center', flexWrap:'wrap', align:"center"}} align="center"> <div style={{display:'flex',alignItems:'center', justifyContent:'center', flexWrap:'wrap', align:"center"}} align="center">
<BalanceIcon/> <BalanceIcon/>
{" Your " + (this.props.data.is_maker ? 'maker' : 'taker')+" bond was settled"} {this.props.data.is_maker ? t("Your maker bond was settled") : t("Your taker bond was settled")}
</div> </div>
</Typography> </Typography>
</Grid> </Grid>
@ -263,12 +269,13 @@ export default class TradeBox extends Component {
} }
showBondIsReturned=()=>{ showBondIsReturned=()=>{
const { t } = this.props;
return ( return (
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="green" component="subtitle1" variant="subtitle1" align="center"> <Typography color="green" component="subtitle1" variant="subtitle1" align="center">
<div style={{display:'flex',alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}> <div style={{display:'flex',alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}>
<LockOpenIcon/> <LockOpenIcon/>
{" Your " + (this.props.data.is_maker ? 'maker' : 'taker')+" bond was unlocked"} {this.props.data.is_maker ? t("Your maker bond was unlock") : t("Your taker bond was unlocked")}
</div> </div>
</Typography> </Typography>
</Grid> </Grid>
@ -276,20 +283,23 @@ export default class TradeBox extends Component {
} }
showEscrowQRInvoice=()=>{ showEscrowQRInvoice=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
{/* Make confirmation sound for HTLC received. */} {/* Make confirmation sound for HTLC received. */}
<this.Sound soundFileName="locked-invoice"/> <this.Sound soundFileName="locked-invoice"/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="green" component="subtitle1" variant="subtitle1"> <Typography color="green" component="subtitle1" variant="subtitle1">
<b>Lock {pn(this.props.data.escrow_satoshis)} Sats as collateral </b> {" " + this.stepXofY()} <b>
{t("Lock {{amountSats}} Sats as collateral", {amountSats:pn(this.props.data.escrow_satoshis)})}
</b>{" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Box sx={{bgcolor:'#ffffff', width:'315px', position:'relative', left:'-5px'}} > <Box sx={{bgcolor:'#ffffff', width:'315px', position:'relative', left:'-5px'}} >
<QRCode value={this.props.data.escrow_invoice} size={305} style={{position:'relative', top:'3px'}}/> <QRCode value={this.props.data.escrow_invoice} size={305} style={{position:'relative', top:'3px'}}/>
</Box> </Box>
<Tooltip disableHoverListener enterTouchDelay="0" title="Copied!"> <Tooltip disableHoverListener enterTouchDelay="0" title={t("Copied!")}>
<Button size="small" color="inherit" onClick={() => {navigator.clipboard.writeText(this.props.data.escrow_invoice)}} align="center"> <ContentCopy/>Copy to clipboard</Button> <Button size="small" color="inherit" onClick={() => {navigator.clipboard.writeText(this.props.data.escrow_invoice)}} align="center"> <ContentCopy/>Copy to clipboard</Button>
</Tooltip> </Tooltip>
</Grid> </Grid>
@ -300,7 +310,7 @@ export default class TradeBox extends Component {
size="small" size="small"
defaultValue={this.props.data.escrow_invoice} defaultValue={this.props.data.escrow_invoice}
disabled="true" disabled="true"
helperText={"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the "+this.props.data.currencyCode+"."} helperText={t("This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.",{currencyCode: this.props.data.currencyCode})}
color = "secondary" color = "secondary"
/> />
</Grid> </Grid>
@ -310,21 +320,20 @@ export default class TradeBox extends Component {
} }
showTakerFound=()=>{ showTakerFound=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
{/* Make bell sound when taker is found */} {/* Make bell sound when taker is found */}
<this.Sound soundFileName="taker-found"/> <this.Sound soundFileName="taker-found"/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1"> <Typography component="subtitle1" variant="subtitle1">
<b>A taker has been found! </b> {" " + this.stepXofY()} <b>{t("A taker has been found!")}</b> {" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Divider/> <Divider/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
Please wait for the taker to lock a bond. {t("Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.")}
If the taker does not lock a bond in time, the order will be made
public again.
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsLocked()} {this.showBondIsLocked()}
@ -345,6 +354,7 @@ export default class TradeBox extends Component {
}; };
EnableTelegramDialog =() =>{ EnableTelegramDialog =() =>{
const { t } = this.props;
return( return(
<Dialog <Dialog
open={this.state.openEnableTelegram} open={this.state.openEnableTelegram}
@ -353,24 +363,23 @@ export default class TradeBox extends Component {
aria-describedby="enable-telegram-dialog-description" aria-describedby="enable-telegram-dialog-description"
> >
<DialogTitle id="open-dispute-dialog-title"> <DialogTitle id="open-dispute-dialog-title">
Enable TG Notifications {t("Enable TG Notifications")}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
<DialogContentText id="alert-dialog-description"> <DialogContentText id="alert-dialog-description">
You will be taken to a conversation with RoboSats telegram bot. {t("You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.")}
Simply open the chat and press "Start". Note that by enabling
telegram notifications you might lower your level of anonymity.
</DialogContentText> </DialogContentText>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={this.handleClickCloseEnableTelegramDialog}>Go back</Button> <Button onClick={this.handleClickCloseEnableTelegramDialog}> {t("Go back")} </Button>
<Button onClick={this.handleClickEnableTelegram} autoFocus> Enable </Button> <Button onClick={this.handleClickEnableTelegram} autoFocus> {t("Enable")} </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
) )
} }
showMakerWait=()=>{ showMakerWait=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
{/* Make confirmation sound for HTLC received. */} {/* Make confirmation sound for HTLC received. */}
@ -378,7 +387,7 @@ export default class TradeBox extends Component {
<this.EnableTelegramDialog/> <this.EnableTelegramDialog/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1"> <Typography component="subtitle1" variant="subtitle1">
<b> Your order is public </b> {" " + this.stepXofY()} <b> {t("Your order is public")} </b> {" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
@ -387,19 +396,16 @@ export default class TradeBox extends Component {
<Divider/> <Divider/>
<ListItem> <ListItem>
<Typography component="body2" variant="body2" align="left"> <Typography component="body2" variant="body2" align="left">
<p>Be patient while robots check the book. <p>{t("Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.")} </p>
It might take some time. This box will ring 🔊 once a robot takes your order. </p> <p>{t("Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).")}</p>
<p>Please note that if your premium is excessive or your currency or payment
methods are not popular, your order might expire untaken. Your bond will
return to you (no action needed).</p>
</Typography> </Typography>
</ListItem> </ListItem>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
{this.props.data.tg_enabled ? {this.props.data.tg_enabled ?
<Typography color='primary' component="h6" variant="h6" align="center"> Telegram enabled</Typography> <Typography color='primary' component="h6" variant="h6" align="center">{t("Telegram enabled")}</Typography>
: :
<Button color="primary" onClick={this.handleClickOpenTelegramDialog}> <Button color="primary" onClick={this.handleClickOpenTelegramDialog}>
<SendIcon/>Enable Telegram Notifications <SendIcon/>{t("Enable Telegram Notifications")}
</Button> </Button>
} }
</Grid> </Grid>
@ -408,7 +414,7 @@ export default class TradeBox extends Component {
<ListItemIcon> <ListItemIcon>
<BookIcon/> <BookIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={this.props.data.num_similar_orders} secondary={"Public orders for " + this.props.data.currencyCode}/> <ListItemText primary={this.props.data.num_similar_orders} secondary={t("Public orders for {{currencyCode}}",{currencyCode: this.props.data.currencyCode})}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -416,8 +422,8 @@ export default class TradeBox extends Component {
<ListItemIcon> <ListItemIcon>
<PercentIcon/> <PercentIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={"Premium rank " + this.props.data.premium_percentile*100+"%"} <ListItemText primary={t("Premium rank") +" "+this.props.data.premium_percentile*100+"%"}
secondary={"Among public " + this.props.data.currencyCode + " orders (higher is cheaper)"} /> secondary={t("Among public {{currencyCode}} orders (higher is cheaper)",{ currencyCode: this.props.data.currencyCode })}/>
</ListItem> </ListItem>
<Divider/> <Divider/>
@ -492,6 +498,7 @@ export default class TradeBox extends Component {
} }
showInputInvoice(){ showInputInvoice(){
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
@ -499,14 +506,18 @@ export default class TradeBox extends Component {
{/* Make confirmation sound for HTLC received. */} {/* Make confirmation sound for HTLC received. */}
<this.Sound soundFileName="locked-invoice"/> <this.Sound soundFileName="locked-invoice"/>
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b> Submit an invoice for {pn(this.props.data.invoice_amount)} Sats </b> {" " + this.stepXofY()} <b> {t("Submit an invoice for {{amountSats}} Sats",{amountSats: pn(this.props.data.invoice_amount)})}
</b> {" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="left"> <Grid item xs={12} align="left">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
The taker is committed! Before letting you send {" "+ parseFloat(parseFloat(this.props.data.amount).toFixed(4))+ {t("The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
" "+ this.props.data.currencyCode}, we want to make sure you are able to receive the BTC. Please provide a {amountFiat: parseFloat(parseFloat(this.props.data.amount).toFixed(4)),
valid invoice for {pn(this.props.data.invoice_amount)} Satoshis. currencyCode: this.props.data.currencyCode,
amountSats: pn(this.props.data.invoice_amount)}
)
}
</Typography> </Typography>
</Grid> </Grid>
@ -514,7 +525,7 @@ export default class TradeBox 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={"Payout Lightning Invoice"} label={t("Payout Lightning Invoice")}
required required
value={this.state.invoice} value={this.state.invoice}
inputProps={{ inputProps={{
@ -549,23 +560,19 @@ export default class TradeBox extends Component {
// Asks the user for a dispute statement. // Asks the user for a dispute statement.
showInDisputeStatement=()=>{ showInDisputeStatement=()=>{
const { t } = this.props;
if(this.props.data.statement_submitted){ if(this.props.data.statement_submitted){
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b> We have received your statement </b> <b> {t("We have received your statement")} </b>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="left"> <Grid item xs={12} align="left">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p>We are waiting for your trade counterpart statement. If you are hesitant about <p>{t("We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.")}</p>
the state of the dispute or want to add more information, contact robosats@protonmail.com.</p> <p>{t("Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).")}</p>
<p>Please, save the information needed to identify your order and your payments: order ID;
payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of
satoshis; and robot nickname. You will have to identify yourself as the user involved
in this trade via email (or other contact methods).</p>
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsSettled()} {this.showBondIsSettled()}
@ -579,15 +586,12 @@ export default class TradeBox extends Component {
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b> A dispute has been opened </b> <b> {t("A dispute has been opened")} </b>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="left"> <Grid item xs={12} align="left">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
Please, submit your statement. Be clear and specific about what happened and provide the necessary {t("Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.")}
evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff.
Disputes are solved at the discretion of real robots <i>(aka humans)</i>, so be as helpful
as possible to ensure a fair outcome. Max 5000 chars.
</Typography> </Typography>
</Grid> </Grid>
@ -595,7 +599,7 @@ export default class TradeBox extends Component {
<TextField <TextField
error={this.state.badStatement} error={this.state.badStatement}
helperText={this.state.badStatement ? this.state.badStatement : "" } helperText={this.state.badStatement ? this.state.badStatement : "" }
label={"Submit dispute statement"} label={t("Submit dispute statement")}
required required
inputProps={{ inputProps={{
style: {textAlign:"center"} style: {textAlign:"center"}
@ -614,24 +618,18 @@ export default class TradeBox extends Component {
} }
showWaitForDisputeResolution=()=>{ showWaitForDisputeResolution=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b> We have the statements </b> <b> {t("We have the statements")} </b>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="left"> <Grid item xs={12} align="left">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
<p>Both statements have been received, wait for the staff to resolve the dispute. <p>{t("Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.")} </p>
If you are hesitant about the state of the dispute or want to add more information, <p>{t("Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).")}</p>
contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether
you wrote it right, write us immediately. </p>
<p>Please, save the information needed to identify your order and your payments: order ID;
payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of
satoshis; and robot nickname. You will have to identify yourself as the user involved
in this trade via email (or other contact methods).</p>
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsSettled()} {this.showBondIsSettled()}
@ -640,18 +638,17 @@ export default class TradeBox extends Component {
} }
showDisputeWinner=()=>{ showDisputeWinner=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b> You have won the dispute </b> <b> {t("You have won the dispute")} </b>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="left"> <Grid item xs={12} align="left">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
You can claim the dispute resolution amount (escrow and fidelity bond) from {t("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).")}
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).
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsSettled()} {this.showBondIsSettled()}
@ -660,18 +657,17 @@ export default class TradeBox extends Component {
} }
showDisputeLoser=()=>{ showDisputeLoser=()=>{
const { t } = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="error" component="subtitle1" variant="subtitle1"> <Typography color="error" component="subtitle1" variant="subtitle1">
<b> You have lost the dispute </b> <b> {t("You have lost the dispute")} </b>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="left"> <Grid item xs={12} align="left">
<Typography component="body2" variant="body2"> <Typography component="body2" variant="body2">
Unfortunately you have lost the dispute. If you think this is a mistake {t("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.")}
you can ask to re-open the case via email to robosats@protonmail.com. However,
chances of it being investigated again are low.
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsSettled()} {this.showBondIsSettled()}
@ -680,19 +676,18 @@ export default class TradeBox extends Component {
} }
showWaitingForEscrow(){ showWaitingForEscrow(){
const { t } = this.props;
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1"> <Typography component="subtitle1" variant="subtitle1">
<b>Your invoice looks good!🎉</b> {" " + this.stepXofY()} <b>{t("Your invoice looks good!")}</b> {" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="left"> <Typography component="body2" variant="body2" align="left">
<p>We are waiting for the seller lock the trade amount. </p> <p>{t("We are waiting for the seller lock the trade amount.")}</p>
<p> Just hang on for a moment. If the seller does not deposit, <p>{t("Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).")}</p>
you will get your bond back automatically. In addition, you will
receive a compensation (check the rewards in your profile).</p>
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsLocked()} {this.showBondIsLocked()}
@ -701,23 +696,20 @@ export default class TradeBox extends Component {
} }
showWaitingForBuyerInvoice(){ showWaitingForBuyerInvoice(){
const { t } = this.props;
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
{/* Make confirmation sound for HTLC received. */} {/* Make confirmation sound for HTLC received. */}
<this.Sound soundFileName="locked-invoice"/> <this.Sound soundFileName="locked-invoice"/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1"> <Typography component="subtitle1" variant="subtitle1">
<b>The trade collateral is locked! 🎉 </b> {" " + this.stepXofY()} <b>{t("The trade collateral is locked!")}</b> {" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="left"> <Typography component="body2" variant="body2" align="left">
<p> We are waiting for the buyer to post a lightning invoice. Once <p>{t("We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.")} </p>
he does, you will be able to directly communicate the fiat payment <p>{t("Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).")}</p>
details. </p>
<p> Just hang on for a moment. If the buyer does not cooperate,
you will get back the trade collateral and your bond automatically. In addition, you will
receive a compensation (check the rewards in your profile).</p>
</Typography> </Typography>
</Grid> </Grid>
{this.showBondIsLocked()} {this.showBondIsLocked()}
@ -772,38 +764,41 @@ handleRatingRobosatsChange=(e)=>{
} }
showFiatSentButton(){ showFiatSentButton(){
const { t } = this.props;
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button defaultValue="confirm" variant='contained' color='secondary' onClick={this.handleClickConfirmButton}>Confirm {this.props.data.currencyCode} sent</Button> <Button defaultValue="confirm" variant='contained' color='secondary' onClick={this.handleClickConfirmButton}>{t("Confirm {{currencyCode}} sent",{currencyCode: this.props.data.currencyCode})}</Button>
</Grid> </Grid>
</Grid> </Grid>
) )
} }
showFiatReceivedButton(){ showFiatReceivedButton(){
const { t } = this.props;
return( return(
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button defaultValue="confirm" variant='contained' color='secondary' onClick={this.handleClickOpenConfirmFiatReceived}>Confirm {this.props.data.currencyCode} received</Button> <Button defaultValue="confirm" variant='contained' color='secondary' onClick={this.handleClickOpenConfirmFiatReceived}>{t("Confirm {{currencyCode}} received",{currencyCode: this.props.data.currencyCode})}</Button>
</Grid> </Grid>
) )
} }
showOpenDisputeButton(){ showOpenDisputeButton(){
// TODO, show alert about how opening a dispute might involve giving away personal data and might mean losing the bond. Ask for double confirmation. const { t } = this.props;
return( return(
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button color="inherit" onClick={this.handleClickOpenConfirmDispute}>Open Dispute</Button> <Button color="inherit" onClick={this.handleClickOpenConfirmDispute}>{t("Open Dispute")}</Button>
</Grid> </Grid>
) )
} }
showOrderExpired(){ showOrderExpired(){
const { t } = this.props;
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1"> <Typography component="subtitle1" variant="subtitle1">
<b>The order has expired</b> <b>{t("The order has expired")}</b>
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>
@ -811,6 +806,7 @@ handleRatingRobosatsChange=(e)=>{
} }
showChat=()=>{ showChat=()=>{
const { t } = this.props;
//In Chatroom - No fiat sent - showChat(showSendButton, showReveiceButton, showDisputeButton) //In Chatroom - No fiat sent - showChat(showSendButton, showReveiceButton, showDisputeButton)
if(this.props.data.is_buyer & this.props.data.status == 9){ if(this.props.data.is_buyer & this.props.data.status == 9){
var showSendButton=true; var showSendButton=true;
@ -841,24 +837,24 @@ handleRatingRobosatsChange=(e)=>{
<this.Sound soundFileName="chat-open"/> <this.Sound soundFileName="chat-open"/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle1" variant="subtitle1"> <Typography component="subtitle1" variant="subtitle1">
<b>Chat with the {this.props.data.is_seller ? 'buyer': 'seller'}</b> {" " + this.stepXofY()} <b> {this.props.data.is_seller ? t("Chat with the buyer"): t("Chat with the seller")}</b> {" " + this.stepXofY()}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
{this.props.data.is_seller ? {this.props.data.is_seller ?
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
{this.props.data.status == 9? {this.props.data.status == 9?
"Say hi! Be helpful and concise. Let them know how to send you "+this.props.data.currencyCode+"." t("Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.",{currencyCode: this.props.data.currencyCode})
: :
"The buyer has sent the fiat. Click 'Confirm Received' once you receive it." t("The buyer has sent the fiat. Click 'Confirm Received' once you receive it.")
} }
</Typography> </Typography>
: :
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
{this.props.data.status == 9? {this.props.data.status == 9?
"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent." t("Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.")
: :
"Wait for the seller to confirm he has received the payment." t("Wait for the seller to confirm he has received the payment.")
} }
</Typography> </Typography>
} }
@ -876,13 +872,14 @@ handleRatingRobosatsChange=(e)=>{
} }
showRateSelect(){ showRateSelect(){
const { t } = this.props;
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
{/* Make confirmation sound for Chat Open. */} {/* Make confirmation sound for Chat Open. */}
<this.Sound soundFileName="successful"/> <this.Sound soundFileName="successful"/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="h6" variant="h6"> <Typography component="h6" variant="h6">
🎉Trade finished!🥳 {t("🎉Trade finished!🥳")}
</Typography> </Typography>
</Grid> </Grid>
{/* <Grid item xs={12} align="center"> {/* <Grid item xs={12} align="center">
@ -895,7 +892,7 @@ handleRatingRobosatsChange=(e)=>{
</Grid> */} </Grid> */}
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
What do you think of 🤖<b>RoboSats</b>? <Trans i18nKey="rate_robosats">What do you think of 🤖<b>RoboSats</b>?</Trans>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
@ -904,22 +901,21 @@ handleRatingRobosatsChange=(e)=>{
{this.state.rating_platform==5 ? {this.state.rating_platform==5 ?
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
<p><b>Thank you! RoboSats loves you too </b></p> <p><b>{t("Thank you! RoboSats loves you too ❤️")}</b></p>
<p>RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!</p> <p>{t("RoboSats gets better with more liquidity and users. Tell a bitcoiner friend about Robosats!")}</p>
</Typography> </Typography>
</Grid> </Grid>
: null} : null}
{this.state.rating_platform!=5 & this.state.rating_platform!=null ? {this.state.rating_platform!=5 & this.state.rating_platform!=null ?
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
<p><b>Thank you for using Robosats!</b></p> <p><b>{t("Thank you for using Robosats!")}</b></p>
<p>Let us know how the platform could improve <p><Trans i18nKey="let_us_know_hot_to_improve">Let us know how the platform could improve (<Link target='_blank' href="https://t.me/robosats">Telegram</Link> / <Link target='_blank' href="https://github.com/Reckless-Satoshi/robosats/issues">Github</Link>)</Trans></p>
(<Link href="https://t.me/robosats">Telegram</Link> / <Link href="https://github.com/Reckless-Satoshi/robosats/issues">Github</Link>)</p>
</Typography> </Typography>
</Grid> </Grid>
: null} : null}
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Button color='primary' onClick={() => {this.props.push('/')}}>Start Again</Button> <Button color='primary' onClick={() => {this.props.push('/')}}>{t("Start Again")}</Button>
</Grid> </Grid>
{this.showBondIsReturned()} {this.showBondIsReturned()}
</Grid> </Grid>
@ -927,17 +923,17 @@ handleRatingRobosatsChange=(e)=>{
} }
showSendingPayment(){ showSendingPayment(){
const { t } = this.props;
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="h6" variant="h6"> <Typography component="h6" variant="h6">
Attempting Lightning Payment {t("Attempting Lightning Payment")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must {t("RoboSats is trying to pay your lightning invoice. Remember that lightning nodes must be online in order to receive payments.")}
be online in order to receive payments.
</Typography> </Typography>
<br/> <br/>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
@ -950,9 +946,10 @@ handleRatingRobosatsChange=(e)=>{
// Countdown Renderer callback with condition // Countdown Renderer callback with condition
countdownRenderer = ({ minutes, seconds, completed }) => { countdownRenderer = ({ minutes, seconds, completed }) => {
const { t } = this.props;
if (completed) { if (completed) {
// Render a completed state // Render a completed state
return (<div align="center"><span> Retrying! </span><br/><CircularProgress/></div> ); return (<div align="center"><span> {t("Retrying!")} </span><br/><CircularProgress/></div> );
} else { } else {
return ( return (
@ -962,32 +959,31 @@ handleRatingRobosatsChange=(e)=>{
}; };
showRoutingFailed=()=>{ showRoutingFailed=()=>{
// TODO If it has failed 3 times, ask for a new invoice. const { t } = this.props;
if(this.props.data.invoice_expired){ if(this.props.data.invoice_expired){
return( return(
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="h6" variant="h6"> <Typography component="h6" variant="h6">
Lightning Routing Failed {t("Lightning Routing Failed")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
Your invoice has expired or more than 3 payment attempts have been made. {t("Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ")}
Muun wallet is not recommended, <Link href="https://github.com/Reckless-Satoshi/robosats/issues/44">check the list of <Link href="https://github.com/Reckless-Satoshi/robosats/issues/44"> {t("Check the list of compatible wallets")}</Link>
compatible wallets</Link>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography color="primary" component="subtitle1" variant="subtitle1"> <Typography color="primary" component="subtitle1" variant="subtitle1">
<b> Submit a LN invoice for {pn(this.props.data.invoice_amount)} Sats </b> <b> {t("Submit an invoice for {{amountSats}} Sats",{amountSats: pn(this.props.data.invoice_amount)})}</b>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<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={"Payout Lightning Invoice"} label={t("Payout Lightning Invoice")}
required required
inputProps={{ inputProps={{
style: {textAlign:"center"} style: {textAlign:"center"}
@ -1009,18 +1005,16 @@ handleRatingRobosatsChange=(e)=>{
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="h6" variant="h6"> <Typography component="h6" variant="h6">
Lightning Routing Failed {t("Lightning Routing Failed")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="body2" variant="body2" align="center"> <Typography component="body2" variant="body2" align="center">
RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you {t("RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.")}
will be able to submit a new invoice. Check whether you have enough inbound liquidity.
Remember that lightning nodes must be online in order to receive payments.
</Typography> </Typography>
<List> <List>
<Divider/> <Divider/>
<ListItemText secondary="Next attempt in"> <ListItemText secondary={t("Next attempt in")}>
<Countdown date={new Date(this.props.data.next_retry_time)} renderer={this.countdownRenderer} /> <Countdown date={new Date(this.props.data.next_retry_time)} renderer={this.countdownRenderer} />
</ListItemText> </ListItemText>
</List> </List>
@ -1031,6 +1025,7 @@ handleRatingRobosatsChange=(e)=>{
} }
render() { render() {
const { t } = this.props;
return ( return (
<Grid container spacing={1} style={{ width:this.props.width}}> <Grid container spacing={1} style={{ width:this.props.width}}>
<this.ConfirmDisputeDialog/> <this.ConfirmDisputeDialog/>
@ -1038,7 +1033,7 @@ handleRatingRobosatsChange=(e)=>{
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<MediaQuery minWidth={920}> <MediaQuery minWidth={920}>
<Typography component="h5" variant="h5"> <Typography component="h5" variant="h5">
Contract Box {t("Contract Box")}
</Typography> </Typography>
</MediaQuery> </MediaQuery>
<Paper elevation={12} style={{ padding: 8,}}> <Paper elevation={12} style={{ padding: 8,}}>
@ -1088,3 +1083,5 @@ handleRatingRobosatsChange=(e)=>{
); );
} }
} }
export default withTranslation()(TradeBox);

View File

@ -1,9 +1,9 @@
import {Paper, Alert, AlertTitle, Button, Link} from "@mui/material"
import React, { Component } from 'react' import React, { Component } from 'react'
import { withTranslation, Trans} from "react-i18next";
import {Paper, Alert, AlertTitle, Button, Link} from "@mui/material"
import MediaQuery from 'react-responsive' import MediaQuery from 'react-responsive'
export default class UnsafeAlert extends Component { class UnsafeAlert extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
} }
@ -23,31 +23,36 @@ export default class UnsafeAlert extends Component {
] ]
render() { render() {
const { t, i18n} = this.props;
return ( return (
(!this.safe_urls.includes(this.getHost()) & this.state.show) ? (!this.safe_urls.includes(this.getHost()) & this.state.show) ?
<div> <div>
<MediaQuery minWidth={800}> <MediaQuery minWidth={800}>
<Paper elevation={6} className="alertUnsafe"> <Paper elevation={6} className="alertUnsafe">
<Alert severity="warning" sx={{maxHeight:"100px"}} <Alert severity="warning" sx={{maxHeight:"100px"}}
action={<Button onClick={() => this.setState({show:false})}>Hide</Button>} action={<Button onClick={() => this.setState({show:false})}>{t("Hide")}</Button>}
> >
<AlertTitle>You are not using RoboSats privately</AlertTitle> <AlertTitle>{t("You are not using RoboSats privately")}</AlertTitle>
Some features are disabled for your protection (e.g. chat) and you will not be able to complete a <Trans i18nKey="desktop_unsafe_alert">
trade without them. To protect your privacy and fully enable RoboSats, use <Link href='https://www.torproject.org/download/' target="_blank">Tor Browser</Link> and visit the <Link chref='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion' target="_blank">Onion</Link> site. Some features are disabled for your protection (e.g. chat) and you will not be able to complete a
</Alert> trade without them. To protect your privacy and fully enable RoboSats, use <Link href='https://www.torproject.org/download/' target="_blank">Tor Browser</Link> and visit the <Link href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion' target="_blank">Onion</Link> site.
</Trans>
</Alert>
</Paper> </Paper>
</MediaQuery> </MediaQuery>
<MediaQuery maxWidth={799}> <MediaQuery maxWidth={799}>
<Paper elevation={6} className="alertUnsafe"> <Paper elevation={6} className="alertUnsafe">
<Alert severity="warning" sx={{maxHeight:"120px"}}> <Alert severity="warning" sx={{maxHeight:"120px"}}>
<AlertTitle>You are not using RoboSats privately</AlertTitle> <AlertTitle>{t("You are not using RoboSats privately")}</AlertTitle>
You will not be able to complete a <Trans i18nKey="phone_unsafe_alert">
trade. Use <Link href='https://www.torproject.org/download/' target="_blank">Tor Browser</Link> and visit the <Link href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion' target="_blank">Onion</Link> site. You will not be able to complete a
trade. Use <Link href='https://www.torproject.org/download/' target="_blank">Tor Browser</Link> and visit the <Link href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion' target="_blank">Onion</Link> site.
</Trans>
<div style={{width: '100%'}}> <div style={{width: '100%'}}>
</div> </div>
<div align="center"> <div align="center">
<Button className="hideAlertButton" onClick={() => this.setState({show:false})}>Hide</Button> <Button className="hideAlertButton" onClick={() => this.setState({show:false})}>{t("Hide")}</Button>
</div> </div>
</Alert> </Alert>
</Paper> </Paper>
@ -58,3 +63,5 @@ export default class UnsafeAlert extends Component {
) )
} }
} }
export default withTranslation()(UnsafeAlert);

View File

@ -1,13 +1,14 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { withTranslation } from "react-i18next";
import { Button , Tooltip, Dialog, Grid, Typography, TextField, ButtonGroup, CircularProgress, IconButton} from "@mui/material" import { Button , Tooltip, Dialog, Grid, Typography, TextField, ButtonGroup, CircularProgress, IconButton} from "@mui/material"
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import Image from 'material-ui-image' import Image from 'material-ui-image'
import InfoDialog from './InfoDialog' import InfoDialog from './InfoDialog'
import SmartToyIcon from '@mui/icons-material/SmartToy'; import SmartToyIcon from '@mui/icons-material/SmartToy';
import CasinoIcon from '@mui/icons-material/Casino'; import CasinoIcon from '@mui/icons-material/Casino';
import ContentCopy from "@mui/icons-material/ContentCopy"; import ContentCopy from "@mui/icons-material/ContentCopy";
import RoboSatsNoTextIcon from "./icons/RoboSatsNoTextIcon" import RoboSatsNoTextIcon from "./icons/RoboSatsNoTextIcon"
import BoltIcon from '@mui/icons-material/Bolt'; import BoltIcon from '@mui/icons-material/Bolt';
function getCookie(name) { function getCookie(name) {
@ -27,7 +28,7 @@ function getCookie(name) {
} }
const csrftoken = getCookie('csrftoken'); const csrftoken = getCookie('csrftoken');
export default class UserGenPage extends Component { class UserGenPage extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -101,8 +102,7 @@ export default class UserGenPage extends Component {
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')}, headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')},
}; };
fetch("/api/user", requestOptions) fetch("/api/user", requestOptions)
.then((response) => response.json()) .then((response) => response.json());
.then((data) => console.log(data));
} }
handleClickNewRandomToken=()=>{ handleClickNewRandomToken=()=>{
@ -150,6 +150,7 @@ export default class UserGenPage extends Component {
} }
render() { render() {
const { t, i18n} = this.props;
return ( return (
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item> <Grid item>
@ -168,7 +169,7 @@ export default class UserGenPage extends Component {
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Tooltip enterTouchDelay="0" title="This is your trading avatar"> <Tooltip enterTouchDelay="0" title={t("This is your trading avatar")}>
<div style={{ maxWidth: 200, maxHeight: 200 }}> <div style={{ maxWidth: 200, maxHeight: 200 }}>
<Image className='newAvatar' <Image className='newAvatar'
disableError='true' disableError='true'
@ -186,7 +187,7 @@ export default class UserGenPage extends Component {
this.state.found ? this.state.found ?
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<Typography component="subtitle2" variant="subtitle2" color='primary'> <Typography component="subtitle2" variant="subtitle2" color='primary'>
{this.state.found}<br/> {this.state.found ? t("A robot avatar was found, welcome back!"):null}<br/>
</Typography> </Typography>
</Grid> </Grid>
: :
@ -195,18 +196,13 @@ export default class UserGenPage extends Component {
<Grid container align="center"> <Grid container align="center">
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<TextField sx={{maxWidth: 280}} <TextField sx={{maxWidth: 280}}
//sx={{ input: { color: 'purple' } }}
// InputLabelProps={{
// style: { color: 'green' },
// }}
error={this.state.bad_request} error={this.state.bad_request}
label={"Store your token safely"} label={t("Store your token safely")}
required='true' required='true'
value={this.state.token} value={this.state.token}
variant='standard' variant='standard'
helperText={this.state.bad_request} helperText={this.state.bad_request}
size='small' size='small'
// multiline = {true}
onChange={this.handleChangeToken} onChange={this.handleChangeToken}
onKeyPress={(e) => { onKeyPress={(e) => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
@ -215,13 +211,13 @@ export default class UserGenPage extends Component {
}} }}
InputProps={{ InputProps={{
startAdornment: startAdornment:
<Tooltip disableHoverListener open={this.state.copied} enterTouchDelay="0" title="Copied!"> <Tooltip disableHoverListener open={this.state.copied} enterTouchDelay="0" title={t("Copied!")}>
<IconButton onClick= {()=> (navigator.clipboard.writeText(this.state.token) & this.setState({copied:true}))}> <IconButton onClick= {()=> (navigator.clipboard.writeText(this.state.token) & this.setState({copied:true}))}>
<ContentCopy color={this.props.avatarLoaded & !this.state.copied & !this.state.bad_request ? 'primary' : 'inherit' } sx={{width:18, height:18}}/> <ContentCopy color={this.props.avatarLoaded & !this.state.copied & !this.state.bad_request ? 'primary' : 'inherit' } sx={{width:18, height:18}}/>
</IconButton> </IconButton>
</Tooltip>, </Tooltip>,
endAdornment: endAdornment:
<Tooltip enterTouchDelay="250" title="Generate a new token"> <Tooltip enterTouchDelay="250" title={t("Generate a new token")}>
<IconButton onClick={this.handleClickNewRandomToken}><CasinoIcon/></IconButton> <IconButton onClick={this.handleClickNewRandomToken}><CasinoIcon/></IconButton>
</Tooltip>, </Tooltip>,
}} }}
@ -232,14 +228,14 @@ export default class UserGenPage extends Component {
{this.state.tokenHasChanged ? {this.state.tokenHasChanged ?
<Button type="submit" size='small' onClick= {this.handleClickSubmitToken}> <Button type="submit" size='small' onClick= {this.handleClickSubmitToken}>
<SmartToyIcon sx={{width:18, height:18}} /> <SmartToyIcon sx={{width:18, height:18}} />
<span> Generate Robot</span> <span> {t("Generate Robot")}</span>
</Button> </Button>
: :
<Tooltip enterTouchDelay="0" enterDelay="500" enterNextDelay="2000" title="You must enter a new token first"> <Tooltip enterTouchDelay="0" enterDelay="500" enterNextDelay="2000" title={t("You must enter a new token first")}>
<div> <div>
<Button disabled={true} type="submit" size='small' > <Button disabled={true} type="submit" size='small' >
<SmartToyIcon sx={{width:18, height:18}} /> <SmartToyIcon sx={{width:18, height:18}} />
<span> Generate Robot</span> <span>{t("Generate Robot")}</span>
</Button> </Button>
</div> </div>
</Tooltip> </Tooltip>
@ -247,10 +243,10 @@ export default class UserGenPage extends Component {
</Grid> </Grid>
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
<ButtonGroup variant="contained" aria-label="outlined primary button group"> <ButtonGroup variant="contained" aria-label="outlined primary button group">
<Button disabled={this.state.loadingRobot} color='primary' to='/make/' component={Link}>Make Order</Button> <Button disabled={this.state.loadingRobot} color='primary' to='/make/' component={Link}>{t("Make Order")}</Button>
<Button color='inherit' onClick={this.handleClickOpenInfo}>Info</Button> <Button color='inherit' onClick={this.handleClickOpenInfo}>{t("Info")}</Button>
<this.InfoDialog/> <this.InfoDialog/>
<Button disabled={this.state.loadingRobot} color='secondary' to='/book/' component={Link}>View Book</Button> <Button disabled={this.state.loadingRobot} color='secondary' to='/book/' component={Link}>{t("View Book")}</Button>
</ButtonGroup> </ButtonGroup>
</Grid> </Grid>
@ -263,7 +259,7 @@ export default class UserGenPage extends Component {
<Grid item xs={0.8}/> <Grid item xs={0.8}/>
<Grid item xs={7.5} align="right"> <Grid item xs={7.5} align="right">
<Typography component="h5" variant="h5"> <Typography component="h5" variant="h5">
Simple and Private LN P2P Exchange {t("Simple and Private LN P2P Exchange")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={2.5} align="left"> <Grid item xs={2.5} align="left">
@ -276,3 +272,5 @@ export default class UserGenPage extends Component {
); );
} }
} }
export default withTranslation()(UserGenPage);

View File

@ -247,7 +247,7 @@ export default function AutocompletePayments(props) {
{groupedOptions.length > 0 ? ( {groupedOptions.length > 0 ? (
<Listbox {...getListboxProps()}> <Listbox {...getListboxProps()}>
<div style={{position:'fixed', minHeight:'20px', marginLeft: '53px', marginTop: '-13px'}}> <div style={{position:'fixed', minHeight:'20px', marginLeft: '53px', marginTop: '-13px'}}>
<ListHeader><i>You can add any method </i></ListHeader> <ListHeader><i>{props.listHeaderText}</i></ListHeader>
</div> </div>
{groupedOptions.map((option, index) => ( {groupedOptions.map((option, index) => (
<li {...getOptionProps({ option, index })}> <li {...getOptionProps({ option, index })}>
@ -262,7 +262,7 @@ export default function AutocompletePayments(props) {
))} ))}
{val != null? {val != null?
(val.length > 2 ? (val.length > 2 ?
<Button size="small" fullWidth={true} onClick={() => handleAddNew(getInputProps())}><DashboardCustomizeIcon sx={{width:18,height:18}}/>Add New</Button> <Button size="small" fullWidth={true} onClick={() => handleAddNew(getInputProps())}><DashboardCustomizeIcon sx={{width:18,height:18}}/>{props.addNewButtonText}</Button>
:null) :null)
:null} :null}
</Listbox> </Listbox>
@ -270,7 +270,7 @@ export default function AutocompletePayments(props) {
//Here goes what happens if there is no groupedOptions //Here goes what happens if there is no groupedOptions
(getInputProps().value.length > 0 ? (getInputProps().value.length > 0 ?
<Listbox {...getListboxProps()}> <Listbox {...getListboxProps()}>
<Button fullWidth={true} onClick={() => handleAddNew(getInputProps())}><DashboardCustomizeIcon sx={{width:20,height:20}}/>Add New</Button> <Button fullWidth={true} onClick={() => handleAddNew(getInputProps())}><DashboardCustomizeIcon sx={{width:20,height:20}}/>{props.addNewButtonText}</Button>
</Listbox> </Listbox>
:null) :null)
} }

View File

@ -0,0 +1,45 @@
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import HttpApi from 'i18next-http-backend';
import translationEN from "../locales/en.json";
import translationES from "../locales/es.json";
import translationDE from "../locales/de.json";
import translationRU from "../locales/ru.json";
import translationZH from "../locales/zh.json";
i18n
.use(HttpApi)
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: {translations: translationEN},
es: {translations: translationES},
ru: {translations: translationRU},
de: {translations: translationDE},
zh: {translations: translationZH},
},
fallbackLng: "en",
debug: true,
// have a common namespace used around the full app
ns: ["translations"],
defaultNS: "translations",
keySeparator: false, // we use content as keys
interpolation: {
escapeValue: false,
formatSeparator: ","
},
react: {
wait: true,
useSuspense: false,
}
});
export default i18n;

View File

@ -0,0 +1,35 @@
# Contributing Translations to RoboSats
RoboSats is a way to exchange BTC for **any currency of the world**. As such, for many users this tool might only be useful if it is available in a language they can understand. Translating RoboSats into a new language is one of the most valuable contributions to the project, as it makes it available to new audience, increasing the reach of this cool freedom tool.
There isn't a lot of text in RoboSats, however it might be bst to split the work with another contributor. You can poll in the telegram community @RoboSats and find users willing to split the task.
## How to contribute a new translation.
Simply create a new translation file in `frontend/src/locales` (Same folder where you are reading these instructions). In `locales` there is a single file with a json dictionary for every language. In order to create a new translation, simply copy `en.json` (the master text) into a new file named after the language's [ISO 639 two character code](https://www.loc.gov/standards/iso639-2/php/English_list.php).
## Guidelines
Each language .json dictionary contains pairs of keys and values in the following format { "key1":"value1", "key2":"value2", ...}. Most keys are the literal English sentence. These simply have to be translated on the right side, for example, in order to translate the `Make Order` button to Spanish we should change the file to look like this `{... "Make Order":"Crear Orden",...}`.
1. **Not all keys are explicit sentences.** Some keys are variable names e.g. "phone_unsafe_alert". In these case you must take a look at the value originally in `en.json`.
2. **The language dictionary is split into 9 sections.** The first key of each section is a reference and does not need to be translated. For example, the second section starts with the key:value `"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation"` . It does not need to be translated, it is just information for the translator to understand what part of the app he will be working on.
3. **Try to keep a similar length to the original sentence.** In most cases it will be okay if the translation is shorter. However, translations that result in a higher character count might break the UI! Of course, it might not always be possible to stick to the length of the English sentence. In those cases the UI might have to be changed, contact the responsible person for such a change.
4. **Some sentences contain variables**, for example, {{currencyCode}}. It will insert the currency code where the variable is found. E.g., `"Pay 30 {{currencyCode}}"` will render into "Pay 30 USD".
5. **Some sentences contain HTML tags.** These tags are usually hyperlinks. For example in `{"phone_unsafe_alert": "Use <1>Tor Browser</1> and visit the <3>Onion</3> site."}` the children text of <1> (Tor Browser) will link to the Tor Download website, and the children of <3> will link to the RoboSats Onion site.
6. **Some text is high priority, some other text is low priority.** Some keys are likely to change soon or they might not be so relevant for the user of the app. The translation files are sorted from top to bottom by the priority of the translation. The keys by the end of the translation file are more likely to change. It is best to translate from top to bottom.
7. Use a spell checker ;)
8. **Understand the context of where the translation will be displayed.** Literal translations might not work well to some languages. While in English the wording is always similar, in some languages it might be very different if you are translating a button (the user is taking an action) or if you are simply translating a tooltip.
To understand the context it might be clever to translate the strings while looking at the app. However, many strings can only be found while trading. The testnet RoboSats site is great for this as you can explore the whole app simply interacting with it with testnet bitcoin. However, in case of doubt where a text is displayed, it might be faster to simply write a message on the community group @robosats in Telegram.
9. Congratulate yourself! Seriously, it's so awesome you are looking into building up freedom tools!!

View File

@ -0,0 +1,354 @@
{
"UNSAFE ALERT - UnsafeAlert.js": "Alert that shows on top when browsing from the unsafe clearnet sites",
"You are not using RoboSats privately": "You are not using RoboSats privately",
"desktop_unsafe_alert": "Some features are disabled for your protection (e.g. chat) and you will not be able to complete a trade without them. To protect your privacy and fully enable RoboSats, 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",
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
"Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange",
"This is your trading avatar":"This is your trading avatar",
"Store your token safely":"Store your token safely",
"A robot avatar was found, welcome back!":"A robot avatar was found, welcome back!",
"Copied!":"Copied!",
"Generate a new token":"Generate a new token",
"Generate Robot":"Generate Robot",
"You must enter a new token first":"You must enter a new token first",
"Make Order":"Make Order",
"Info":"Info",
"View Book":"View Book",
"MAKER PAGE - MakerPage.js": "This is the page where users can create new orders",
"Order":"Order",
"Customize":"Customize",
"Buy or Sell Bitcoin?":"Buy or Sell Bitcoin?",
"Buy":"Buy",
"Sell":"Sell",
"Amount":"Amount",
"Amount of fiat to exchange for bitcoin":"Amount of fiat to exchange for bitcoin",
"Invalid":"Invalid",
"Enter your preferred fiat payment methods. Fast methods are highly recommended.":"Enter your preferred fiat payment methods. Fast methods are highly recommended.",
"Must be shorter than 65 characters":"Must be shorter than 65 characters",
"Swap Destination(s)":"Swap Destination(s)",
"Fiat Payment Method(s)":"Fiat Payment Method(s)",
"You can add any method":"You can add any method",
"Add New":"Add New",
"Choose a Pricing Method":"Choose a Pricing Method",
"Relative":"Relative",
"Let the price move with the market":"Let the price move with the market",
"Premium over Market (%)":"Premium over Market (%)",
"Explicit":"Explicit",
"Set a fix amount of satoshis":"Set a fix amount of satoshis",
"Satoshis":"Satoshis",
"Let the taker chose an amount within the range":"Let the taker chose an amount within the range",
"Enable Amount Range":"Enable Amount Range",
"From": "From",
"to":"to",
"Public Duration (HH:mm)":"Public Duration (HH:mm)",
"Set the skin-in-the-game, increase for higher safety assurance":"Set the skin-in-the-game, increase for higher safety assurance",
"Fidelity Bond Size":"Fidelity Bond Size",
"Allow bondless takers":"Allow bondless takers",
"COMING SOON - High risk! Limited to {{limitSats}}K Sats":"COMING SOON - High risk! Limited to {{limitSats}}K Sats",
"You must fill the order correctly":"You must fill the order correctly",
"Create Order":"Create Order",
"Back":"Back",
"Create a BTC buy order for ":"Create a BTC buy order for ",
"Create a BTC sell order for ":"Create a BTC sell order for ",
" of {{satoshis}} Satoshis":" of {{satoshis}} Satoshis",
" at market price":" at market price",
" at a {{premium}}% premium":" at a {{premium}}% premium",
" at a {{discount}}% discount":" at a {{discount}}% discount",
"Must be less than {{max}}%":"Must be less than {{max}}%",
"Must be more than {{min}}%":"Must be more than {{min}}%",
"Must be less than {{maxSats}": "Must be less than {{maxSats}}",
"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",
"Robot":"Robot",
"Is":"Is",
"Currency":"Currency",
"Payment Method":"Payment Method",
"Pay":"Pay",
"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 miscellaneous 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 Chinese speaking community!":"Join RoboSats Chinese 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 Box":"Order Box",
"Contract":"Contract",
"Active":"Active",
"Seen recently":"Seen recently",
"Inactive":"Inactive",
"(Seller)":"(Seller)",
"(Buyer)":"(Buyer)",
"Order maker":"Order maker",
"Order taker":"Order taker",
"Order Details":"Order Details",
"Order status":"Order status",
"Waiting for maker bond":"Waiting for maker bond",
"Public":"Public",
"Waiting for taker bond":"Waiting for taker bond",
"Cancelled":"Cancelled",
"Expired":"Expired",
"Waiting for trade collateral and buyer invoice":"Waiting for trade collateral and buyer invoice",
"Waiting only for seller trade collateral":"Waiting only for seller trade collateral",
"Waiting only for buyer invoice":"Waiting only for buyer invoice",
"Sending fiat - In chatroom":"Sending fiat - In chatroom",
"Fiat sent - In chatroom":"Fiat sent - In chatroom",
"In dispute":"In dispute",
"Collaboratively cancelled":"Collaboratively cancelled",
"Sending satoshis to buyer":"Sending satoshis to buyer",
"Sucessful trade":"Successful trade",
"Failed lightning network routing":"Failed lightning network routing",
"Wait for dispute resolution":"Wait for dispute resolution",
"Maker lost dispute":"Maker lost dispute",
"Taker lost dispute":"Taker lost dispute",
"Amount range":"Amount range",
"Swap destination":"Swap destination",
"Accepted payment methods":"Accepted payment methods",
"Others":"Others",
"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%":"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%",
"Price and Premium":"Price and Premium",
"Amount of Satoshis":"Amount of Satoshis",
"Premium over market price":"Premium over market price",
"Order ID":"Order ID",
"Expires in":"Expires in",
"{{nickname}} is asking for a collaborative cancel":"{{nickname}} is asking for a collaborative cancel",
"You asked for a collaborative cancellation":"You asked for a collaborative cancellation",
"Invoice expired. You did not confirm publishing the order in time. Make a new order.":"Invoice expired. You did not confirm publishing the order in time. Make a new order.",
"This order has been cancelled by the maker":"This order has been cancelled by the maker",
"Penalty lifted, good to go!":"Penalty lifted, good to go!",
"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s":"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s",
"Too low":"Too low",
"Too high":"Too high",
"Enter amount of fiat to exchange for bitcoin":"Enter amount of fiat to exchange for bitcoin",
"Amount {{currencyCode}}":"Amount {{currencyCode}}",
"You must specify an amount first":"You must specify an amount first",
"Take Order":"Take Order",
"Wait until you can take an order":"Wait until you can take an order",
"Cancel the order?":"Cancel the order?",
"If the order is cancelled now you will lose your bond.":"If the order is cancelled now you will lose your bond.",
"Confirm Cancel":"Confirm Cancel",
"The maker is away":"The maker is away",
"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.":"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.",
"Collaborative cancel the order?":"Collaborative cancel the order?",
"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.":"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.",
"Ask for Cancel":"Ask for Cancel",
"Cancel":"Cancel",
"Collaborative Cancel":"Collaborative Cancel",
"Invalid Order Id":"Invalid Order Id",
"You must have a robot avatar to see the order details":"You must have a robot avatar to see the order details",
"This order has been cancelled collaborativelly":"This order has been cancelled collaborativelly",
"You are not allowed to see this order":"You are not allowed to see this order",
"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues":"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues",
"CHAT BOX - Chat.js":"Chat Box",
"You":"You",
"Peer":"Peer",
"connected":"connected",
"disconnected":"disconnected",
"Type a message":"Type a message",
"Connecting...":"Connecting...",
"Send":"Send",
"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.",
"CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline",
"Contract Box":"Contract Box",
"Robots show commitment to their peers": "Robots show commitment to their peers",
"Lock {{amountSats}} Sats to PUBLISH order": "Lock {{amountSats}} Sats to PUBLISH order",
"Lock {{amountSats}} Sats to TAKE order": "Lock {{amountSats}} Sats to TAKE order",
"Lock {{amountSats}} Sats as collateral": "Lock {{amountSats}} Sats as collateral",
"Copy to clipboard":"Copy to clipboard",
"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.":"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.",
"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.":"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.",
"Your maker bond is locked":"Your maker bond is locked",
"Your taker bond is locked":"Your taker bond is locked",
"Your maker bond was settled":"Your maker bond was settled",
"Your taker bond was settled":"Your taker bond was settled",
"Your maker bond was unlock":"Your maker bond was unlock",
"Your taker bond was unlocked":"Your taker bond was unlocked",
"Your order is public":"Your order is public",
"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.":"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.",
"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).":"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).",
"Enable Telegram Notifications":"Enable Telegram Notifications",
"Enable TG Notifications":"Enable TG Notifications",
"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.":"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.",
"Go back":"Go back",
"Enable":"Enable",
"Telegram enabled":"Telegram enabled",
"Public orders for {{currencyCode}}":"Public orders for {{currencyCode}}",
"Premium rank": "Premium rank",
"Among public {{currencyCode}} orders (higher is cheaper)": "Among public {{currencyCode}} orders (higher is cheaper)",
"A taker has been found!":"A taker has been found!",
"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.":"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.",
"Submit an invoice for {{amountSats}} Sats":"Submit an invoice for {{amountSats}} Sats",
"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.":"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
"Payout Lightning Invoice":"Payout Lightning Invoice",
"Your invoice looks good!":"Your invoice looks good!",
"We are waiting for the seller lock the trade amount.":"We are waiting for the seller lock the trade amount.",
"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"The trade collateral is locked!":"The trade collateral is locked!",
"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.":"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.",
"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"Confirm {{currencyCode}} sent":"Confirm {{currencyCode}} sent",
"Confirm {{currencyCode}} received":"Confirm {{currencyCode}} received",
"Open Dispute":"Open Dispute",
"The order has expired":"The order has expired",
"Chat with the buyer":"Chat with the buyer",
"Chat with the seller":"Chat with the seller",
"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.":"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.",
"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.":"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.",
"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.":"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.",
"Wait for the seller to confirm he has received the payment.":"Wait for the seller to confirm he has received the payment.",
"Confirm you received {{currencyCode}}?":"Confirm you received {{currencyCode}}?",
"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.":"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.",
"Confirm":"Confirm",
"🎉Trade finished!🥳":"🎉Trade finished!🥳",
"rate_robosats":"What do you think of 🤖<1>RoboSats</1>⚡?",
"Thank you! RoboSats loves you too ❤️":"Thank you! RoboSats loves you too ❤️",
"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!",
"Thank you for using Robosats!":"Thank you for using Robosats!",
"let_us_know_hot_to_improve":"Let us know how the platform could improve (<1>Telegram</1> / <3>Github</3>)",
"Start Again":"Start Again",
"Attempting Lightning Payment":"Attempting Lightning Payment",
"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.",
"Retrying!":"Retrying!",
"Lightning Routing Failed":"Lightning Routing Failed",
"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ":"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ",
"Check the list of compatible wallets":"Check the list of compatible wallets",
"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.":"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.",
"Next attempt in":"Next attempt in",
"Do you want to open a dispute?":"Do you want to open a dispute?",
"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.":"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.",
"Disagree":"Disagree",
"Agree and open dispute":"Agree and open dispute",
"A dispute has been opened":"A dispute has been opened",
"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.":"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.",
"Submit dispute statement":"Submit dispute statement",
"We have received your statement":"We have received your statement",
"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.":"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.",
"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).":"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).",
"We have the statements":"We have the statements",
"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.":"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.",
"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 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.",
"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.",
"Project source code":"Project 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."
}

View File

@ -0,0 +1,354 @@
{
"UNSAFE ALERT - UnsafeAlert.js": "Alert that shows on top when browsing from the unsafe clearnet sites",
"You are not using RoboSats privately": "You are not using RoboSats privately",
"desktop_unsafe_alert": "Some features are disabled for your protection (e.g. chat) and you will not be able to complete a trade without them. To protect your privacy and fully enable RoboSats, 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",
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
"Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange",
"This is your trading avatar":"This is your trading avatar",
"Store your token safely":"Store your token safely",
"A robot avatar was found, welcome back!":"A robot avatar was found, welcome back!",
"Copied!":"Copied!",
"Generate a new token":"Generate a new token",
"Generate Robot":"Generate Robot",
"You must enter a new token first":"You must enter a new token first",
"Make Order":"Make Order",
"Info":"Info",
"View Book":"View Book",
"MAKER PAGE - MakerPage.js": "This is the page where users can create new orders",
"Order":"Order",
"Customize":"Customize",
"Buy or Sell Bitcoin?":"Buy or Sell Bitcoin?",
"Buy":"Buy",
"Sell":"Sell",
"Amount":"Amount",
"Amount of fiat to exchange for bitcoin":"Amount of fiat to exchange for bitcoin",
"Invalid":"Invalid",
"Enter your preferred fiat payment methods. Fast methods are highly recommended.":"Enter your preferred fiat payment methods. Fast methods are highly recommended.",
"Must be shorter than 65 characters":"Must be shorter than 65 characters",
"Swap Destination(s)":"Swap Destination(s)",
"Fiat Payment Method(s)":"Fiat Payment Method(s)",
"You can add any method":"You can add any method",
"Add New":"Add New",
"Choose a Pricing Method":"Choose a Pricing Method",
"Relative":"Relative",
"Let the price move with the market":"Let the price move with the market",
"Premium over Market (%)":"Premium over Market (%)",
"Explicit":"Explicit",
"Set a fix amount of satoshis":"Set a fix amount of satoshis",
"Satoshis":"Satoshis",
"Let the taker chose an amount within the range":"Let the taker chose an amount within the range",
"Enable Amount Range":"Enable Amount Range",
"From": "From",
"to":"to",
"Public Duration (HH:mm)":"Public Duration (HH:mm)",
"Set the skin-in-the-game, increase for higher safety assurance":"Set the skin-in-the-game, increase for higher safety assurance",
"Fidelity Bond Size":"Fidelity Bond Size",
"Allow bondless takers":"Allow bondless takers",
"COMING SOON - High risk! Limited to {{limitSats}}K Sats":"COMING SOON - High risk! Limited to {{limitSats}}K Sats",
"You must fill the order correctly":"You must fill the order correctly",
"Create Order":"Create Order",
"Back":"Back",
"Create a BTC buy order for ":"Create a BTC buy order for ",
"Create a BTC sell order for ":"Create a BTC sell order for ",
" of {{satoshis}} Satoshis":" of {{satoshis}} Satoshis",
" at market price":" at market price",
" at a {{premium}}% premium":" at a {{premium}}% premium",
" at a {{discount}}% discount":" at a {{discount}}% discount",
"Must be less than {{max}}%":"Must be less than {{max}}%",
"Must be more than {{min}}%":"Must be more than {{min}}%",
"Must be less than {{maxSats}": "Must be less than {{maxSats}}",
"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",
"Robot":"Robot",
"Is":"Is",
"Currency":"Currency",
"Payment Method":"Payment Method",
"Pay":"Pay",
"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 miscellaneous 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 Chinese speaking community!":"Join RoboSats Chinese 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 Box":"Order Box",
"Contract":"Contract",
"Active":"Active",
"Seen recently":"Seen recently",
"Inactive":"Inactive",
"(Seller)":"(Seller)",
"(Buyer)":"(Buyer)",
"Order maker":"Order maker",
"Order taker":"Order taker",
"Order Details":"Order Details",
"Order status":"Order status",
"Waiting for maker bond":"Waiting for maker bond",
"Public":"Public",
"Waiting for taker bond":"Waiting for taker bond",
"Cancelled":"Cancelled",
"Expired":"Expired",
"Waiting for trade collateral and buyer invoice":"Waiting for trade collateral and buyer invoice",
"Waiting only for seller trade collateral":"Waiting only for seller trade collateral",
"Waiting only for buyer invoice":"Waiting only for buyer invoice",
"Sending fiat - In chatroom":"Sending fiat - In chatroom",
"Fiat sent - In chatroom":"Fiat sent - In chatroom",
"In dispute":"In dispute",
"Collaboratively cancelled":"Collaboratively cancelled",
"Sending satoshis to buyer":"Sending satoshis to buyer",
"Sucessful trade":"Successful trade",
"Failed lightning network routing":"Failed lightning network routing",
"Wait for dispute resolution":"Wait for dispute resolution",
"Maker lost dispute":"Maker lost dispute",
"Taker lost dispute":"Taker lost dispute",
"Amount range":"Amount range",
"Swap destination":"Swap destination",
"Accepted payment methods":"Accepted payment methods",
"Others":"Others",
"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%":"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%",
"Price and Premium":"Price and Premium",
"Amount of Satoshis":"Amount of Satoshis",
"Premium over market price":"Premium over market price",
"Order ID":"Order ID",
"Expires in":"Expires in",
"{{nickname}} is asking for a collaborative cancel":"{{nickname}} is asking for a collaborative cancel",
"You asked for a collaborative cancellation":"You asked for a collaborative cancellation",
"Invoice expired. You did not confirm publishing the order in time. Make a new order.":"Invoice expired. You did not confirm publishing the order in time. Make a new order.",
"This order has been cancelled by the maker":"This order has been cancelled by the maker",
"Penalty lifted, good to go!":"Penalty lifted, good to go!",
"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s":"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s",
"Too low":"Too low",
"Too high":"Too high",
"Enter amount of fiat to exchange for bitcoin":"Enter amount of fiat to exchange for bitcoin",
"Amount {{currencyCode}}":"Amount {{currencyCode}}",
"You must specify an amount first":"You must specify an amount first",
"Take Order":"Take Order",
"Wait until you can take an order":"Wait until you can take an order",
"Cancel the order?":"Cancel the order?",
"If the order is cancelled now you will lose your bond.":"If the order is cancelled now you will lose your bond.",
"Confirm Cancel":"Confirm Cancel",
"The maker is away":"The maker is away",
"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.":"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.",
"Collaborative cancel the order?":"Collaborative cancel the order?",
"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.":"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.",
"Ask for Cancel":"Ask for Cancel",
"Cancel":"Cancel",
"Collaborative Cancel":"Collaborative Cancel",
"Invalid Order Id":"Invalid Order Id",
"You must have a robot avatar to see the order details":"You must have a robot avatar to see the order details",
"This order has been cancelled collaborativelly":"This order has been cancelled collaborativelly",
"You are not allowed to see this order":"You are not allowed to see this order",
"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues":"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues",
"CHAT BOX - Chat.js":"Chat Box",
"You":"You",
"Peer":"Peer",
"connected":"connected",
"disconnected":"disconnected",
"Type a message":"Type a message",
"Connecting...":"Connecting...",
"Send":"Send",
"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.",
"CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline",
"Contract Box":"Contract Box",
"Robots show commitment to their peers": "Robots show commitment to their peers",
"Lock {{amountSats}} Sats to PUBLISH order": "Lock {{amountSats}} Sats to PUBLISH order",
"Lock {{amountSats}} Sats to TAKE order": "Lock {{amountSats}} Sats to TAKE order",
"Lock {{amountSats}} Sats as collateral": "Lock {{amountSats}} Sats as collateral",
"Copy to clipboard":"Copy to clipboard",
"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.":"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.",
"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.":"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.",
"Your maker bond is locked":"Your maker bond is locked",
"Your taker bond is locked":"Your taker bond is locked",
"Your maker bond was settled":"Your maker bond was settled",
"Your taker bond was settled":"Your taker bond was settled",
"Your maker bond was unlock":"Your maker bond was unlock",
"Your taker bond was unlocked":"Your taker bond was unlocked",
"Your order is public":"Your order is public",
"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.":"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.",
"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).":"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).",
"Enable Telegram Notifications":"Enable Telegram Notifications",
"Enable TG Notifications":"Enable TG Notifications",
"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.":"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.",
"Go back":"Go back",
"Enable":"Enable",
"Telegram enabled":"Telegram enabled",
"Public orders for {{currencyCode}}":"Public orders for {{currencyCode}}",
"Premium rank": "Premium rank",
"Among public {{currencyCode}} orders (higher is cheaper)": "Among public {{currencyCode}} orders (higher is cheaper)",
"A taker has been found!":"A taker has been found!",
"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.":"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.",
"Submit an invoice for {{amountSats}} Sats":"Submit an invoice for {{amountSats}} Sats",
"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.":"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
"Payout Lightning Invoice":"Payout Lightning Invoice",
"Your invoice looks good!":"Your invoice looks good!",
"We are waiting for the seller lock the trade amount.":"We are waiting for the seller lock the trade amount.",
"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"The trade collateral is locked!":"The trade collateral is locked!",
"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.":"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.",
"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"Confirm {{currencyCode}} sent":"Confirm {{currencyCode}} sent",
"Confirm {{currencyCode}} received":"Confirm {{currencyCode}} received",
"Open Dispute":"Open Dispute",
"The order has expired":"The order has expired",
"Chat with the buyer":"Chat with the buyer",
"Chat with the seller":"Chat with the seller",
"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.":"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.",
"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.":"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.",
"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.":"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.",
"Wait for the seller to confirm he has received the payment.":"Wait for the seller to confirm he has received the payment.",
"Confirm you received {{currencyCode}}?":"Confirm you received {{currencyCode}}?",
"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.":"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.",
"Confirm":"Confirm",
"🎉Trade finished!🥳":"🎉Trade finished!🥳",
"rate_robosats":"What do you think of 🤖<1>RoboSats</1>⚡?",
"Thank you! RoboSats loves you too ❤️":"Thank you! RoboSats loves you too ❤️",
"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!",
"Thank you for using Robosats!":"Thank you for using Robosats!",
"let_us_know_hot_to_improve":"Let us know how the platform could improve (<1>Telegram</1> / <3>Github</3>)",
"Start Again":"Start Again",
"Attempting Lightning Payment":"Attempting Lightning Payment",
"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.",
"Retrying!":"Retrying!",
"Lightning Routing Failed":"Lightning Routing Failed",
"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ":"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ",
"Check the list of compatible wallets":"Check the list of compatible wallets",
"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.":"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.",
"Next attempt in":"Next attempt in",
"Do you want to open a dispute?":"Do you want to open a dispute?",
"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.":"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.",
"Disagree":"Disagree",
"Agree and open dispute":"Agree and open dispute",
"A dispute has been opened":"A dispute has been opened",
"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.":"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.",
"Submit dispute statement":"Submit dispute statement",
"We have received your statement":"We have received your statement",
"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.":"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.",
"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).":"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).",
"We have the statements":"We have the statements",
"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.":"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.",
"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 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.",
"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.",
"Project source code":"Project 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."
}

View File

@ -0,0 +1,354 @@
{
"UNSAFE-ALERT": "Alert that shows on top when browsing from the unsafe clearnet sites",
"You are not using RoboSats privately": "No estás usando RoboSats de forma privada",
"desktop_unsafe_alert": "Some features are disabled for your protection (e.g. chat) and you will not be able to complete a trade without them. To protect your privacy and fully enable RoboSats, 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",
"UserGenPage": "User Generation Page and Landing Page",
"Simple and Private LN P2P Exchange":"Intercambio LN P2P Fácil y Privado",
"This is your trading avatar":"Este es tu avatar de compraventa",
"Store your token safely":"Store your token safely",
"A robot avatar was found, welcome back!":"A robot avatar was found, welcome back!",
"Copied!":"Copied!",
"Generate a new token":"Generate a new token",
"Generate Robot":"Generate Robot",
"You must enter a new token first":"You must enter a new token first",
"Make Order":"Make Order",
"Info":"Info",
"View Book":"View Book",
"MAKER PAGE - MakerPage.js": "This is the page where users can create new orders",
"Order":"Order",
"Customize":"Customize",
"Buy or Sell Bitcoin?":"Buy or Sell Bitcoin?",
"Buy":"Buy",
"Sell":"Sell",
"Amount":"Amount",
"Amount of fiat to exchange for bitcoin":"Amount of fiat to exchange for bitcoin",
"Invalid":"Invalid",
"Enter your preferred fiat payment methods. Fast methods are highly recommended.":"Enter your preferred fiat payment methods. Fast methods are highly recommended.",
"Must be shorter than 65 characters":"Must be shorter than 65 characters",
"Swap Destination(s)":"Swap Destination(s)",
"Fiat Payment Method(s)":"Fiat Payment Method(s)",
"You can add any method":"You can add any method",
"Add New":"Add New",
"Choose a Pricing Method":"Choose a Pricing Method",
"Relative":"Relative",
"Let the price move with the market":"Let the price move with the market",
"Premium over Market (%)":"Premium over Market (%)",
"Explicit":"Explicit",
"Set a fix amount of satoshis":"Set a fix amount of satoshis",
"Satoshis":"Satoshis",
"Let the taker chose an amount within the range":"Let the taker chose an amount within the range",
"Enable Amount Range":"Enable Amount Range",
"From": "From",
"to":"to",
"Public Duration (HH:mm)":"Public Duration (HH:mm)",
"Set the skin-in-the-game, increase for higher safety assurance":"Set the skin-in-the-game, increase for higher safety assurance",
"Fidelity Bond Size":"Fidelity Bond Size",
"Allow bondless takers":"Allow bondless takers",
"COMING SOON - High risk! Limited to {{limitSats}}K Sats":"COMING SOON - High risk! Limited to {{limitSats}}K Sats",
"You must fill the order correctly":"You must fill the order correctly",
"Create Order":"Create Order",
"Back":"Back",
"Create a BTC buy order for ":"Create a BTC buy order for ",
"Create a BTC sell order for ":"Create a BTC sell order for ",
" of {{satoshis}} Satoshis":" of {{satoshis}} Satoshis",
" at market price":" at market price",
" at a {{premium}}% premium":" at a {{premium}}% premium",
" at a {{discount}}% discount":" at a {{discount}}% discount",
"Must be less than {{max}}%":"Must be less than {{max}}%",
"Must be more than {{min}}%":"Must be more than {{min}}%",
"Must be less than {{maxSats}": "Must be less than {{maxSats}}",
"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",
"Robot":"Robot",
"Is":"Is",
"Currency":"Currency",
"Payment Method":"Payment Method",
"Pay":"Pay",
"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 miscellaneous 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 Chinese speaking community!":"Join RoboSats Chinese 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 Box":"Order Box",
"Contract":"Contract",
"Active":"Active",
"Seen recently":"Seen recently",
"Inactive":"Inactive",
"(Seller)":"(Seller)",
"(Buyer)":"(Buyer)",
"Order maker":"Order maker",
"Order taker":"Order taker",
"Order Details":"Order Details",
"Order status":"Order status",
"Waiting for maker bond":"Waiting for maker bond",
"Public":"Public",
"Waiting for taker bond":"Waiting for taker bond",
"Cancelled":"Cancelled",
"Expired":"Expired",
"Waiting for trade collateral and buyer invoice":"Waiting for trade collateral and buyer invoice",
"Waiting only for seller trade collateral":"Waiting only for seller trade collateral",
"Waiting only for buyer invoice":"Waiting only for buyer invoice",
"Sending fiat - In chatroom":"Sending fiat - In chatroom",
"Fiat sent - In chatroom":"Fiat sent - In chatroom",
"In dispute":"In dispute",
"Collaboratively cancelled":"Collaboratively cancelled",
"Sending satoshis to buyer":"Sending satoshis to buyer",
"Sucessful trade":"Successful trade",
"Failed lightning network routing":"Failed lightning network routing",
"Wait for dispute resolution":"Wait for dispute resolution",
"Maker lost dispute":"Maker lost dispute",
"Taker lost dispute":"Taker lost dispute",
"Amount range":"Amount range",
"Swap destination":"Swap destination",
"Accepted payment methods":"Accepted payment methods",
"Others":"Others",
"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%":"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%",
"Price and Premium":"Price and Premium",
"Amount of Satoshis":"Amount of Satoshis",
"Premium over market price":"Premium over market price",
"Order ID":"Order ID",
"Expires in":"Expires in",
"{{nickname}} is asking for a collaborative cancel":"{{nickname}} is asking for a collaborative cancel",
"You asked for a collaborative cancellation":"You asked for a collaborative cancellation",
"Invoice expired. You did not confirm publishing the order in time. Make a new order.":"Invoice expired. You did not confirm publishing the order in time. Make a new order.",
"This order has been cancelled by the maker":"This order has been cancelled by the maker",
"Penalty lifted, good to go!":"Penalty lifted, good to go!",
"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s":"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s",
"Too low":"Too low",
"Too high":"Too high",
"Enter amount of fiat to exchange for bitcoin":"Enter amount of fiat to exchange for bitcoin",
"Amount {{currencyCode}}":"Amount {{currencyCode}}",
"You must specify an amount first":"You must specify an amount first",
"Take Order":"Take Order",
"Wait until you can take an order":"Wait until you can take an order",
"Cancel the order?":"Cancel the order?",
"If the order is cancelled now you will lose your bond.":"If the order is cancelled now you will lose your bond.",
"Confirm Cancel":"Confirm Cancel",
"The maker is away":"The maker is away",
"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.":"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.",
"Collaborative cancel the order?":"Collaborative cancel the order?",
"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.":"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.",
"Ask for Cancel":"Ask for Cancel",
"Cancel":"Cancel",
"Collaborative Cancel":"Collaborative Cancel",
"Invalid Order Id":"Invalid Order Id",
"You must have a robot avatar to see the order details":"You must have a robot avatar to see the order details",
"This order has been cancelled collaborativelly":"This order has been cancelled collaborativelly",
"You are not allowed to see this order":"You are not allowed to see this order",
"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues":"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues",
"CHAT BOX - Chat.js":"Chat Box",
"You":"You",
"Peer":"Peer",
"connected":"connected",
"disconnected":"disconnected",
"Type a message":"Type a message",
"Connecting...":"Connecting...",
"Send":"Send",
"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.",
"CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline",
"Contract Box":"Contract Box",
"Robots show commitment to their peers": "Robots show commitment to their peers",
"Lock {{amountSats}} Sats to PUBLISH order": "Lock {{amountSats}} Sats to PUBLISH order",
"Lock {{amountSats}} Sats to TAKE order": "Lock {{amountSats}} Sats to TAKE order",
"Lock {{amountSats}} Sats as collateral": "Lock {{amountSats}} Sats as collateral",
"Copy to clipboard":"Copy to clipboard",
"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.":"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.",
"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.":"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.",
"Your maker bond is locked":"Your maker bond is locked",
"Your taker bond is locked":"Your taker bond is locked",
"Your maker bond was settled":"Your maker bond was settled",
"Your taker bond was settled":"Your taker bond was settled",
"Your maker bond was unlock":"Your maker bond was unlock",
"Your taker bond was unlocked":"Your taker bond was unlocked",
"Your order is public":"Your order is public",
"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.":"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.",
"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).":"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).",
"Enable Telegram Notifications":"Enable Telegram Notifications",
"Enable TG Notifications":"Enable TG Notifications",
"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.":"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.",
"Go back":"Go back",
"Enable":"Enable",
"Telegram enabled":"Telegram enabled",
"Public orders for {{currencyCode}}":"Public orders for {{currencyCode}}",
"Premium rank": "Premium rank",
"Among public {{currencyCode}} orders (higher is cheaper)": "Among public {{currencyCode}} orders (higher is cheaper)",
"A taker has been found!":"A taker has been found!",
"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.":"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.",
"Submit an invoice for {{amountSats}} Sats":"Submit an invoice for {{amountSats}} Sats",
"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.":"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
"Payout Lightning Invoice":"Payout Lightning Invoice",
"Your invoice looks good!":"Your invoice looks good!",
"We are waiting for the seller lock the trade amount.":"We are waiting for the seller lock the trade amount.",
"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"The trade collateral is locked!":"The trade collateral is locked!",
"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.":"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.",
"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"Confirm {{currencyCode}} sent":"Confirm {{currencyCode}} sent",
"Confirm {{currencyCode}} received":"Confirm {{currencyCode}} received",
"Open Dispute":"Open Dispute",
"The order has expired":"The order has expired",
"Chat with the buyer":"Chat with the buyer",
"Chat with the seller":"Chat with the seller",
"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.":"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.",
"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.":"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.",
"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.":"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.",
"Wait for the seller to confirm he has received the payment.":"Wait for the seller to confirm he has received the payment.",
"Confirm you received {{currencyCode}}?":"Confirm you received {{currencyCode}}?",
"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.":"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.",
"Confirm":"Confirm",
"🎉Trade finished!🥳":"🎉Trade finished!🥳",
"rate_robosats":"What do you think of 🤖<1>RoboSats</1>⚡?",
"Thank you! RoboSats loves you too ❤️":"Thank you! RoboSats loves you too ❤️",
"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!",
"Thank you for using Robosats!":"Thank you for using Robosats!",
"let_us_know_hot_to_improve":"Let us know how the platform could improve (<1>Telegram</1> / <3>Github</3>)",
"Start Again":"Start Again",
"Attempting Lightning Payment":"Attempting Lightning Payment",
"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.",
"Retrying!":"Retrying!",
"Lightning Routing Failed":"Lightning Routing Failed",
"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ":"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ",
"Check the list of compatible wallets":"Check the list of compatible wallets",
"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.":"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.",
"Next attempt in":"Next attempt in",
"Do you want to open a dispute?":"Do you want to open a dispute?",
"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.":"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.",
"Disagree":"Disagree",
"Agree and open dispute":"Agree and open dispute",
"A dispute has been opened":"A dispute has been opened",
"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.":"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.",
"Submit dispute statement":"Submit dispute statement",
"We have received your statement":"We have received your statement",
"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.":"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.",
"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).":"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).",
"We have the statements":"We have the statements",
"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.":"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.",
"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 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.",
"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.",
"Project source code":"Project 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."
}

View File

@ -0,0 +1,354 @@
{
"UNSAFE ALERT - UnsafeAlert.js": "Alert that shows on top when browsing from the unsafe clearnet sites",
"You are not using RoboSats privately": "You are not using RoboSats privately",
"desktop_unsafe_alert": "Some features are disabled for your protection (e.g. chat) and you will not be able to complete a trade without them. To protect your privacy and fully enable RoboSats, 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",
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
"Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange",
"This is your trading avatar":"This is your trading avatar",
"Store your token safely":"Store your token safely",
"A robot avatar was found, welcome back!":"A robot avatar was found, welcome back!",
"Copied!":"Copied!",
"Generate a new token":"Generate a new token",
"Generate Robot":"Generate Robot",
"You must enter a new token first":"You must enter a new token first",
"Make Order":"Make Order",
"Info":"Info",
"View Book":"View Book",
"MAKER PAGE - MakerPage.js": "This is the page where users can create new orders",
"Order":"Order",
"Customize":"Customize",
"Buy or Sell Bitcoin?":"Buy or Sell Bitcoin?",
"Buy":"Buy",
"Sell":"Sell",
"Amount":"Amount",
"Amount of fiat to exchange for bitcoin":"Amount of fiat to exchange for bitcoin",
"Invalid":"Invalid",
"Enter your preferred fiat payment methods. Fast methods are highly recommended.":"Enter your preferred fiat payment methods. Fast methods are highly recommended.",
"Must be shorter than 65 characters":"Must be shorter than 65 characters",
"Swap Destination(s)":"Swap Destination(s)",
"Fiat Payment Method(s)":"Fiat Payment Method(s)",
"You can add any method":"You can add any method",
"Add New":"Add New",
"Choose a Pricing Method":"Choose a Pricing Method",
"Relative":"Relative",
"Let the price move with the market":"Let the price move with the market",
"Premium over Market (%)":"Premium over Market (%)",
"Explicit":"Explicit",
"Set a fix amount of satoshis":"Set a fix amount of satoshis",
"Satoshis":"Satoshis",
"Let the taker chose an amount within the range":"Let the taker chose an amount within the range",
"Enable Amount Range":"Enable Amount Range",
"From": "From",
"to":"to",
"Public Duration (HH:mm)":"Public Duration (HH:mm)",
"Set the skin-in-the-game, increase for higher safety assurance":"Set the skin-in-the-game, increase for higher safety assurance",
"Fidelity Bond Size":"Fidelity Bond Size",
"Allow bondless takers":"Allow bondless takers",
"COMING SOON - High risk! Limited to {{limitSats}}K Sats":"COMING SOON - High risk! Limited to {{limitSats}}K Sats",
"You must fill the order correctly":"You must fill the order correctly",
"Create Order":"Create Order",
"Back":"Back",
"Create a BTC buy order for ":"Create a BTC buy order for ",
"Create a BTC sell order for ":"Create a BTC sell order for ",
" of {{satoshis}} Satoshis":" of {{satoshis}} Satoshis",
" at market price":" at market price",
" at a {{premium}}% premium":" at a {{premium}}% premium",
" at a {{discount}}% discount":" at a {{discount}}% discount",
"Must be less than {{max}}%":"Must be less than {{max}}%",
"Must be more than {{min}}%":"Must be more than {{min}}%",
"Must be less than {{maxSats}": "Must be less than {{maxSats}}",
"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",
"Robot":"Robot",
"Is":"Is",
"Currency":"Currency",
"Payment Method":"Payment Method",
"Pay":"Pay",
"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 miscellaneous 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 Chinese speaking community!":"Join RoboSats Chinese 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 Box":"Order Box",
"Contract":"Contract",
"Active":"Active",
"Seen recently":"Seen recently",
"Inactive":"Inactive",
"(Seller)":"(Seller)",
"(Buyer)":"(Buyer)",
"Order maker":"Order maker",
"Order taker":"Order taker",
"Order Details":"Order Details",
"Order status":"Order status",
"Waiting for maker bond":"Waiting for maker bond",
"Public":"Public",
"Waiting for taker bond":"Waiting for taker bond",
"Cancelled":"Cancelled",
"Expired":"Expired",
"Waiting for trade collateral and buyer invoice":"Waiting for trade collateral and buyer invoice",
"Waiting only for seller trade collateral":"Waiting only for seller trade collateral",
"Waiting only for buyer invoice":"Waiting only for buyer invoice",
"Sending fiat - In chatroom":"Sending fiat - In chatroom",
"Fiat sent - In chatroom":"Fiat sent - In chatroom",
"In dispute":"In dispute",
"Collaboratively cancelled":"Collaboratively cancelled",
"Sending satoshis to buyer":"Sending satoshis to buyer",
"Sucessful trade":"Successful trade",
"Failed lightning network routing":"Failed lightning network routing",
"Wait for dispute resolution":"Wait for dispute resolution",
"Maker lost dispute":"Maker lost dispute",
"Taker lost dispute":"Taker lost dispute",
"Amount range":"Amount range",
"Swap destination":"Swap destination",
"Accepted payment methods":"Accepted payment methods",
"Others":"Others",
"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%":"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%",
"Price and Premium":"Price and Premium",
"Amount of Satoshis":"Amount of Satoshis",
"Premium over market price":"Premium over market price",
"Order ID":"Order ID",
"Expires in":"Expires in",
"{{nickname}} is asking for a collaborative cancel":"{{nickname}} is asking for a collaborative cancel",
"You asked for a collaborative cancellation":"You asked for a collaborative cancellation",
"Invoice expired. You did not confirm publishing the order in time. Make a new order.":"Invoice expired. You did not confirm publishing the order in time. Make a new order.",
"This order has been cancelled by the maker":"This order has been cancelled by the maker",
"Penalty lifted, good to go!":"Penalty lifted, good to go!",
"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s":"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s",
"Too low":"Too low",
"Too high":"Too high",
"Enter amount of fiat to exchange for bitcoin":"Enter amount of fiat to exchange for bitcoin",
"Amount {{currencyCode}}":"Amount {{currencyCode}}",
"You must specify an amount first":"You must specify an amount first",
"Take Order":"Take Order",
"Wait until you can take an order":"Wait until you can take an order",
"Cancel the order?":"Cancel the order?",
"If the order is cancelled now you will lose your bond.":"If the order is cancelled now you will lose your bond.",
"Confirm Cancel":"Confirm Cancel",
"The maker is away":"The maker is away",
"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.":"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.",
"Collaborative cancel the order?":"Collaborative cancel the order?",
"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.":"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.",
"Ask for Cancel":"Ask for Cancel",
"Cancel":"Cancel",
"Collaborative Cancel":"Collaborative Cancel",
"Invalid Order Id":"Invalid Order Id",
"You must have a robot avatar to see the order details":"You must have a robot avatar to see the order details",
"This order has been cancelled collaborativelly":"This order has been cancelled collaborativelly",
"You are not allowed to see this order":"You are not allowed to see this order",
"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues":"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues",
"CHAT BOX - Chat.js":"Chat Box",
"You":"You",
"Peer":"Peer",
"connected":"connected",
"disconnected":"disconnected",
"Type a message":"Type a message",
"Connecting...":"Connecting...",
"Send":"Send",
"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.",
"CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline",
"Contract Box":"Contract Box",
"Robots show commitment to their peers": "Robots show commitment to their peers",
"Lock {{amountSats}} Sats to PUBLISH order": "Lock {{amountSats}} Sats to PUBLISH order",
"Lock {{amountSats}} Sats to TAKE order": "Lock {{amountSats}} Sats to TAKE order",
"Lock {{amountSats}} Sats as collateral": "Lock {{amountSats}} Sats as collateral",
"Copy to clipboard":"Copy to clipboard",
"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.":"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.",
"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.":"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.",
"Your maker bond is locked":"Your maker bond is locked",
"Your taker bond is locked":"Your taker bond is locked",
"Your maker bond was settled":"Your maker bond was settled",
"Your taker bond was settled":"Your taker bond was settled",
"Your maker bond was unlock":"Your maker bond was unlock",
"Your taker bond was unlocked":"Your taker bond was unlocked",
"Your order is public":"Your order is public",
"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.":"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.",
"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).":"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).",
"Enable Telegram Notifications":"Enable Telegram Notifications",
"Enable TG Notifications":"Enable TG Notifications",
"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.":"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.",
"Go back":"Go back",
"Enable":"Enable",
"Telegram enabled":"Telegram enabled",
"Public orders for {{currencyCode}}":"Public orders for {{currencyCode}}",
"Premium rank": "Premium rank",
"Among public {{currencyCode}} orders (higher is cheaper)": "Among public {{currencyCode}} orders (higher is cheaper)",
"A taker has been found!":"A taker has been found!",
"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.":"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.",
"Submit an invoice for {{amountSats}} Sats":"Submit an invoice for {{amountSats}} Sats",
"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.":"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
"Payout Lightning Invoice":"Payout Lightning Invoice",
"Your invoice looks good!":"Your invoice looks good!",
"We are waiting for the seller lock the trade amount.":"We are waiting for the seller lock the trade amount.",
"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"The trade collateral is locked!":"The trade collateral is locked!",
"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.":"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.",
"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"Confirm {{currencyCode}} sent":"Confirm {{currencyCode}} sent",
"Confirm {{currencyCode}} received":"Confirm {{currencyCode}} received",
"Open Dispute":"Open Dispute",
"The order has expired":"The order has expired",
"Chat with the buyer":"Chat with the buyer",
"Chat with the seller":"Chat with the seller",
"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.":"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.",
"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.":"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.",
"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.":"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.",
"Wait for the seller to confirm he has received the payment.":"Wait for the seller to confirm he has received the payment.",
"Confirm you received {{currencyCode}}?":"Confirm you received {{currencyCode}}?",
"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.":"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.",
"Confirm":"Confirm",
"🎉Trade finished!🥳":"🎉Trade finished!🥳",
"rate_robosats":"What do you think of 🤖<1>RoboSats</1>⚡?",
"Thank you! RoboSats loves you too ❤️":"Thank you! RoboSats loves you too ❤️",
"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!",
"Thank you for using Robosats!":"Thank you for using Robosats!",
"let_us_know_hot_to_improve":"Let us know how the platform could improve (<1>Telegram</1> / <3>Github</3>)",
"Start Again":"Start Again",
"Attempting Lightning Payment":"Attempting Lightning Payment",
"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.",
"Retrying!":"Retrying!",
"Lightning Routing Failed":"Lightning Routing Failed",
"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ":"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ",
"Check the list of compatible wallets":"Check the list of compatible wallets",
"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.":"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.",
"Next attempt in":"Next attempt in",
"Do you want to open a dispute?":"Do you want to open a dispute?",
"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.":"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.",
"Disagree":"Disagree",
"Agree and open dispute":"Agree and open dispute",
"A dispute has been opened":"A dispute has been opened",
"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.":"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.",
"Submit dispute statement":"Submit dispute statement",
"We have received your statement":"We have received your statement",
"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.":"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.",
"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).":"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).",
"We have the statements":"We have the statements",
"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.":"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.",
"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 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.",
"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.",
"Project source code":"Project 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."
}

View File

@ -0,0 +1,354 @@
{
"UNSAFE ALERT - UnsafeAlert.js": "Alert that shows on top when browsing from the unsafe clearnet sites",
"You are not using RoboSats privately": "You are not using RoboSats privately",
"desktop_unsafe_alert": "Some features are disabled for your protection (e.g. chat) and you will not be able to complete a trade without them. To protect your privacy and fully enable RoboSats, 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",
"USER GENERATION PAGE - UserGenPage.js": "Landing Page and User Generation",
"Simple and Private LN P2P Exchange": "Simple and Private LN P2P Exchange",
"This is your trading avatar":"This is your trading avatar",
"Store your token safely":"Store your token safely",
"A robot avatar was found, welcome back!":"A robot avatar was found, welcome back!",
"Copied!":"Copied!",
"Generate a new token":"Generate a new token",
"Generate Robot":"Generate Robot",
"You must enter a new token first":"You must enter a new token first",
"Make Order":"Make Order",
"Info":"Info",
"View Book":"View Book",
"MAKER PAGE - MakerPage.js": "This is the page where users can create new orders",
"Order":"Order",
"Customize":"Customize",
"Buy or Sell Bitcoin?":"Buy or Sell Bitcoin?",
"Buy":"Buy",
"Sell":"Sell",
"Amount":"Amount",
"Amount of fiat to exchange for bitcoin":"Amount of fiat to exchange for bitcoin",
"Invalid":"Invalid",
"Enter your preferred fiat payment methods. Fast methods are highly recommended.":"Enter your preferred fiat payment methods. Fast methods are highly recommended.",
"Must be shorter than 65 characters":"Must be shorter than 65 characters",
"Swap Destination(s)":"Swap Destination(s)",
"Fiat Payment Method(s)":"Fiat Payment Method(s)",
"You can add any method":"You can add any method",
"Add New":"Add New",
"Choose a Pricing Method":"Choose a Pricing Method",
"Relative":"Relative",
"Let the price move with the market":"Let the price move with the market",
"Premium over Market (%)":"Premium over Market (%)",
"Explicit":"Explicit",
"Set a fix amount of satoshis":"Set a fix amount of satoshis",
"Satoshis":"Satoshis",
"Let the taker chose an amount within the range":"Let the taker chose an amount within the range",
"Enable Amount Range":"Enable Amount Range",
"From": "From",
"to":"to",
"Public Duration (HH:mm)":"Public Duration (HH:mm)",
"Set the skin-in-the-game, increase for higher safety assurance":"Set the skin-in-the-game, increase for higher safety assurance",
"Fidelity Bond Size":"Fidelity Bond Size",
"Allow bondless takers":"Allow bondless takers",
"COMING SOON - High risk! Limited to {{limitSats}}K Sats":"COMING SOON - High risk! Limited to {{limitSats}}K Sats",
"You must fill the order correctly":"You must fill the order correctly",
"Create Order":"Create Order",
"Back":"Back",
"Create a BTC buy order for ":"Create a BTC buy order for ",
"Create a BTC sell order for ":"Create a BTC sell order for ",
" of {{satoshis}} Satoshis":" of {{satoshis}} Satoshis",
" at market price":" at market price",
" at a {{premium}}% premium":" at a {{premium}}% premium",
" at a {{discount}}% discount":" at a {{discount}}% discount",
"Must be less than {{max}}%":"Must be less than {{max}}%",
"Must be more than {{min}}%":"Must be more than {{min}}%",
"Must be less than {{maxSats}": "Must be less than {{maxSats}}",
"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",
"Robot":"Robot",
"Is":"Is",
"Currency":"Currency",
"Payment Method":"Payment Method",
"Pay":"Pay",
"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 miscellaneous 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 Chinese speaking community!":"Join RoboSats Chinese 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 Box":"Order Box",
"Contract":"Contract",
"Active":"Active",
"Seen recently":"Seen recently",
"Inactive":"Inactive",
"(Seller)":"(Seller)",
"(Buyer)":"(Buyer)",
"Order maker":"Order maker",
"Order taker":"Order taker",
"Order Details":"Order Details",
"Order status":"Order status",
"Waiting for maker bond":"Waiting for maker bond",
"Public":"Public",
"Waiting for taker bond":"Waiting for taker bond",
"Cancelled":"Cancelled",
"Expired":"Expired",
"Waiting for trade collateral and buyer invoice":"Waiting for trade collateral and buyer invoice",
"Waiting only for seller trade collateral":"Waiting only for seller trade collateral",
"Waiting only for buyer invoice":"Waiting only for buyer invoice",
"Sending fiat - In chatroom":"Sending fiat - In chatroom",
"Fiat sent - In chatroom":"Fiat sent - In chatroom",
"In dispute":"In dispute",
"Collaboratively cancelled":"Collaboratively cancelled",
"Sending satoshis to buyer":"Sending satoshis to buyer",
"Sucessful trade":"Successful trade",
"Failed lightning network routing":"Failed lightning network routing",
"Wait for dispute resolution":"Wait for dispute resolution",
"Maker lost dispute":"Maker lost dispute",
"Taker lost dispute":"Taker lost dispute",
"Amount range":"Amount range",
"Swap destination":"Swap destination",
"Accepted payment methods":"Accepted payment methods",
"Others":"Others",
"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%":"{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%",
"Price and Premium":"Price and Premium",
"Amount of Satoshis":"Amount of Satoshis",
"Premium over market price":"Premium over market price",
"Order ID":"Order ID",
"Expires in":"Expires in",
"{{nickname}} is asking for a collaborative cancel":"{{nickname}} is asking for a collaborative cancel",
"You asked for a collaborative cancellation":"You asked for a collaborative cancellation",
"Invoice expired. You did not confirm publishing the order in time. Make a new order.":"Invoice expired. You did not confirm publishing the order in time. Make a new order.",
"This order has been cancelled by the maker":"This order has been cancelled by the maker",
"Penalty lifted, good to go!":"Penalty lifted, good to go!",
"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s":"You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s",
"Too low":"Too low",
"Too high":"Too high",
"Enter amount of fiat to exchange for bitcoin":"Enter amount of fiat to exchange for bitcoin",
"Amount {{currencyCode}}":"Amount {{currencyCode}}",
"You must specify an amount first":"You must specify an amount first",
"Take Order":"Take Order",
"Wait until you can take an order":"Wait until you can take an order",
"Cancel the order?":"Cancel the order?",
"If the order is cancelled now you will lose your bond.":"If the order is cancelled now you will lose your bond.",
"Confirm Cancel":"Confirm Cancel",
"The maker is away":"The maker is away",
"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.":"By taking this order you risk wasting your time. If the maker does not proceed in time, you will be compensated in satoshis for 50% of the maker bond.",
"Collaborative cancel the order?":"Collaborative cancel the order?",
"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.":"The trade escrow has been posted. The order can be cancelled only if both, maker and taker, agree to cancel.",
"Ask for Cancel":"Ask for Cancel",
"Cancel":"Cancel",
"Collaborative Cancel":"Collaborative Cancel",
"Invalid Order Id":"Invalid Order Id",
"You must have a robot avatar to see the order details":"You must have a robot avatar to see the order details",
"This order has been cancelled collaborativelly":"This order has been cancelled collaborativelly",
"You are not allowed to see this order":"You are not allowed to see this order",
"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues":"The Robotic Satoshis working in the warehouse did not understand you. Please, fill a Bug Issue in Github https://github.com/reckless-satoshi/robosats/issues",
"CHAT BOX - Chat.js":"Chat Box",
"You":"You",
"Peer":"Peer",
"connected":"connected",
"disconnected":"disconnected",
"Type a message":"Type a message",
"Connecting...":"Connecting...",
"Send":"Send",
"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.",
"CONTRACT BOX - TradeBox.js": "The Contract Box that guides users trough the whole trade pipeline",
"Contract Box":"Contract Box",
"Robots show commitment to their peers": "Robots show commitment to their peers",
"Lock {{amountSats}} Sats to PUBLISH order": "Lock {{amountSats}} Sats to PUBLISH order",
"Lock {{amountSats}} Sats to TAKE order": "Lock {{amountSats}} Sats to TAKE order",
"Lock {{amountSats}} Sats as collateral": "Lock {{amountSats}} Sats as collateral",
"Copy to clipboard":"Copy to clipboard",
"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.":"This is a hold invoice, it will freeze in your wallet. It will be charged only if you cancel or lose a dispute.",
"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.":"This is a hold invoice, it will freeze in your wallet. It will be released to the buyer once you confirm to have received the {{currencyCode}}.",
"Your maker bond is locked":"Your maker bond is locked",
"Your taker bond is locked":"Your taker bond is locked",
"Your maker bond was settled":"Your maker bond was settled",
"Your taker bond was settled":"Your taker bond was settled",
"Your maker bond was unlock":"Your maker bond was unlock",
"Your taker bond was unlocked":"Your taker bond was unlocked",
"Your order is public":"Your order is public",
"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.":"Be patient while robots check the book. It might take some time. This box will ring 🔊 once a robot takes your order.",
"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).":"Please note that if your premium is excessive or your currency or payment methods are not popular, your order might expire untaken. Your bond will return to you (no action needed).",
"Enable Telegram Notifications":"Enable Telegram Notifications",
"Enable TG Notifications":"Enable TG Notifications",
"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.":"You will be taken to a conversation with RoboSats telegram bot. Simply open the chat and press Start. Note that by enabling telegram notifications you might lower your level of anonymity.",
"Go back":"Go back",
"Enable":"Enable",
"Telegram enabled":"Telegram enabled",
"Public orders for {{currencyCode}}":"Public orders for {{currencyCode}}",
"Premium rank": "Premium rank",
"Among public {{currencyCode}} orders (higher is cheaper)": "Among public {{currencyCode}} orders (higher is cheaper)",
"A taker has been found!":"A taker has been found!",
"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.":"Please wait for the taker to lock a bond. If the taker does not lock a bond in time, the order will be made public again.",
"Submit an invoice for {{amountSats}} Sats":"Submit an invoice for {{amountSats}} Sats",
"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.":"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
"Payout Lightning Invoice":"Payout Lightning Invoice",
"Your invoice looks good!":"Your invoice looks good!",
"We are waiting for the seller lock the trade amount.":"We are waiting for the seller lock the trade amount.",
"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"The trade collateral is locked!":"The trade collateral is locked!",
"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.":"We are waiting for the buyer to post a lightning invoice. Once he does, you will be able to directly communicate the fiat payment details.",
"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the buyer does not cooperate, you will get back the trade collateral and your bond automatically. In addition, you will receive a compensation (check the rewards in your profile).",
"Confirm {{currencyCode}} sent":"Confirm {{currencyCode}} sent",
"Confirm {{currencyCode}} received":"Confirm {{currencyCode}} received",
"Open Dispute":"Open Dispute",
"The order has expired":"The order has expired",
"Chat with the buyer":"Chat with the buyer",
"Chat with the seller":"Chat with the seller",
"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.":"Say hi! Be helpful and concise. Let them know how to send you {{currencyCode}}.",
"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.":"The buyer has sent the fiat. Click 'Confirm Received' once you receive it.",
"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.":"Say hi! Ask for payment details and click 'Confirm Sent' as soon as the payment is sent.",
"Wait for the seller to confirm he has received the payment.":"Wait for the seller to confirm he has received the payment.",
"Confirm you received {{currencyCode}}?":"Confirm you received {{currencyCode}}?",
"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.":"Confirming that you received the fiat will finalize the trade. The satoshis in the escrow will be released to the buyer. Only confirm after the {{currencyCode}} has arrived to your account. In addition, if you have received {{currencyCode}} and do not confirm the receipt, you risk losing your bond.",
"Confirm":"Confirm",
"🎉Trade finished!🥳":"🎉Trade finished!🥳",
"rate_robosats":"What do you think of 🤖<1>RoboSats</1>⚡?",
"Thank you! RoboSats loves you too ❤️":"Thank you! RoboSats loves you too ❤️",
"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!",
"Thank you for using Robosats!":"Thank you for using Robosats!",
"let_us_know_hot_to_improve":"Let us know how the platform could improve (<1>Telegram</1> / <3>Github</3>)",
"Start Again":"Start Again",
"Attempting Lightning Payment":"Attempting Lightning Payment",
"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.",
"Retrying!":"Retrying!",
"Lightning Routing Failed":"Lightning Routing Failed",
"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ":"Your invoice has expired or more than 3 payment attempts have been made. Muun wallet is not recommended. ",
"Check the list of compatible wallets":"Check the list of compatible wallets",
"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.":"RoboSats will try to pay your invoice 3 times every 5 minutes. If it keeps failing, you will be able to submit a new invoice. Check whether you have enough inbound liquidity. Remember that lightning nodes must be online in order to receive payments.",
"Next attempt in":"Next attempt in",
"Do you want to open a dispute?":"Do you want to open a dispute?",
"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.":"The RoboSats staff will examine the statements and evidence provided. You need to build a complete case, as the staff cannot read the chat. It is best to provide a burner contact method with your statement. The satoshis in the trade escrow will be sent to the dispute winner, while the dispute loser will lose the bond.",
"Disagree":"Disagree",
"Agree and open dispute":"Agree and open dispute",
"A dispute has been opened":"A dispute has been opened",
"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.":"Please, submit your statement. Be clear and specific about what happened and provide the necessary evidence. You MUST provide a contact method: burner email, XMPP or telegram username to follow up with the staff. Disputes are solved at the discretion of real robots (aka humans), so be as helpful as possible to ensure a fair outcome. Max 5000 chars.",
"Submit dispute statement":"Submit dispute statement",
"We have received your statement":"We have received your statement",
"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.":"We are waiting for your trade counterpart statement. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com.",
"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).":"Please, save the information needed to identify your order and your payments: order ID; payment hashes of the bonds or escrow (check on your lightning wallet); exact amount of satoshis; and robot nickname. You will have to identify yourself as the user involved in this trade via email (or other contact methods).",
"We have the statements":"We have the statements",
"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.":"Both statements have been received, wait for the staff to resolve the dispute. If you are hesitant about the state of the dispute or want to add more information, contact robosats@protonmail.com. If you did not provide a contact method, or are unsure whether you wrote it right, write us immediately.",
"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 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.",
"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.",
"Project source code":"Project 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

@ -9,6 +9,8 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="A simple and private way to exchange bitcoin for national currencies. Robosats simplifies the peer-to-peer user experience and uses lightning hold invoices to minimize custody and trust requirements. No user registration required.">
<title>RoboSats - Simple and Private Bitcoin Exchange</title> <title>RoboSats - Simple and Private Bitcoin Exchange</title>
{% load static %} {% load static %}
<link rel="stylesheet" href="{% static "css/fonts.css" %}"/> <link rel="stylesheet" href="{% static "css/fonts.css" %}"/>