diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,9 @@ # Ignore node_modules at every level node_modules/ + +# Ignore fbt generated files +.source_strings.json +.src_manifest.json +.enum_manifest.json +src/translatedFbts.json diff --git a/web/cashtab/config/paths.js b/web/cashtab/config/paths.js --- a/web/cashtab/config/paths.js +++ b/web/cashtab/config/paths.js @@ -70,6 +70,8 @@ appBuild: resolveApp('build'), appPublic: resolveApp('public'), appHtml: resolveApp('public/index.html'), + appI18nJs: resolveApp('src/i18n/init.js'), + appI18n: resolveApp('src/i18n'), appIndexJs: resolveModule(resolveApp, 'src/index'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), diff --git a/web/cashtab/config/webpack.config.js b/web/cashtab/config/webpack.config.js --- a/web/cashtab/config/webpack.config.js +++ b/web/cashtab/config/webpack.config.js @@ -269,9 +269,11 @@ // the line below with these two lines if you prefer the stock client: // require.resolve('webpack-dev-server/client') + '?/', // require.resolve('webpack/hot/dev-server'), + isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'), // Finally, this is your app's code: + paths.appI18nJs, paths.appIndexJs, // We include the app code last so that if there is a runtime error during // initialization, it doesn't blow up the WebpackDevServer client, and @@ -395,9 +397,11 @@ // We placed these paths second because we want `node_modules` to "win" // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebook/create-react-app/issues/253 - modules: ['node_modules', paths.appNodeModules].concat( - modules.additionalModulePaths || [], - ), + modules: [ + 'node_modules', + paths.appI18n, + paths.appNodeModules, + ].concat(modules.additionalModulePaths || []), // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: @@ -498,6 +502,17 @@ }, }, ], + [ + 'babel-plugin-fbt', + { + fbtEnumPath: path.join( + paths.appPath, + '.enum_manifest.json', + ), + extraOptions: { __self: true }, + }, + ], + 'babel-plugin-fbt-runtime', ], // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ diff --git a/web/cashtab/package-lock.json b/web/cashtab/package-lock.json --- a/web/cashtab/package-lock.json +++ b/web/cashtab/package-lock.json @@ -9,7 +9,6 @@ "dependencies": { "@ant-design/dark-theme": "^1.0.3", "@ant-design/icons": "^4.2.2", - "@babel/core": "7.6.0", "@fortawesome/fontawesome-free": "^5.15.1", "@psf/bch-js": "^3.9.1", "@svgr/webpack": "4.3.2", @@ -41,6 +40,8 @@ "eslint-plugin-react": "7.14.3", "eslint-plugin-react-hooks": "^1.6.1", "ethereum-blockies-base64": "^1.0.2", + "fbt": "^0.16.0", + "fbt-easy-setup": "^0.0.1", "file-loader": "3.0.1", "fs-extra": "7.0.1", "gh-pages": "^2.1.1", @@ -91,7 +92,12 @@ "webpack-manifest-plugin": "2.0.4" }, "devDependencies": { + "@babel/core": "^7.6.0", + "@babel/node": "^7.12.6", "@testing-library/react": "^11.1.0", + "babel-plugin-fbt": "^0.16.0", + "babel-plugin-fbt-runtime": "^0.9.12", + "fbt-generate-translations": "^0.0.4", "less": "^3.10.3", "less-loader": "^5.0.0", "react-test-renderer": "^17.0.0", @@ -492,6 +498,61 @@ "js-tokens": "^4.0.0" } }, + "node_modules/@babel/node": { + "version": "7.12.6", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.12.6.tgz", + "integrity": "sha512-A1TpW2X05ZkI5+WV7Aa24QX4LyGwrGUQPflG1CyBdr84jUuH0mhkE2BQWSQAlfRnp4bMLjeveMJIhS20JaOfVQ==", + "dev": true, + "dependencies": { + "@babel/register": "^7.12.1", + "commander": "^4.0.1", + "core-js": "^3.2.1", + "lodash": "^4.17.19", + "node-environment-flags": "^1.0.5", + "regenerator-runtime": "^0.13.4", + "resolve": "^1.13.1", + "v8flags": "^3.1.1" + }, + "bin": { + "babel-node": "bin/babel-node.js" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/node/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@babel/node/node_modules/core-js": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.0.tgz", + "integrity": "sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/@babel/node/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@babel/parser": { "version": "7.12.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", @@ -1511,6 +1572,44 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/register": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.12.1.tgz", + "integrity": "sha512-XWcmseMIncOjoydKZnWvWi0/5CUCD+ZYKhRwgYlWOrA8fGZ/FjuLRpqtIhLOVD/fvR1b9DQHtZPn68VvhpYf+Q==", + "dev": true, + "dependencies": { + "find-cache-dir": "^2.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@babel/runtime": { "version": "7.12.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", @@ -5632,6 +5731,174 @@ "object.assign": "^4.1.0" } }, + "node_modules/babel-plugin-fbt": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/babel-plugin-fbt/-/babel-plugin-fbt-0.16.0.tgz", + "integrity": "sha512-A38Gy+OuPh6g3wXKeR1rSqLUbLzRnF9CkrQN8482xNjlMAbt1M76zePx7j+6H9QYSuyUqMC4HDHmOSaAHHi5oA==", + "dependencies": { + "@babel/core": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-transform-flow-strip-types": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.8.3", + "@babel/types": "^7.2.2", + "fb-babel-plugin-utils": "^0.11.0", + "glob": "^7.1.6", + "invariant": "^2.2.4", + "jest-docblock": "^26.0.0", + "nullthrows": "^1.1.1", + "shelljs": "^0.8.4", + "yargs": "^15.3.1" + }, + "bin": { + "fbt-collect": "bin/collectFBT.bin.js", + "fbt-manifest": "bin/manifest.bin.js", + "fbt-translate": "bin/translate.bin.js" + } + }, + "node_modules/babel-plugin-fbt-runtime": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/babel-plugin-fbt-runtime/-/babel-plugin-fbt-runtime-0.9.12.tgz", + "integrity": "sha512-YbSWgNzNBoRF6golLWvpSg2HA0SwKCUSoI0Syl0y846cYfq5ZzFKuCQt9zRFkmaWFQ1ncuI4wHRznchFreQi9g==", + "dependencies": { + "@babel/core": "^7.0.0", + "fbjs": "^1.0.0" + }, + "peerDependencies": { + "babel-plugin-fbt": "^0.14.2" + } + }, + "node_modules/babel-plugin-fbt-runtime/node_modules/fbjs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz", + "integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==", + "dependencies": { + "core-js": "^2.4.1", + "fbjs-css-vars": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "node_modules/babel-plugin-fbt/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-plugin-fbt/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/babel-plugin-fbt/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-plugin-fbt/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/babel-plugin-fbt/node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-fbt/node_modules/jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/babel-plugin-fbt/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-fbt/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-fbt/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-fbt/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/babel-plugin-istanbul": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", @@ -7291,6 +7558,25 @@ "node": "*" } }, + "node_modules/cli-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz", + "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=", + "dependencies": { + "es5-ext": "0.8.x" + }, + "engines": { + "node": ">=0.1.103" + } + }, + "node_modules/cli-color/node_modules/es5-ext": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", + "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=", + "engines": { + "node": ">=0.4" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -8723,6 +9009,17 @@ "randombytes": "^2.0.0" } }, + "node_modules/difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", + "dependencies": { + "heap": ">= 0.2.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/dijkstrajs": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", @@ -8954,6 +9251,17 @@ "node": ">=0.10" } }, + "node_modules/dreamopt": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.6.0.tgz", + "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=", + "dependencies": { + "wordwrap": ">=0.0.2" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -10471,6 +10779,25 @@ "node": ">=0.8.0" } }, + "node_modules/fb-babel-plugin-utils": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/fb-babel-plugin-utils/-/fb-babel-plugin-utils-0.11.0.tgz", + "integrity": "sha512-xJ9j9hlFjbbH0yrkVCZTHpmd9EN46+rxEwZLrg+TbF1DegwXnNFT5MF/U+iQgeMhQVGWmhkR1ez0AGOBwX/cKA==", + "dependencies": { + "@babel/core": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.7.4", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-numeric-separator": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "json-diff": "^0.5.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -10493,12 +10820,49 @@ "ua-parser-js": "^0.7.18" } }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, "node_modules/fbjs/node_modules/core-js": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", "deprecated": "core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3." }, + "node_modules/fbt": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/fbt/-/fbt-0.16.0.tgz", + "integrity": "sha512-QT5K+aF2b/7CH4takZeYIBAqH9cATV2IXV5kCmI5lWfPMssv34sDbBYJjoWNEV3nU/kDBogCr3QOahuOh8hPMw==", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "babel-plugin-fbt": "^0.10.x", + "babel-plugin-fbt-runtime": "^0.9.x", + "react": "0.12.0 - 16.x.x" + } + }, + "node_modules/fbt-easy-setup": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/fbt-easy-setup/-/fbt-easy-setup-0.0.1.tgz", + "integrity": "sha512-toSBhtEOuzy2rdO7jduir5yyhnwBI2PPGhrhtWnr5ibFJKbttX1pfnl6QaP2I/fbC/0uLQF2TuoN3Xk6uuKvAg==", + "peerDependencies": { + "fbt": ">=0.9.0", + "react": ">=16.8.0" + } + }, + "node_modules/fbt-generate-translations": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fbt-generate-translations/-/fbt-generate-translations-0.0.4.tgz", + "integrity": "sha512-j+1+ZE6Ce1hl2GQHfyYNEIRN2gtFyukRafKPtdghiSmXB7jOPJxGIF+Jsm+JcZQYAQexdoX4nvSZqZBI84dc0Q==", + "dev": true, + "dependencies": { + "assert": "^2.0.0", + "yargs": "^13.3.0" + } + }, "node_modules/fecha": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", @@ -11748,6 +12112,11 @@ "he": "bin/he" } }, + "node_modules/heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + }, "node_modules/hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -11789,6 +12158,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -12523,6 +12904,14 @@ "node": ">=6" } }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -16617,6 +17006,22 @@ "node": ">=4" } }, + "node_modules/json-diff": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.5.4.tgz", + "integrity": "sha512-q5Xmx9QXNOzOzIlMoYtLrLiu4Jl/Ce2bn0CNcv54PhyH89CI4GWlGVDye8ei2Ijt9R3U+vsWPsXpLUNob8bs8Q==", + "dependencies": { + "cli-color": "~0.1.6", + "difflib": "~0.2.1", + "dreamopt": "~0.6.0" + }, + "bin": { + "json-diff": "bin/json-diff.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -18232,6 +18637,25 @@ "lodash.toarray": "^4.4.0" } }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -18492,6 +18916,11 @@ "boolbase": "~1.0.0" } }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, "node_modules/num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -19445,6 +19874,15 @@ "node": ">=4" } }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -23266,6 +23704,17 @@ "node": ">=4" } }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/recursive-readdir": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", @@ -24554,6 +25003,22 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" }, + "node_modules/shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -27224,6 +27689,18 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==" }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -28030,6 +28507,11 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, "node_modules/workbox-background-sync": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz", @@ -28825,6 +29307,46 @@ "js-tokens": "^4.0.0" } }, + "@babel/node": { + "version": "7.12.6", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.12.6.tgz", + "integrity": "sha512-A1TpW2X05ZkI5+WV7Aa24QX4LyGwrGUQPflG1CyBdr84jUuH0mhkE2BQWSQAlfRnp4bMLjeveMJIhS20JaOfVQ==", + "dev": true, + "requires": { + "@babel/register": "^7.12.1", + "commander": "^4.0.1", + "core-js": "^3.2.1", + "lodash": "^4.17.19", + "node-environment-flags": "^1.0.5", + "regenerator-runtime": "^0.13.4", + "resolve": "^1.13.1", + "v8flags": "^3.1.1" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "core-js": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.0.tgz", + "integrity": "sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + } + } + }, "@babel/parser": { "version": "7.12.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", @@ -29599,6 +30121,37 @@ "@babel/plugin-transform-typescript": "^7.9.0" } }, + "@babel/register": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.12.1.tgz", + "integrity": "sha512-XWcmseMIncOjoydKZnWvWi0/5CUCD+ZYKhRwgYlWOrA8fGZ/FjuLRpqtIhLOVD/fvR1b9DQHtZPn68VvhpYf+Q==", + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "@babel/runtime": { "version": "7.12.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", @@ -32175,7 +32728,8 @@ "acorn-jsx": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "requires": {} }, "acorn-walk": { "version": "6.2.0", @@ -32293,12 +32847,14 @@ "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "requires": {} }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "alphanum-sort": { "version": "1.0.2", @@ -32902,6 +33458,143 @@ "object.assign": "^4.1.0" } }, + "babel-plugin-fbt": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/babel-plugin-fbt/-/babel-plugin-fbt-0.16.0.tgz", + "integrity": "sha512-A38Gy+OuPh6g3wXKeR1rSqLUbLzRnF9CkrQN8482xNjlMAbt1M76zePx7j+6H9QYSuyUqMC4HDHmOSaAHHi5oA==", + "requires": { + "@babel/core": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-transform-flow-strip-types": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.8.3", + "@babel/types": "^7.2.2", + "fb-babel-plugin-utils": "^0.11.0", + "glob": "^7.1.6", + "invariant": "^2.2.4", + "jest-docblock": "^26.0.0", + "nullthrows": "^1.1.1", + "shelljs": "^0.8.4", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + }, + "jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "requires": { + "detect-newline": "^3.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "babel-plugin-fbt-runtime": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/babel-plugin-fbt-runtime/-/babel-plugin-fbt-runtime-0.9.12.tgz", + "integrity": "sha512-YbSWgNzNBoRF6golLWvpSg2HA0SwKCUSoI0Syl0y846cYfq5ZzFKuCQt9zRFkmaWFQ1ncuI4wHRznchFreQi9g==", + "requires": { + "@babel/core": "^7.0.0", + "fbjs": "^1.0.0" + }, + "dependencies": { + "fbjs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz", + "integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==", + "requires": { + "core-js": "^2.4.1", + "fbjs-css-vars": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + } + } + }, "babel-plugin-istanbul": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", @@ -32982,7 +33675,8 @@ "babel-plugin-named-asset-import": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.7.tgz", - "integrity": "sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==" + "integrity": "sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==", + "requires": {} }, "babel-plugin-styled-components": { "version": "1.12.0", @@ -34303,6 +34997,21 @@ "resolved": "https://registry.npmjs.org/clear/-/clear-0.1.0.tgz", "integrity": "sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==" }, + "cli-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz", + "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=", + "requires": { + "es5-ext": "0.8.x" + }, + "dependencies": { + "es5-ext": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", + "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=" + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -35494,6 +36203,14 @@ "randombytes": "^2.0.0" } }, + "difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", + "requires": { + "heap": ">= 0.2.0" + } + }, "dijkstrajs": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", @@ -35690,6 +36407,14 @@ "create-hmac": "^1.1.4" } }, + "dreamopt": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.6.0.tgz", + "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=", + "requires": { + "wordwrap": ">=0.0.2" + } + }, "duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -35862,7 +36587,8 @@ "ws": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", - "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==" + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "requires": {} } } }, @@ -36213,12 +36939,14 @@ "eslint-config-standard": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", - "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==" + "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==", + "requires": {} }, "eslint-config-standard-jsx": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-5.0.0.tgz", - "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==" + "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==", + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.4", @@ -36444,12 +37172,14 @@ "eslint-plugin-react-hooks": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz", - "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==" + "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==", + "requires": {} }, "eslint-plugin-standard": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=" + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "requires": {} }, "eslint-scope": { "version": "5.1.1", @@ -36935,6 +37665,25 @@ "websocket-driver": ">=0.5.1" } }, + "fb-babel-plugin-utils": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/fb-babel-plugin-utils/-/fb-babel-plugin-utils-0.11.0.tgz", + "integrity": "sha512-xJ9j9hlFjbbH0yrkVCZTHpmd9EN46+rxEwZLrg+TbF1DegwXnNFT5MF/U+iQgeMhQVGWmhkR1ez0AGOBwX/cKA==", + "requires": { + "@babel/core": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.7.4", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-numeric-separator": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "json-diff": "^0.5.4" + } + }, "fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -36964,6 +37713,35 @@ } } }, + "fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "fbt": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/fbt/-/fbt-0.16.0.tgz", + "integrity": "sha512-QT5K+aF2b/7CH4takZeYIBAqH9cATV2IXV5kCmI5lWfPMssv34sDbBYJjoWNEV3nU/kDBogCr3QOahuOh8hPMw==", + "requires": { + "invariant": "^2.2.4" + } + }, + "fbt-easy-setup": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/fbt-easy-setup/-/fbt-easy-setup-0.0.1.tgz", + "integrity": "sha512-toSBhtEOuzy2rdO7jduir5yyhnwBI2PPGhrhtWnr5ibFJKbttX1pfnl6QaP2I/fbC/0uLQF2TuoN3Xk6uuKvAg==", + "requires": {} + }, + "fbt-generate-translations": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fbt-generate-translations/-/fbt-generate-translations-0.0.4.tgz", + "integrity": "sha512-j+1+ZE6Ce1hl2GQHfyYNEIRN2gtFyukRafKPtdghiSmXB7jOPJxGIF+Jsm+JcZQYAQexdoX4nvSZqZBI84dc0Q==", + "dev": true, + "requires": { + "assert": "^2.0.0", + "yargs": "^13.3.0" + } + }, "fecha": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", @@ -37960,6 +38738,11 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + }, "hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -38003,6 +38786,15 @@ } } }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -38594,6 +39386,11 @@ "ipaddr.js": "^1.9.0" } }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -40715,7 +41512,8 @@ "jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "requires": {} }, "jest-regex-util": { "version": "26.0.0", @@ -41842,6 +42640,16 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, + "json-diff": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.5.4.tgz", + "integrity": "sha512-q5Xmx9QXNOzOzIlMoYtLrLiu4Jl/Ce2bn0CNcv54PhyH89CI4GWlGVDye8ei2Ijt9R3U+vsWPsXpLUNob8bs8Q==", + "requires": { + "cli-color": "~0.1.6", + "difflib": "~0.2.1", + "dreamopt": "~0.6.0" + } + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -43153,6 +43961,24 @@ "lodash.toarray": "^4.4.0" } }, + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -43388,6 +44214,11 @@ "boolbase": "~1.0.0" } }, + "nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -44121,6 +44952,12 @@ "json-parse-better-errors": "^1.0.1" } }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -46973,12 +47810,14 @@ "react-ga": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.0.tgz", - "integrity": "sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ==" + "integrity": "sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ==", + "requires": {} }, "react-image": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-image/-/react-image-4.0.3.tgz", - "integrity": "sha512-19MUK9u1qaw9xys8XEsVkSpVhHctEBUeYFvrLTe1PN+4w5Co13AN2WA7xtBshPM6SthsOj77SlDrEAeOaJpf7g==" + "integrity": "sha512-19MUK9u1qaw9xys8XEsVkSpVhHctEBUeYFvrLTe1PN+4w5Co13AN2WA7xtBshPM6SthsOj77SlDrEAeOaJpf7g==", + "requires": {} }, "react-is": { "version": "17.0.1", @@ -47330,6 +48169,14 @@ "util.promisify": "^1.0.0" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, "recursive-readdir": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", @@ -48349,6 +49196,16 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" }, + "shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -49009,7 +49866,8 @@ "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "requires": {} }, "ansi-escapes": { "version": "3.2.0", @@ -49784,7 +50642,8 @@ "stylis-rule-sheet": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", - "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", + "requires": {} }, "supports-color": { "version": "5.5.0", @@ -50202,7 +51061,8 @@ "ts-pnp": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.4.tgz", - "integrity": "sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==" + "integrity": "sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==", + "requires": {} }, "tslib": { "version": "1.14.1", @@ -50575,6 +51435,15 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==" }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -51233,6 +52102,11 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, "workbox-background-sync": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz", diff --git a/web/cashtab/package.json b/web/cashtab/package.json --- a/web/cashtab/package.json +++ b/web/cashtab/package.json @@ -6,7 +6,6 @@ "dependencies": { "@ant-design/dark-theme": "^1.0.3", "@ant-design/icons": "^4.2.2", - "@babel/core": "7.6.0", "@fortawesome/fontawesome-free": "^5.15.1", "@psf/bch-js": "^3.9.1", "@svgr/webpack": "4.3.2", @@ -38,6 +37,8 @@ "eslint-plugin-react": "7.14.3", "eslint-plugin-react-hooks": "^1.6.1", "ethereum-blockies-base64": "^1.0.2", + "fbt": "^0.16.0", + "fbt-easy-setup": "^0.0.1", "file-loader": "3.0.1", "fs-extra": "7.0.1", "gh-pages": "^2.1.1", @@ -94,11 +95,21 @@ ] }, "scripts": { + "manifest-fbts": "NODE_ENV=production node node_modules/babel-plugin-fbt/bin/manifest --src src", + "collect-fbts": "NODE_ENV=production node node_modules/babel-plugin-fbt/bin/collectFBT --pretty --manifest < .src_manifest.json > .source_strings.json", + "translate-fbts": "NODE_ENV=production node node_modules/babel-plugin-fbt/bin/translate.js --pretty --translations translations/*.json --jenkins > src/translatedFbts.json", + "translate-fbts-single-file": "NODE_ENV=production node node_modules/babel-plugin-fbt/bin/translate.js --pretty --jenkins --stdin < translation_input.json > src/translatedFbts.json", + "clean-fbts": "rm .enum_manifest.json .src_manifest.json .source_strings.json src/translatedFbts.json 2&> /dev/null || exit 0", + "fbt-generate-translations": "NODE_ENV=production node node_modules/fbt-generate-translations --locales src/i18n/locales.js --multi-files translations", + "fbt-generate-translations-single-file": "NODE_ENV=production node node_modules/fbt-generate-translations --locales src/i18n/locales.js", + "prepare-fbts": "NODE_ENV=production npm run manifest-fbts && npm run collect-fbts && npm run fbt-generate-translations && npm run translate-fbts", + "prestart": "npm run prepare-fbts", + "prebuild": "npm run prepare-fbts", "start": "node scripts/start.js", "build": "node scripts/build.js", "predeploy": "npm run build", "test": "node scripts/test.js", - "test:coverage": "yarn test --coverage --watchAll=false", + "test:coverage": "npm run test --coverage --watchAll=false", "debug": "node --inspect-brk=9229 scripts/start.js" }, "eslintConfig": { @@ -178,7 +189,12 @@ ] }, "devDependencies": { + "@babel/core": "^7.6.0", + "@babel/node": "^7.12.6", "@testing-library/react": "^11.1.0", + "babel-plugin-fbt": "^0.16.0", + "babel-plugin-fbt-runtime": "^0.9.12", + "fbt-generate-translations": "^0.0.4", "less": "^3.10.3", "less-loader": "^5.0.0", "react-test-renderer": "^17.0.0", diff --git a/web/cashtab/src/components/App.js b/web/cashtab/src/components/App.js --- a/web/cashtab/src/components/App.js +++ b/web/cashtab/src/components/App.js @@ -20,6 +20,7 @@ useHistory, } from 'react-router-dom'; +import fbt from 'fbt'; const { Footer } = Layout; const { TabPane } = Tabs; @@ -216,7 +217,7 @@ type="folder-open" theme="filled" /> - Wallet + Wallet } key="wallet" @@ -232,7 +233,7 @@ type="caret-right" theme="filled" /> - Send + Send } key="send" @@ -249,7 +250,9 @@ type="setting" theme="filled" /> - Settings + + Settings + } key="configure" diff --git a/web/cashtab/src/i18n/init.js b/web/cashtab/src/i18n/init.js new file mode 100644 --- /dev/null +++ b/web/cashtab/src/i18n/init.js @@ -0,0 +1,15 @@ +import { init } from 'fbt'; +import translations from '../translatedFbts.json'; +import locales from './locales'; +const viewerContext = { + locale: navigator.language.replace('-', '_'), +}; + +init({ + translations, + hooks: { + getViewerContext: () => viewerContext, + }, + locales, + defaultLocale: navigator.language, +}); diff --git a/web/cashtab/src/i18n/locales.js b/web/cashtab/src/i18n/locales.js new file mode 100644 --- /dev/null +++ b/web/cashtab/src/i18n/locales.js @@ -0,0 +1,14 @@ +module.exports = { + en_US: { + bcp47: 'en-US', + displayName: 'English (US)', + englishName: 'English (US)', + rtl: false, + }, + pt_BR: { + bcp47: 'pt-BR', + displayName: 'Português (Brasil)', + englishName: 'Portuguese (Brazilian)', + rtl: false, + }, +}; diff --git a/web/cashtab/translation_input.json b/web/cashtab/translation_input.json new file mode 100644 --- /dev/null +++ b/web/cashtab/translation_input.json @@ -0,0 +1,100 @@ +{ + "phrases": [ + { + "hashToText": { + "fJKXmrI8Wv3P5CqV03fP1w==": "Wallet" + }, + "filepath": "src/components/App.js", + "line_beg": 223, + "col_beg": 56, + "line_end": 223, + "col_end": 87, + "desc": "Wallet", + "project": "", + "type": "text", + "jsfbt": "Wallet" + }, + { + "hashToText": { + "4b2jW7VoOq0mSpln/V61BA==": "Send" + }, + "filepath": "src/components/App.js", + "line_beg": 239, + "col_beg": 56, + "line_end": 239, + "col_end": 83, + "desc": "Send", + "project": "", + "type": "text", + "jsfbt": "Send" + }, + { + "hashToText": { + "3Tx5Pa2fR7yHhhtDr3A40Q==": "Settings" + }, + "filepath": "src/components/App.js", + "line_beg": 256, + "col_beg": 56, + "line_end": 256, + "col_end": 91, + "desc": "Settings", + "project": "", + "type": "text", + "jsfbt": "Settings" + } + ], + "translationGroups": [ + { + "fb-locale": "en_US", + "translations": { + "fJKXmrI8Wv3P5CqV03fP1w==": { + "translations": [ + { + "translation": "Wallet" + } + ] + }, + "4b2jW7VoOq0mSpln/V61BA==": { + "translations": [ + { + "translation": "Send" + } + ] + }, + "3Tx5Pa2fR7yHhhtDr3A40Q==": { + "translations": [ + { + "translation": "Settings" + } + ] + } + } + }, + { + "fb-locale": "pt_BR", + "translations": { + "fJKXmrI8Wv3P5CqV03fP1w==": { + "translations": [ + { + "translation": "Wallet" + } + ] + }, + "4b2jW7VoOq0mSpln/V61BA==": { + "translations": [ + { + "translation": "Send" + } + ] + }, + "3Tx5Pa2fR7yHhhtDr3A40Q==": { + "translations": [ + { + "translation": "Settings" + } + ] + } + } + } + ] +} diff --git a/web/cashtab/translations/en_US.json b/web/cashtab/translations/en_US.json new file mode 100644 --- /dev/null +++ b/web/cashtab/translations/en_US.json @@ -0,0 +1,26 @@ +{ + "fb-locale": "en_US", + "translations": { + "fJKXmrI8Wv3P5CqV03fP1w==": { + "translations": [ + { + "translation": "Wallet" + } + ] + }, + "4b2jW7VoOq0mSpln/V61BA==": { + "translations": [ + { + "translation": "Send" + } + ] + }, + "3Tx5Pa2fR7yHhhtDr3A40Q==": { + "translations": [ + { + "translation": "Settings" + } + ] + } + } +} diff --git a/web/cashtab/translations/pt_BR.json b/web/cashtab/translations/pt_BR.json new file mode 100644 --- /dev/null +++ b/web/cashtab/translations/pt_BR.json @@ -0,0 +1,26 @@ +{ + "fb-locale": "pt_BR", + "translations": { + "fJKXmrI8Wv3P5CqV03fP1w==": { + "translations": [ + { + "translation": "Carteira" + } + ] + }, + "4b2jW7VoOq0mSpln/V61BA==": { + "translations": [ + { + "translation": "Enviar" + } + ] + }, + "3Tx5Pa2fR7yHhhtDr3A40Q==": { + "translations": [ + { + "translation": "Opções" + } + ] + } + } +}