From 96c6358d4e5567dd7b764cf3c1eaea5a1457a007 Mon Sep 17 00:00:00 2001
From: Reckless_Satoshi <90936742+Reckless-Satoshi@users.noreply.github.com>
Date: Tue, 5 Apr 2022 14:25:53 +0000
Subject: [PATCH] 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
---
frontend/package-lock.json | 203 +++++++---
frontend/package.json | 8 +-
frontend/src/components/App.js | 30 +-
frontend/src/components/BookPage.js | 115 +++---
frontend/src/components/BottomBar.js | 194 +++++-----
frontend/src/components/Chat.js | 18 +-
frontend/src/components/InfoDialog.js | 137 +++----
frontend/src/components/MakerPage.js | 150 ++++----
frontend/src/components/OrderPage.js | 142 +++----
frontend/src/components/PaymentIcons.js | 1 -
frontend/src/components/PaymentText.js | 7 +-
frontend/src/components/TradeBox.js | 263 +++++++------
frontend/src/components/UnsafeAlert.js | 33 +-
frontend/src/components/UserGenPage.js | 42 +--
.../src/components/autocompletePayments.js | 6 +-
frontend/src/components/i18n.js | 45 +++
frontend/src/locales/CONTRIBUTING.MD | 35 ++
frontend/src/locales/de.json | 354 ++++++++++++++++++
frontend/src/locales/en.json | 354 ++++++++++++++++++
frontend/src/locales/es.json | 354 ++++++++++++++++++
frontend/src/locales/ru.json | 354 ++++++++++++++++++
frontend/src/locales/zh.json | 354 ++++++++++++++++++
frontend/static/frontend/main.js | 30 +-
frontend/templates/frontend/index.html | 2 +
24 files changed, 2592 insertions(+), 639 deletions(-)
create mode 100644 frontend/src/components/i18n.js
create mode 100644 frontend/src/locales/CONTRIBUTING.MD
create mode 100644 frontend/src/locales/de.json
create mode 100644 frontend/src/locales/en.json
create mode 100644 frontend/src/locales/es.json
create mode 100644 frontend/src/locales/ru.json
create mode 100644 frontend/src/locales/zh.json
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 26724235..f07e6d28 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -2657,9 +2657,9 @@
}
},
"ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
},
"ansi-styles": {
"version": "3.2.1",
@@ -2966,9 +2966,9 @@
}
},
"bplist-parser": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.0.tgz",
- "integrity": "sha512-zgmaRvT6AN1JpPPV+S0a1/FAtoxSreYDccZGIqEMSvZl9DMe70mJ7MFzpxa1X+gHVdkToE2haRUHHMiW1OdejA==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
+ "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
"requires": {
"big-integer": "1.6.x"
}
@@ -3398,6 +3398,14 @@
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.25.tgz",
"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": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -3415,14 +3423,15 @@
"integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA="
},
"css-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
- "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+ "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"requires": {
"boolbase": "^1.0.0",
- "css-what": "^3.2.1",
- "domutils": "^1.7.0",
- "nth-check": "^1.0.2"
+ "css-what": "^6.0.1",
+ "domhandler": "^4.3.1",
+ "domutils": "^2.8.0",
+ "nth-check": "^2.0.1"
}
},
"css-tree": {
@@ -3444,9 +3453,9 @@
}
},
"css-what": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
- "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ=="
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
},
"csstype": {
"version": "2.6.19",
@@ -3580,33 +3589,36 @@
}
},
"dom-serializer": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
- "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+ "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"requires": {
"domelementtype": "^2.0.1",
+ "domhandler": "^4.2.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": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
- "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+ "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": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
- "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+ "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"requires": {
- "dom-serializer": "0",
- "domelementtype": "1"
+ "dom-serializer": "^1.0.1",
+ "domelementtype": "^2.2.0",
+ "domhandler": "^4.2.0"
}
},
"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": {
"version": "1.8.1",
"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",
"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": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz",
@@ -5751,9 +5818,9 @@
}
},
"minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"mixin-deep": {
"version": "1.3.2",
@@ -5839,9 +5906,9 @@
}
},
"node-fetch": {
- "version": "2.6.6",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
- "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
}
@@ -5881,11 +5948,11 @@
}
},
"nth-check": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
- "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
+ "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
"requires": {
- "boolbase": "~1.0.0"
+ "boolbase": "^1.0.0"
}
},
"nullthrows": {
@@ -6143,9 +6210,9 @@
}
},
"plist": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
- "integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==",
+ "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"
@@ -6355,6 +6422,16 @@
"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": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -6601,11 +6678,11 @@
}
},
"react-native-svg": {
- "version": "12.1.1",
- "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.1.1.tgz",
- "integrity": "sha512-NIAJ8jCnXGCqGWXkkJ1GTzO4a3Md5at5sagYV8Vh4MXYnL4z5Rh428Wahjhh+LIjx40EE5xM5YtwyJBqOIba2Q==",
+ "version": "12.3.0",
+ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.3.0.tgz",
+ "integrity": "sha512-ESG1g1j7/WLD7X3XRFTQHVv0r6DpbHNNcdusngAODIxG88wpTWUZkhcM3A2HJTb+BbXTFDamHv7FwtRKWQ/ALg==",
"requires": {
- "css-select": "^2.1.0",
+ "css-select": "^4.2.1",
"css-tree": "^1.0.0-alpha.39"
}
},
@@ -7345,13 +7422,24 @@
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
},
"simple-plist": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.0.tgz",
- "integrity": "sha512-uYWpeGFtZtVt2NhG4AHgpwx323zxD85x42heMJBan1qAiqqozIlaGrwrEt6kRjXWRWIXsuV1VLCvVmZan2B5dg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz",
+ "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==",
"requires": {
"bplist-creator": "0.1.0",
- "bplist-parser": "0.3.0",
- "plist": "^3.0.4"
+ "bplist-parser": "0.3.1",
+ "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": {
@@ -7993,6 +8081,11 @@
"resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
"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": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 73e16d2a..a7dd8d1f 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -33,16 +33,22 @@
"@mui/x-data-grid": "^5.2.2",
"country-flag-icons": "^1.4.25",
"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",
"react-countdown": "^2.3.2",
+ "react-i18next": "^11.16.2",
"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-reader": "^2.2.1",
"react-responsive": "^9.0.0-beta.6",
"react-router-dom": "^5.2.0",
"react-world-flags": "^1.4.0",
"reconnecting-websocket": "^4.4.0",
+ "simple-plist": "^1.3.1",
"websocket": "^1.0.34"
}
}
diff --git a/frontend/src/components/App.js b/frontend/src/components/App.js
index 4d89def1..100c285b 100644
--- a/frontend/src/components/App.js
+++ b/frontend/src/components/App.js
@@ -5,6 +5,9 @@ import { CssBaseline, IconButton} from "@mui/material";
import { ThemeProvider, createTheme } from '@mui/material/styles';
import UnsafeAlert from "./UnsafeAlert";
+import { I18nextProvider } from "react-i18next";
+import i18n from "./i18n";
+
import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode';
@@ -12,18 +15,11 @@ export default class App extends Component {
constructor(props) {
super(props);
this.state = {
- nickname: null,
- token: null,
dark: false,
}
}
- setAppState=(newState)=>{
- this.setState(newState)
- }
-
- lightTheme = createTheme({
- });
+ lightTheme = createTheme({});
darkTheme = createTheme({
palette: {
@@ -36,14 +32,16 @@ export default class App extends Component {
render() {
return (
-
-
- this.setState({dark:!this.state.dark})}>
- {this.state.dark ? :}
-
-
-
-
+
+
+
+ this.setState({dark:!this.state.dark})}>
+ {this.state.dark ? :}
+
+
+
+
+
);
}
}
diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js
index a45b5961..27410bcd 100644
--- a/frontend/src/components/BookPage.js
+++ b/frontend/src/components/BookPage.js
@@ -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 { Link } from 'react-router-dom'
import { DataGrid } from '@mui/x-data-grid';
+import currencyDict from '../../static/assets/currencies.json';
+
import MediaQuery from 'react-responsive'
import Image from 'material-ui-image'
import getFlags from './getFlags'
import PaymentText from './PaymentText'
-export default class BookPage extends Component {
+class BookPage extends Component {
constructor(props) {
super(props);
this.state = {
orders: new Array({id:0,}),
- currencies_dict: {"0":"ANY"},
loading: true,
pageSize: 6,
};
- this.getCurrencyDict()
this.getOrderDetails(this.props.type, this.props.currency)
}
@@ -50,21 +51,13 @@ export default class BookPage extends Component {
})
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){
+ const { t } = this.props;
if (val){
- return val == 0 ? 'ANY' : this.state.currencies_dict[val.toString()]
+ return val == 0 ? t('ANY_currency') : currencyDict[val.toString()]
}else{
- return 'ANY'
+ return t('ANY_currency')
}
}
@@ -94,6 +87,7 @@ export default class BookPage extends Component {
}
bookListTableDesktop=()=>{
+ const { t } = this.props;
return (
{return (
-
+
);
} },
- { field: 'type', headerName: 'Is', width: 60 },
- { field: 'amount', headerName: 'Amount', type: 'number', width: 90,
+ { field: 'type', headerName: t("Is"), width: 60 },
+ { field: 'amount', headerName: t("Amount"), type: 'number', width: 90,
renderCell: (params) => {return (
{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}
)}},
- { field: 'currency', headerName: 'Currency', width: 100,
+ { field: 'currency', headerName: t("Currency"), width: 100,
renderCell: (params) => {return (
{params.row.currency+" "}{getFlags(params.row.currency)}
)
}},
- { field: 'payment_method', headerName: 'Payment Method', width: 180 ,
+ { field: 'payment_method', headerName: t("Payment Method"), width: 180 ,
renderCell: (params) => {return (
-
+
)} },
- { field: 'price', headerName: 'Price', type: 'number', width: 140,
+ { field: 'price', headerName: t("Price"), type: 'number', width: 140,
renderCell: (params) => {return (
{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }
)} },
- { field: 'premium', headerName: 'Premium', type: 'number', width: 100,
+ { field: 'premium', headerName: t("Premium"), type: 'number', width: 100,
renderCell: (params) => {return (
{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }
)} },
@@ -172,7 +166,7 @@ export default class BookPage extends Component {
}
bookListTablePhone=()=>{
-
+ const { t } = this.props;
return (
{return (
-
+
);
} },
- { field: 'type', headerName: 'Is', width: 60, hide:'true'},
- { field: 'amount', headerName: 'Amount', type: 'number', width: 84,
+ { field: 'type', headerName: t("Is"), width: 60, hide:'true'},
+ { field: 'amount', headerName: t("Amount"), type: 'number', width: 84,
renderCell: (params) => {return (
-
+
{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}
)} },
- { field: 'currency', headerName: 'Currency', width: 85,
+ { field: 'currency', headerName: t("Currency"), width: 85,
renderCell: (params) => {return (
//
{params.row.currency+" "}{getFlags(params.row.currency)}
//
)} },
- { field: 'payment_method', headerName: 'Payment Method', width: 180, hide:'true'},
- { field: 'payment_icons', headerName: 'Pay', width: 75 ,
+ { field: 'payment_method', headerName: t("Payment Method"), width: 180, hide:'true'},
+ { field: 'payment_icons', headerName: t("Pay"), width: 75 ,
renderCell: (params) => {return (
-
+
)} },
- { field: 'price', headerName: 'Price', type: 'number', width: 140, hide:'true',
+ { field: 'price', headerName: t("Price"), type: 'number', width: 140, hide:'true',
renderCell: (params) => {return (
{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }
)} },
- { field: 'premium', headerName: 'Premium', type: 'number', width: 85,
+ { field: 'premium', headerName: t("Premium"), type: 'number', width: 85,
renderCell: (params) => {return (
{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }
@@ -255,6 +249,7 @@ export default class BookPage extends Component {
}
render() {
+ const { t } = this.props;
return (
{/*
@@ -264,21 +259,21 @@ export default class BookPage extends Component {
- I want to
+ {t("I want to")}
@@ -286,21 +281,21 @@ export default class BookPage extends Component {
- 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") )}
@@ -309,7 +304,15 @@ export default class BookPage extends Component {
{ this.state.not_found ? "" :
- You are {this.props.type == 0 ? selling : (this.props.type == 1 ? buying :" 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")
+ )
+ }
}
@@ -318,15 +321,19 @@ export default class BookPage extends Component {
(
- 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})
+ }
-
+
- Be the first one to create an order
+ {t("Be the first one to create an order")}
@@ -350,10 +357,12 @@ export default class BookPage extends Component {
}
);
};
-}
\ No newline at end of file
+}
+
+export default withTranslation()(BookPage);
\ No newline at end of file
diff --git a/frontend/src/components/BottomBar.js b/frontend/src/components/BottomBar.js
index 6faf0207..818579d1 100644
--- a/frontend/src/components/BottomBar.js
+++ b/frontend/src/components/BottomBar.js
@@ -1,7 +1,9 @@
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 MediaQuery from 'react-responsive'
import { Link as LinkRouter } from 'react-router-dom'
+import Flags from 'country-flag-icons/react/3x2'
// Icons
import SettingsIcon from '@mui/icons-material/Settings';
@@ -54,7 +56,7 @@ function getCookie(name) {
return cookieValue;
}
-export default class BottomBar extends Component {
+class BottomBar extends Component {
constructor(props) {
super(props);
this.state = {
@@ -104,7 +106,7 @@ export default class BottomBar extends Component {
};
StatsDialog =() =>{
-
+ const { t } = this.props;
return(
}
- secondary="... somewhere on Earth!"/>
+ secondary={t("... somewhere on Earth!")}/>
@@ -200,6 +202,7 @@ export default class BottomBar extends Component {
};
CommunityDialog =() =>{
+ const { t } = this.props;
return(