diff --git a/package-lock.json b/package-lock.json index 5477fa8b4..df8f29cae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,9 +24,11 @@ "scratch-storage": "2.0.2" }, "devDependencies": { - "@formatjs/intl-locale": "2.4.34", - "@formatjs/intl-pluralrules": "4.1.0", - "@formatjs/intl-relativetimeformat": "8.1.8", + "@formatjs/intl-datetimeformat": "6.4.3", + "@formatjs/intl-locale": "3.0.11", + "@formatjs/intl-numberformat": "8.3.3", + "@formatjs/intl-pluralrules": "5.1.8", + "@formatjs/intl-relativetimeformat": "11.1.8", "async": "3.2.2", "autoprefixer": "10.4.2", "babel-cli": "6.26.0", @@ -83,7 +85,7 @@ "query-string": "5.1.1", "react": "16.14.0", "react-dom": "16.14.0", - "react-intl": "2.9.0", + "react-intl": "5.25.1", "react-modal": "3.11.1", "react-onclickoutside": "6.7.1", "react-plotly.js": "2.4.0", @@ -99,8 +101,8 @@ "regenerator-runtime": "0.13.9", "sass": "1.49.7", "sass-loader": "10.2.1", - "scratch-gui": "1.3.10", - "scratch-l10n": "3.15.20230212032126", + "scratch-gui": "1.3.21", + "scratch-l10n": "3.15.20230227032200", "selenium-webdriver": "4.1.0", "slick-carousel": "1.6.0", "style-loader": "0.12.3", @@ -897,108 +899,340 @@ } }, "node_modules/@formatjs/ecma402-abstract": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.5.tgz", - "integrity": "sha512-cGpEBzrf9bL2lTMEuRZ3gjLrEUEucxAXDIdX4tNqNdNZO81ZN558BfjiFfyPgrhILEuJU/+sgLwWxddSn6usHw==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.14.3.tgz", + "integrity": "sha512-SlsbRC/RX+/zg4AApWIFNDdkLtFbkq3LNoZWXZCE/nHVKqoIJyaoQyge/I0Y38vLxowUn9KTtXgusLD91+orbg==", "dev": true, "dependencies": { - "@formatjs/intl-localematcher": "0.2.18", - "tslib": "^2.1.0" + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" } }, "node_modules/@formatjs/ecma402-abstract/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/@formatjs/fast-memoize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz", + "integrity": "sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/fast-memoize/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz", + "integrity": "sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/icu-skeleton-parser": "1.3.6", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz", + "integrity": "sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "node_modules/@formatjs/intl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.2.1.tgz", + "integrity": "sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/fast-memoize": "1.2.1", + "@formatjs/icu-messageformat-parser": "2.1.0", + "@formatjs/intl-displaynames": "5.4.3", + "@formatjs/intl-listformat": "6.5.3", + "intl-messageformat": "9.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "typescript": "^4.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@formatjs/intl-datetimeformat": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-datetimeformat/-/intl-datetimeformat-6.4.3.tgz", + "integrity": "sha512-+fLPuBHTZZqJJzjfK4cqamW00j8yCtcQekkAVvfSn/2xibJaQvhqrpDs++4/qM847lZtnDU3q33lelM3H5JMbQ==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-datetimeformat/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/@formatjs/intl-displaynames": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-5.4.3.tgz", + "integrity": "sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl-displaynames/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl-displaynames/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl-displaynames/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "dev": true }, "node_modules/@formatjs/intl-getcanonicallocales": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-1.7.1.tgz", - "integrity": "sha512-U+q2TNDn5LZataWFbo1vokRUgLYabUeVaSGietn22wr6ZR2O2gpMKiejoVBiyaWTDJYLckN581fsZYoJw59NMg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-2.0.5.tgz", + "integrity": "sha512-YOk+Fa5gpPq5bdpm8JDAY5bkfCkR+NENZKQbLHeqhm8JchHcclPwZ9FU48gYGg3CW6Wi/cTCOvmOrzsIhlkr0w==", "dev": true, "dependencies": { - "tslib": "^2.1.0" + "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-getcanonicallocales/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/@formatjs/intl-listformat": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.5.3.tgz", + "integrity": "sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl-listformat/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl-listformat/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl-listformat/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "dev": true }, "node_modules/@formatjs/intl-locale": { - "version": "2.4.34", - "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-2.4.34.tgz", - "integrity": "sha512-IsjySVKvQ4w+QbPPX3l5iidE0PorLHdemvf/rIIYcgvDrw2hTaSQEocG7+C86B3wxxQgCIdVnbxYViCPXHG/Fw==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-3.0.11.tgz", + "integrity": "sha512-gLEX9kzebBjIVCkXMMN+VFMUV2aj0vhmrP+nke2muxUSJ3fLs/DJjlkv+s59rAL3nNaGdvphqKLhQsul0mmhAw==", "dev": true, "dependencies": { - "@formatjs/ecma402-abstract": "1.9.5", - "@formatjs/intl-getcanonicallocales": "1.7.1", - "tslib": "^2.1.0" + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-getcanonicallocales": "2.0.5", + "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-locale/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, "node_modules/@formatjs/intl-localematcher": { - "version": "0.2.18", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.18.tgz", - "integrity": "sha512-xI9X+mi7wbucbh35GNTY+C0+oMJXAp8ueC73SOyJlBpRNjLuOlSwgw3yJaCZxy3WpjcRBCP0laJ5zlpITO0QpA==", + "version": "0.2.32", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.32.tgz", + "integrity": "sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ==", "dev": true, "dependencies": { - "tslib": "^2.1.0" + "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-localematcher/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/@formatjs/intl-numberformat": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-numberformat/-/intl-numberformat-8.3.3.tgz", + "integrity": "sha512-11mSFZb5RsCVZMVaHbRcDYNxQ+tsstReL62AJcTCBZdvAZMqECOEsDkJODZ90nf/ClKqp0/KxwVlshxprn22Nw==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-numberformat/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, "node_modules/@formatjs/intl-pluralrules": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-4.1.0.tgz", - "integrity": "sha512-rJFWETXa1OOcru4kqjEz/MUyBxdcMWhbmqKVjDBVZ6HF4ZqkC1TUWQkj+jqIxDiShQ6/J7QLMOGMwiGDjGepHg==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-5.1.8.tgz", + "integrity": "sha512-uevO916EWoeuueqeNzHjnUzpfWZzXFJibC/sEvPR/ZiZH5btWuOLeJLdb1To4nMH8ZJQlmAf8SDpFf+eWvz5lQ==", "dev": true, "dependencies": { - "@formatjs/ecma402-abstract": "1.9.5", - "@formatjs/intl-localematcher": "0.2.18", - "tslib": "^2.1.0" + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-pluralrules/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, "node_modules/@formatjs/intl-relativetimeformat": { - "version": "8.1.8", - "resolved": "https://registry.npmjs.org/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-8.1.8.tgz", - "integrity": "sha512-MIVrsgG7hvYrnes6TxJLflXhhTuxIaWCIdf6p5Iv6HguTtDJqqAFOCNRCqUnYQeYcNbgIQBgLb0Kh7djS0GU+w==", + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-11.1.8.tgz", + "integrity": "sha512-5evaQTfSiSNLXt6GxfPEq2YGtPCH2UKNEoPB0Rg9+3IPSPp5o39Oks91bDZE8SCk5rK2ABlmrc8ZnMILfZhl/Q==", "dev": true, "dependencies": { - "@formatjs/ecma402-abstract": "1.7.1", - "tslib": "^2.1.0" - } - }, - "node_modules/@formatjs/intl-relativetimeformat/node_modules/@formatjs/ecma402-abstract": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.7.1.tgz", - "integrity": "sha512-FjewVLB2DVEVCvvC7IMffzXVhysvi442i6ed0H7qcrT6xtUpO4vr0oZgpOmsv6D9I4Io0GVebIuySwteS/k3gg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" } }, "node_modules/@formatjs/intl-relativetimeformat/node_modules/tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/@formatjs/intl/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@formatjs/intl/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "dev": true }, "node_modules/@gar/promisify": { @@ -1724,6 +1958,25 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/hoist-non-react-statics/node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/@types/js-cookie": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", @@ -1746,6 +1999,29 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", + "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, "node_modules/@types/yauzl": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", @@ -12674,21 +12950,49 @@ "dev": true }, "node_modules/intl-messageformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", - "integrity": "sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz", + "integrity": "sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==", "dev": true, "dependencies": { - "intl-messageformat-parser": "1.4.0" + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/fast-memoize": "1.2.1", + "@formatjs/icu-messageformat-parser": "2.1.0", + "tslib": "^2.1.0" } }, "node_modules/intl-messageformat-parser": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz", - "integrity": "sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU=", + "integrity": "sha512-/XkqFHKezO6UcF4Av2/Lzfrez18R0jyw7kRFhSeB/YRakdrgSc9QfFZUwNJI9swMwMoNPygK1ArC5wdFSjPw+A==", "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", "dev": true }, + "node_modules/intl-messageformat/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/intl-messageformat/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/intl-messageformat/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, "node_modules/intl-relativeformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/intl-relativeformat/-/intl-relativeformat-2.2.0.tgz", @@ -12702,19 +13006,12 @@ "node_modules/intl-relativeformat/node_modules/intl-messageformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", - "integrity": "sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=", + "integrity": "sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw==", "dev": true, "dependencies": { "intl-messageformat-parser": "1.4.0" } }, - "node_modules/intl-relativeformat/node_modules/intl-messageformat-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz", - "integrity": "sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU=", - "deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser", - "dev": true - }, "node_modules/into-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", @@ -20133,34 +20430,49 @@ } }, "node_modules/react-intl": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.9.0.tgz", - "integrity": "sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==", + "version": "5.25.1", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz", + "integrity": "sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==", "dev": true, "dependencies": { - "hoist-non-react-statics": "^3.3.0", - "intl-format-cache": "^2.0.5", - "intl-messageformat": "^2.1.0", - "intl-relativeformat": "^2.1.0", - "invariant": "^2.1.1" + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/icu-messageformat-parser": "2.1.0", + "@formatjs/intl": "2.2.1", + "@formatjs/intl-displaynames": "5.4.3", + "@formatjs/intl-listformat": "6.5.3", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "9.13.0", + "tslib": "^2.1.0" }, "peerDependencies": { - "prop-types": "^15.5.4", - "react": "^0.14.9 || ^15.0.0 || ^16.0.0" + "react": "^16.3.0 || 17 || 18", + "typescript": "^4.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/react-intl-redux": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/react-intl-redux/-/react-intl-redux-0.7.0.tgz", - "integrity": "sha512-T7I7Yy1UkvD8rOB1B+SCG63LYJBtBcvGJ8FVJ8g8Yjhm4+rEhKzJuh1MaQBhwKZNlVcHlx4SlKdtkw8urdZdrA==", + "node_modules/react-intl/node_modules/@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", "dev": true, - "peer": true, "dependencies": { - "prop-types": "^15.6.0" - }, - "peerDependencies": { - "react-intl": "^2.2.2", - "react-redux": "^5.0.1" + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "node_modules/react-intl/node_modules/@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/react-intl/node_modules/hoist-non-react-statics": { @@ -20172,6 +20484,12 @@ "react-is": "^16.7.0" } }, + "node_modules/react-intl/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -23000,39 +23318,21 @@ } }, "node_modules/scratch-blocks": { - "version": "0.1.0-prerelease.20230113103241", - "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230113103241.tgz", - "integrity": "sha512-bQgjkm54gr820GLZ4E9mYlKYTVdDnt5DcA6BOImiFgyBScdKfRnycuh0cMGJnJeQ1JcyVEX1uezre8Wix91mWQ==", + "version": "0.1.0-prerelease.20230227082058", + "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230227082058.tgz", + "integrity": "sha512-D2XElzziBZc6SWOzDgDE2c3kG0EWtSOxhPq5h2drSKsPIxncx1RcK7D5XC23vhgsMiaUQ3NgIFqMQ9RPIJxwKw==", "dev": true, "dependencies": { "exports-loader": "0.7.0", "google-closure-library": "20190301.0.0", "imports-loader": "0.8.0", - "scratch-l10n": "3.15.20230113032113" - } - }, - "node_modules/scratch-blocks/node_modules/scratch-l10n": { - "version": "3.15.20230113032113", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230113032113.tgz", - "integrity": "sha512-q5//oIbED4o3VznMCFnbJH1vEtJwXUgWhEEHqdGGrysl/kp90X/F82YznCpCb042XpZy6FfS1X/YfcGvLRz6bA==", - "dev": true, - "dependencies": { - "@babel/cli": "^7.1.2", - "@babel/core": "^7.1.2", - "@transifex/api": "4.2.5", - "babel-plugin-react-intl": "^3.0.1", - "download": "^8.0.0", - "transifex": "1.6.6" - }, - "bin": { - "build-i18n-src": "scripts/build-i18n-src.js", - "tx-push-src": "scripts/tx-push-src.js" + "scratch-l10n": "3.15.20230227032200" } }, "node_modules/scratch-gui": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.3.10.tgz", - "integrity": "sha512-mtPpJ8PP1M0uuLqA0SU+7hTP21uYm/mK7ixuqNPeaFgLjVTxLm7q9w8PKIetmYeRr6hiQXrqZOQ8YSAPp2NH3A==", + "version": "1.3.21", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.3.21.tgz", + "integrity": "sha512-epUR5vTmTj756LYZyB4zlnOSOPe3UHq9KYBJoeL/MPwBptXnWrBqxT/Wyxl45hPMXzGzvuNPUgWCwaqu+hEIlg==", "dev": true, "dependencies": { "arraybuffer-loader": "^1.0.6", @@ -23083,14 +23383,14 @@ "redux": "3.7.2", "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20221123180128", - "scratch-blocks": "0.1.0-prerelease.20230113103241", - "scratch-l10n": "3.15.20230113032113", + "scratch-blocks": "0.1.0-prerelease.20230227082058", + "scratch-l10n": "3.15.20230223032131", "scratch-paint": "1.1.31", - "scratch-render": "0.1.0-prerelease.20221121051603", + "scratch-render": "0.1.0-prerelease.20230221152523", "scratch-render-fonts": "1.0.0-prerelease.20221102164332", "scratch-storage": "2.0.2", - "scratch-svg-renderer": "0.2.0-prerelease.20221120235613", - "scratch-vm": "1.3.18", + "scratch-svg-renderer": "0.2.0-prerelease.20230224194137", + "scratch-vm": "1.3.61", "startaudiocontext": "1.2.1", "style-loader": "^0.23.0", "text-encoding": "0.7.0", @@ -23219,6 +23519,24 @@ "node": ">=4" } }, + "node_modules/scratch-gui/node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/scratch-gui/node_modules/intl-messageformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", + "integrity": "sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw==", + "dev": true, + "dependencies": { + "intl-messageformat-parser": "1.4.0" + } + }, "node_modules/scratch-gui/node_modules/lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -23322,6 +23640,37 @@ "react": "^16.0.0" } }, + "node_modules/scratch-gui/node_modules/react-intl": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.9.0.tgz", + "integrity": "sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==", + "dev": true, + "dependencies": { + "hoist-non-react-statics": "^3.3.0", + "intl-format-cache": "^2.0.5", + "intl-messageformat": "^2.1.0", + "intl-relativeformat": "^2.1.0", + "invariant": "^2.1.1" + }, + "peerDependencies": { + "prop-types": "^15.5.4", + "react": "^0.14.9 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/scratch-gui/node_modules/react-intl-redux": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/react-intl-redux/-/react-intl-redux-0.7.0.tgz", + "integrity": "sha512-T7I7Yy1UkvD8rOB1B+SCG63LYJBtBcvGJ8FVJ8g8Yjhm4+rEhKzJuh1MaQBhwKZNlVcHlx4SlKdtkw8urdZdrA==", + "dev": true, + "peer": true, + "dependencies": { + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react-intl": "^2.2.2", + "react-redux": "^5.0.1" + } + }, "node_modules/scratch-gui/node_modules/react-modal": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.9.1.tgz", @@ -23368,9 +23717,9 @@ } }, "node_modules/scratch-gui/node_modules/scratch-l10n": { - "version": "3.15.20230113032113", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230113032113.tgz", - "integrity": "sha512-q5//oIbED4o3VznMCFnbJH1vEtJwXUgWhEEHqdGGrysl/kp90X/F82YznCpCb042XpZy6FfS1X/YfcGvLRz6bA==", + "version": "3.15.20230223032131", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230223032131.tgz", + "integrity": "sha512-VTUStiRe0cad8TqnL2MfuRXbexQHWmTpEwiMDH+i+2mTWsLSm2k6tM7yS1VyOTmaE0BIsJA3IUHgPj4XybN1Iw==", "dev": true, "dependencies": { "@babel/cli": "^7.1.2", @@ -23420,6 +23769,23 @@ "integrity": "sha512-DTt3GhOUDKhh4ONwIJW4lmhyotQmV2LjNlGK/J2hkwUcqcbKkCLAdJPtxQnxnlc7SR3f1CEXCyMmc7WLUsWbNA==", "dev": true }, + "node_modules/scratch-gui/node_modules/scratch-svg-renderer": { + "version": "0.2.0-prerelease.20230224194137", + "resolved": "https://registry.npmjs.org/scratch-svg-renderer/-/scratch-svg-renderer-0.2.0-prerelease.20230224194137.tgz", + "integrity": "sha512-NhsWkc0ci5R7ZH9Z7j6crI69Oe9XtNlp4u+Q6bOoLicGHJBnNeDeD2/w2ySxiYnnhJI9KioByvAoOwxZnEA+0Q==", + "dev": true, + "dependencies": { + "base64-js": "1.2.1", + "base64-loader": "1.0.0", + "dompurify": "2.2.7", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "minilog": "3.1.0", + "transformation-matrix": "1.15.0" + }, + "peerDependencies": { + "scratch-render-fonts": "^1.0.0-prerelease" + } + }, "node_modules/scratch-gui/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -23467,9 +23833,9 @@ } }, "node_modules/scratch-l10n": { - "version": "3.15.20230212032126", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230212032126.tgz", - "integrity": "sha512-EOaa47NpTo8C+PnfAGplB09jklEZ6j09ANFdnINEapkKp/qVOlZpw/JchjOPy4omNaJ0RQMYFc7Z3XCDqSyMHg==", + "version": "3.15.20230227032200", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230227032200.tgz", + "integrity": "sha512-6Y8MVsySw9/z4j5WM8bOiyAKMl4ghPt9lEbAZv0XGwDRr1Ab+XcByZBlWcYUlUHfNvCXVvgm9b36LZvKtwDanw==", "dev": true, "dependencies": { "@babel/cli": "^7.1.2", @@ -23508,9 +23874,9 @@ } }, "node_modules/scratch-render": { - "version": "0.1.0-prerelease.20221121051603", - "resolved": "https://registry.npmjs.org/scratch-render/-/scratch-render-0.1.0-prerelease.20221121051603.tgz", - "integrity": "sha512-+PmRxh3Ms5+ichCinmg9Nl7jYwYZvGrlOGNLwxGZSYv+Ve96RqMPJAdpyv0ctOzELoYnMalFGZwUWmdMAJLE5Q==", + "version": "0.1.0-prerelease.20230221152523", + "resolved": "https://registry.npmjs.org/scratch-render/-/scratch-render-0.1.0-prerelease.20230221152523.tgz", + "integrity": "sha512-h8BStWgU0uguli98sTlvY2vdTM9LAhyo5M24iVATwoijNhGFfwaR3acpolgGuDMV3GaJILCl6kuMei0CCbC7bw==", "dev": true, "dependencies": { "grapheme-breaker": "0.3.2", @@ -23667,9 +24033,9 @@ "dev": true }, "node_modules/scratch-vm": { - "version": "1.3.18", - "resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.3.18.tgz", - "integrity": "sha512-qL/WYZqsvVPc2vXTjdQOxXfuXwm5eY9989yC2jw1JWYvU6WkOr2oCbu0BHaY9FLP2A0XYJ+i8CEPju+zeay2RA==", + "version": "1.3.61", + "resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.3.61.tgz", + "integrity": "sha512-afmy2jm3Lb7qg0vsVAA/B8uwpCcrfapfrlMjTs1twpVEVRPO12MEtXayPX64ZmvyxkaNTBL4IOxkVpbLpTPRMg==", "dev": true, "dependencies": { "@vernier/godirect": "1.5.0", @@ -27581,6 +27947,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tap/node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/tap/node_modules/unicode-length": { "version": "2.0.2", "dev": true, @@ -29065,10 +29444,11 @@ } }, "node_modules/typescript": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -32356,118 +32736,358 @@ } }, "@formatjs/ecma402-abstract": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.5.tgz", - "integrity": "sha512-cGpEBzrf9bL2lTMEuRZ3gjLrEUEucxAXDIdX4tNqNdNZO81ZN558BfjiFfyPgrhILEuJU/+sgLwWxddSn6usHw==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.14.3.tgz", + "integrity": "sha512-SlsbRC/RX+/zg4AApWIFNDdkLtFbkq3LNoZWXZCE/nHVKqoIJyaoQyge/I0Y38vLxowUn9KTtXgusLD91+orbg==", "dev": true, "requires": { - "@formatjs/intl-localematcher": "0.2.18", - "tslib": "^2.1.0" + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" }, "dependencies": { "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true } } }, - "@formatjs/intl-getcanonicallocales": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-1.7.1.tgz", - "integrity": "sha512-U+q2TNDn5LZataWFbo1vokRUgLYabUeVaSGietn22wr6ZR2O2gpMKiejoVBiyaWTDJYLckN581fsZYoJw59NMg==", + "@formatjs/fast-memoize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz", + "integrity": "sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==", "dev": true, "requires": { "tslib": "^2.1.0" }, "dependencies": { "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "dev": true } } }, - "@formatjs/intl-locale": { - "version": "2.4.34", - "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-2.4.34.tgz", - "integrity": "sha512-IsjySVKvQ4w+QbPPX3l5iidE0PorLHdemvf/rIIYcgvDrw2hTaSQEocG7+C86B3wxxQgCIdVnbxYViCPXHG/Fw==", + "@formatjs/icu-messageformat-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz", + "integrity": "sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==", "dev": true, "requires": { - "@formatjs/ecma402-abstract": "1.9.5", - "@formatjs/intl-getcanonicallocales": "1.7.1", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "@formatjs/intl-localematcher": { - "version": "0.2.18", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.18.tgz", - "integrity": "sha512-xI9X+mi7wbucbh35GNTY+C0+oMJXAp8ueC73SOyJlBpRNjLuOlSwgw3yJaCZxy3WpjcRBCP0laJ5zlpITO0QpA==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "dev": true - } - } - }, - "@formatjs/intl-pluralrules": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-4.1.0.tgz", - "integrity": "sha512-rJFWETXa1OOcru4kqjEz/MUyBxdcMWhbmqKVjDBVZ6HF4ZqkC1TUWQkj+jqIxDiShQ6/J7QLMOGMwiGDjGepHg==", - "dev": true, - "requires": { - "@formatjs/ecma402-abstract": "1.9.5", - "@formatjs/intl-localematcher": "0.2.18", - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "@formatjs/intl-relativetimeformat": { - "version": "8.1.8", - "resolved": "https://registry.npmjs.org/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-8.1.8.tgz", - "integrity": "sha512-MIVrsgG7hvYrnes6TxJLflXhhTuxIaWCIdf6p5Iv6HguTtDJqqAFOCNRCqUnYQeYcNbgIQBgLb0Kh7djS0GU+w==", - "dev": true, - "requires": { - "@formatjs/ecma402-abstract": "1.7.1", + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/icu-skeleton-parser": "1.3.6", "tslib": "^2.1.0" }, "dependencies": { "@formatjs/ecma402-abstract": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.7.1.tgz", - "integrity": "sha512-FjewVLB2DVEVCvvC7IMffzXVhysvi442i6ed0H7qcrT6xtUpO4vr0oZgpOmsv6D9I4Io0GVebIuySwteS/k3gg==", + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", "dev": true, "requires": { "tslib": "^2.1.0" } }, "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + } + } + }, + "@formatjs/icu-skeleton-parser": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz", + "integrity": "sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.11.4", + "tslib": "^2.1.0" + }, + "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + } + } + }, + "@formatjs/intl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.2.1.tgz", + "integrity": "sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/fast-memoize": "1.2.1", + "@formatjs/icu-messageformat-parser": "2.1.0", + "@formatjs/intl-displaynames": "5.4.3", + "@formatjs/intl-listformat": "6.5.3", + "intl-messageformat": "9.13.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + } + } + }, + "@formatjs/intl-datetimeformat": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-datetimeformat/-/intl-datetimeformat-6.4.3.tgz", + "integrity": "sha512-+fLPuBHTZZqJJzjfK4cqamW00j8yCtcQekkAVvfSn/2xibJaQvhqrpDs++4/qM847lZtnDU3q33lelM3H5JMbQ==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + } + } + }, + "@formatjs/intl-displaynames": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-5.4.3.tgz", + "integrity": "sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + }, + "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + } + } + }, + "@formatjs/intl-getcanonicallocales": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-2.0.5.tgz", + "integrity": "sha512-YOk+Fa5gpPq5bdpm8JDAY5bkfCkR+NENZKQbLHeqhm8JchHcclPwZ9FU48gYGg3CW6Wi/cTCOvmOrzsIhlkr0w==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + } + } + }, + "@formatjs/intl-listformat": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.5.3.tgz", + "integrity": "sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + }, + "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + } + } + }, + "@formatjs/intl-locale": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@formatjs/intl-locale/-/intl-locale-3.0.11.tgz", + "integrity": "sha512-gLEX9kzebBjIVCkXMMN+VFMUV2aj0vhmrP+nke2muxUSJ3fLs/DJjlkv+s59rAL3nNaGdvphqKLhQsul0mmhAw==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-getcanonicallocales": "2.0.5", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + } + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.32", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.32.tgz", + "integrity": "sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + } + } + }, + "@formatjs/intl-numberformat": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@formatjs/intl-numberformat/-/intl-numberformat-8.3.3.tgz", + "integrity": "sha512-11mSFZb5RsCVZMVaHbRcDYNxQ+tsstReL62AJcTCBZdvAZMqECOEsDkJODZ90nf/ClKqp0/KxwVlshxprn22Nw==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + } + } + }, + "@formatjs/intl-pluralrules": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@formatjs/intl-pluralrules/-/intl-pluralrules-5.1.8.tgz", + "integrity": "sha512-uevO916EWoeuueqeNzHjnUzpfWZzXFJibC/sEvPR/ZiZH5btWuOLeJLdb1To4nMH8ZJQlmAf8SDpFf+eWvz5lQ==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + } + } + }, + "@formatjs/intl-relativetimeformat": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-11.1.8.tgz", + "integrity": "sha512-5evaQTfSiSNLXt6GxfPEq2YGtPCH2UKNEoPB0Rg9+3IPSPp5o39Oks91bDZE8SCk5rK2ABlmrc8ZnMILfZhl/Q==", + "dev": true, + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true } } @@ -33040,6 +33660,27 @@ "@babel/types": "^7.3.0" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "requires": { + "react-is": "^16.7.0" + } + } + } + }, "@types/js-cookie": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", @@ -33062,6 +33703,29 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "@types/react": { + "version": "18.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", + "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, "@types/yauzl": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", @@ -42385,18 +43049,48 @@ "dev": true }, "intl-messageformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", - "integrity": "sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz", + "integrity": "sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==", "dev": true, "requires": { - "intl-messageformat-parser": "1.4.0" + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/fast-memoize": "1.2.1", + "@formatjs/icu-messageformat-parser": "2.1.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + } } }, "intl-messageformat-parser": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz", - "integrity": "sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU=", + "integrity": "sha512-/XkqFHKezO6UcF4Av2/Lzfrez18R0jyw7kRFhSeB/YRakdrgSc9QfFZUwNJI9swMwMoNPygK1ArC5wdFSjPw+A==", "dev": true }, "intl-relativeformat": { @@ -42411,17 +43105,11 @@ "intl-messageformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", - "integrity": "sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw=", + "integrity": "sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw==", "dev": true, "requires": { "intl-messageformat-parser": "1.4.0" } - }, - "intl-messageformat-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz", - "integrity": "sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU=", - "dev": true } } }, @@ -48650,18 +49338,42 @@ } }, "react-intl": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.9.0.tgz", - "integrity": "sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==", + "version": "5.25.1", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz", + "integrity": "sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==", "dev": true, "requires": { - "hoist-non-react-statics": "^3.3.0", - "intl-format-cache": "^2.0.5", - "intl-messageformat": "^2.1.0", - "intl-relativeformat": "^2.1.0", - "invariant": "^2.1.1" + "@formatjs/ecma402-abstract": "1.11.4", + "@formatjs/icu-messageformat-parser": "2.1.0", + "@formatjs/intl": "2.2.1", + "@formatjs/intl-displaynames": "5.4.3", + "@formatjs/intl-listformat": "6.5.3", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react": "16 || 17 || 18", + "hoist-non-react-statics": "^3.3.2", + "intl-messageformat": "9.13.0", + "tslib": "^2.1.0" }, "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz", + "integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==", + "dev": true, + "requires": { + "@formatjs/intl-localematcher": "0.2.25", + "tslib": "^2.1.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz", + "integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -48670,19 +49382,15 @@ "requires": { "react-is": "^16.7.0" } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true } } }, - "react-intl-redux": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/react-intl-redux/-/react-intl-redux-0.7.0.tgz", - "integrity": "sha512-T7I7Yy1UkvD8rOB1B+SCG63LYJBtBcvGJ8FVJ8g8Yjhm4+rEhKzJuh1MaQBhwKZNlVcHlx4SlKdtkw8urdZdrA==", - "dev": true, - "peer": true, - "requires": { - "prop-types": "^15.6.0" - } - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -50983,37 +51691,21 @@ } }, "scratch-blocks": { - "version": "0.1.0-prerelease.20230113103241", - "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230113103241.tgz", - "integrity": "sha512-bQgjkm54gr820GLZ4E9mYlKYTVdDnt5DcA6BOImiFgyBScdKfRnycuh0cMGJnJeQ1JcyVEX1uezre8Wix91mWQ==", + "version": "0.1.0-prerelease.20230227082058", + "resolved": "https://registry.npmjs.org/scratch-blocks/-/scratch-blocks-0.1.0-prerelease.20230227082058.tgz", + "integrity": "sha512-D2XElzziBZc6SWOzDgDE2c3kG0EWtSOxhPq5h2drSKsPIxncx1RcK7D5XC23vhgsMiaUQ3NgIFqMQ9RPIJxwKw==", "dev": true, "requires": { "exports-loader": "0.7.0", "google-closure-library": "20190301.0.0", "imports-loader": "0.8.0", - "scratch-l10n": "3.15.20230113032113" - }, - "dependencies": { - "scratch-l10n": { - "version": "3.15.20230113032113", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230113032113.tgz", - "integrity": "sha512-q5//oIbED4o3VznMCFnbJH1vEtJwXUgWhEEHqdGGrysl/kp90X/F82YznCpCb042XpZy6FfS1X/YfcGvLRz6bA==", - "dev": true, - "requires": { - "@babel/cli": "^7.1.2", - "@babel/core": "^7.1.2", - "@transifex/api": "4.2.5", - "babel-plugin-react-intl": "^3.0.1", - "download": "^8.0.0", - "transifex": "1.6.6" - } - } + "scratch-l10n": "3.15.20230227032200" } }, "scratch-gui": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.3.10.tgz", - "integrity": "sha512-mtPpJ8PP1M0uuLqA0SU+7hTP21uYm/mK7ixuqNPeaFgLjVTxLm7q9w8PKIetmYeRr6hiQXrqZOQ8YSAPp2NH3A==", + "version": "1.3.21", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-1.3.21.tgz", + "integrity": "sha512-epUR5vTmTj756LYZyB4zlnOSOPe3UHq9KYBJoeL/MPwBptXnWrBqxT/Wyxl45hPMXzGzvuNPUgWCwaqu+hEIlg==", "dev": true, "requires": { "arraybuffer-loader": "^1.0.6", @@ -51064,14 +51756,14 @@ "redux": "3.7.2", "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20221123180128", - "scratch-blocks": "0.1.0-prerelease.20230113103241", - "scratch-l10n": "3.15.20230113032113", + "scratch-blocks": "0.1.0-prerelease.20230227082058", + "scratch-l10n": "3.15.20230223032131", "scratch-paint": "1.1.31", - "scratch-render": "0.1.0-prerelease.20221121051603", + "scratch-render": "0.1.0-prerelease.20230221152523", "scratch-render-fonts": "1.0.0-prerelease.20221102164332", "scratch-storage": "2.0.2", - "scratch-svg-renderer": "0.2.0-prerelease.20221120235613", - "scratch-vm": "1.3.18", + "scratch-svg-renderer": "0.2.0-prerelease.20230224194137", + "scratch-vm": "1.3.61", "startaudiocontext": "1.2.1", "style-loader": "^0.23.0", "text-encoding": "0.7.0", @@ -51172,6 +51864,24 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "requires": { + "react-is": "^16.7.0" + } + }, + "intl-messageformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz", + "integrity": "sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw==", + "dev": true, + "requires": { + "intl-messageformat-parser": "1.4.0" + } + }, "lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -51259,6 +51969,29 @@ "prop-types": "^15.6.0" } }, + "react-intl": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.9.0.tgz", + "integrity": "sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==", + "dev": true, + "requires": { + "hoist-non-react-statics": "^3.3.0", + "intl-format-cache": "^2.0.5", + "intl-messageformat": "^2.1.0", + "intl-relativeformat": "^2.1.0", + "invariant": "^2.1.1" + } + }, + "react-intl-redux": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/react-intl-redux/-/react-intl-redux-0.7.0.tgz", + "integrity": "sha512-T7I7Yy1UkvD8rOB1B+SCG63LYJBtBcvGJ8FVJ8g8Yjhm4+rEhKzJuh1MaQBhwKZNlVcHlx4SlKdtkw8urdZdrA==", + "dev": true, + "peer": true, + "requires": { + "prop-types": "^15.6.0" + } + }, "react-modal": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.9.1.tgz", @@ -51295,9 +52028,9 @@ } }, "scratch-l10n": { - "version": "3.15.20230113032113", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230113032113.tgz", - "integrity": "sha512-q5//oIbED4o3VznMCFnbJH1vEtJwXUgWhEEHqdGGrysl/kp90X/F82YznCpCb042XpZy6FfS1X/YfcGvLRz6bA==", + "version": "3.15.20230223032131", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230223032131.tgz", + "integrity": "sha512-VTUStiRe0cad8TqnL2MfuRXbexQHWmTpEwiMDH+i+2mTWsLSm2k6tM7yS1VyOTmaE0BIsJA3IUHgPj4XybN1Iw==", "dev": true, "requires": { "@babel/cli": "^7.1.2", @@ -51332,6 +52065,20 @@ } } }, + "scratch-svg-renderer": { + "version": "0.2.0-prerelease.20230224194137", + "resolved": "https://registry.npmjs.org/scratch-svg-renderer/-/scratch-svg-renderer-0.2.0-prerelease.20230224194137.tgz", + "integrity": "sha512-NhsWkc0ci5R7ZH9Z7j6crI69Oe9XtNlp4u+Q6bOoLicGHJBnNeDeD2/w2ySxiYnnhJI9KioByvAoOwxZnEA+0Q==", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "base64-loader": "1.0.0", + "dompurify": "2.2.7", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "minilog": "3.1.0", + "transformation-matrix": "1.15.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -51372,9 +52119,9 @@ } }, "scratch-l10n": { - "version": "3.15.20230212032126", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230212032126.tgz", - "integrity": "sha512-EOaa47NpTo8C+PnfAGplB09jklEZ6j09ANFdnINEapkKp/qVOlZpw/JchjOPy4omNaJ0RQMYFc7Z3XCDqSyMHg==", + "version": "3.15.20230227032200", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230227032200.tgz", + "integrity": "sha512-6Y8MVsySw9/z4j5WM8bOiyAKMl4ghPt9lEbAZv0XGwDRr1Ab+XcByZBlWcYUlUHfNvCXVvgm9b36LZvKtwDanw==", "dev": true, "requires": { "@babel/cli": "^7.1.2", @@ -51408,9 +52155,9 @@ } }, "scratch-render": { - "version": "0.1.0-prerelease.20221121051603", - "resolved": "https://registry.npmjs.org/scratch-render/-/scratch-render-0.1.0-prerelease.20221121051603.tgz", - "integrity": "sha512-+PmRxh3Ms5+ichCinmg9Nl7jYwYZvGrlOGNLwxGZSYv+Ve96RqMPJAdpyv0ctOzELoYnMalFGZwUWmdMAJLE5Q==", + "version": "0.1.0-prerelease.20230221152523", + "resolved": "https://registry.npmjs.org/scratch-render/-/scratch-render-0.1.0-prerelease.20230221152523.tgz", + "integrity": "sha512-h8BStWgU0uguli98sTlvY2vdTM9LAhyo5M24iVATwoijNhGFfwaR3acpolgGuDMV3GaJILCl6kuMei0CCbC7bw==", "dev": true, "requires": { "grapheme-breaker": "0.3.2", @@ -51569,9 +52316,9 @@ "dev": true }, "scratch-vm": { - "version": "1.3.18", - "resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.3.18.tgz", - "integrity": "sha512-qL/WYZqsvVPc2vXTjdQOxXfuXwm5eY9989yC2jw1JWYvU6WkOr2oCbu0BHaY9FLP2A0XYJ+i8CEPju+zeay2RA==", + "version": "1.3.61", + "resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.3.61.tgz", + "integrity": "sha512-afmy2jm3Lb7qg0vsVAA/B8uwpCcrfapfrlMjTs1twpVEVRPO12MEtXayPX64ZmvyxkaNTBL4IOxkVpbLpTPRMg==", "dev": true, "requires": { "@vernier/godirect": "1.5.0", @@ -54506,6 +55253,12 @@ "bundled": true, "dev": true }, + "typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true + }, "unicode-length": { "version": "2.0.2", "bundled": true, @@ -55770,10 +56523,11 @@ } }, "typescript": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", - "dev": true + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "peer": true }, "ua-parser-js": { "version": "0.7.28", diff --git a/package.json b/package.json index b334018e0..8de3a5aa2 100644 --- a/package.json +++ b/package.json @@ -59,9 +59,11 @@ "scratch-storage": "2.0.2" }, "devDependencies": { - "@formatjs/intl-locale": "2.4.34", - "@formatjs/intl-pluralrules": "4.1.0", - "@formatjs/intl-relativetimeformat": "8.1.8", + "@formatjs/intl-datetimeformat": "6.4.3", + "@formatjs/intl-locale": "3.0.11", + "@formatjs/intl-numberformat": "8.3.3", + "@formatjs/intl-pluralrules": "5.1.8", + "@formatjs/intl-relativetimeformat": "11.1.8", "async": "3.2.2", "autoprefixer": "10.4.2", "babel-cli": "6.26.0", @@ -118,7 +120,7 @@ "query-string": "5.1.1", "react": "16.14.0", "react-dom": "16.14.0", - "react-intl": "2.9.0", + "react-intl": "5.25.1", "react-modal": "3.11.1", "react-onclickoutside": "6.7.1", "react-plotly.js": "2.4.0", @@ -134,8 +136,8 @@ "regenerator-runtime": "0.13.9", "sass": "1.49.7", "sass-loader": "10.2.1", - "scratch-gui": "1.3.10", - "scratch-l10n": "3.15.20230212032126", + "scratch-gui": "1.3.21", + "scratch-l10n": "3.15.20230227032200", "selenium-webdriver": "4.1.0", "slick-carousel": "1.6.0", "style-loader": "0.12.3", diff --git a/src/components/comment/comment.jsx b/src/components/comment/comment.jsx index 5edaeb51d..5816a9179 100644 --- a/src/components/comment/comment.jsx +++ b/src/components/comment/comment.jsx @@ -1,5 +1,4 @@ const classNames = require('classnames'); -const FormattedRelative = require('react-intl').FormattedRelative; const PropTypes = require('prop-types'); const React = require('react'); @@ -13,21 +12,12 @@ const CommentText = props => ( className="mod-comment" text={props.comment} /> - {typeof props.datetimeCreated === 'undefined' ? [] : [ -

- -

- ]} ); CommentText.propTypes = { className: PropTypes.string, - comment: PropTypes.string.isRequired, - datetimeCreated: PropTypes.string + comment: PropTypes.string.isRequired }; module.exports = CommentText; diff --git a/src/components/comment/comment.scss b/src/components/comment/comment.scss index c9499ea39..765436a32 100644 --- a/src/components/comment/comment.scss +++ b/src/components/comment/comment.scss @@ -35,9 +35,3 @@ margin: 0; overflow: hidden; } - -.comment-text-timestamp { - margin: 1rem 0 0; - color: $ui-dark-gray; - font-size: .8rem; -} diff --git a/src/components/footer/conference/2017/footer.jsx b/src/components/footer/conference/2017/footer.jsx index a75e2ca44..9b50ceaa2 100644 --- a/src/components/footer/conference/2017/footer.jsx +++ b/src/components/footer/conference/2017/footer.jsx @@ -1,15 +1,14 @@ -const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const FlexRow = require('../../../flex-row/flex-row.jsx'); const FooterBox = require('../../container/footer.jsx'); const LanguageChooser = require('../../../languagechooser/languagechooser.jsx'); +const {getLocale} = require('../../../../lib/locales.js'); require('../footer.scss'); -const ConferenceFooter = props => ( +const ConferenceFooter = () => (
@@ -86,12 +85,8 @@ const ConferenceFooter = props => (
- +
); -ConferenceFooter.propTypes = { - intl: intlShape -}; - -module.exports = injectIntl(ConferenceFooter); +module.exports = ConferenceFooter; diff --git a/src/components/footer/conference/2018/footer.jsx b/src/components/footer/conference/2018/footer.jsx index 5cef2bde2..0a8f72aae 100644 --- a/src/components/footer/conference/2018/footer.jsx +++ b/src/components/footer/conference/2018/footer.jsx @@ -1,15 +1,14 @@ const FormattedMessage = require('react-intl').FormattedMessage; -const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const FlexRow = require('../../../flex-row/flex-row.jsx'); const FooterBox = require('../../container/footer.jsx'); const LanguageChooser = require('../../../languagechooser/languagechooser.jsx'); +const {getLocale} = require('../../../../lib/locales.js'); require('../footer.scss'); -const ConferenceFooter = props => ( +const ConferenceFooter = () => (

Sponsors

@@ -213,12 +212,8 @@ const ConferenceFooter = props => (
- +
); -ConferenceFooter.propTypes = { - intl: intlShape -}; - -module.exports = injectIntl(ConferenceFooter); +module.exports = ConferenceFooter; diff --git a/src/components/footer/conference/2019/footer.jsx b/src/components/footer/conference/2019/footer.jsx index ab27b268f..63c3a105f 100644 --- a/src/components/footer/conference/2019/footer.jsx +++ b/src/components/footer/conference/2019/footer.jsx @@ -1,15 +1,14 @@ -const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const FlexRow = require('../../../flex-row/flex-row.jsx'); const FooterBox = require('../../container/footer.jsx'); const LanguageChooser = require('../../../languagechooser/languagechooser.jsx'); +const {getLocale} = require('../../../../lib/locales'); require('../footer.scss'); -const ConferenceFooter = props => ( +const ConferenceFooter = () => (
@@ -107,12 +106,8 @@ const ConferenceFooter = props => (
- +
); -ConferenceFooter.propTypes = { - intl: intlShape -}; - -module.exports = injectIntl(ConferenceFooter); +module.exports = ConferenceFooter; diff --git a/src/components/footer/conference/2021/footer.jsx b/src/components/footer/conference/2021/footer.jsx index d1431c9f2..53baa5607 100644 --- a/src/components/footer/conference/2021/footer.jsx +++ b/src/components/footer/conference/2021/footer.jsx @@ -1,13 +1,11 @@ const FormattedMessage = require('react-intl').FormattedMessage; -const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const PropTypes = require('prop-types'); - const FlexRow = require('../../../flex-row/flex-row.jsx'); const FooterBox = require('../../container/footer.jsx'); const LanguageChooser = require('../../../languagechooser/languagechooser.jsx'); +const {getLocale} = require('../../../../lib/locales.js'); require('../footer.scss'); @@ -146,7 +144,7 @@ const ConferenceFooter = props => ( - +
@@ -154,8 +152,7 @@ const ConferenceFooter = props => ( ); ConferenceFooter.propTypes = { - intl: intlShape, organizedByMsgId: PropTypes.string }; -module.exports = injectIntl(ConferenceFooter); +module.exports = ConferenceFooter; diff --git a/src/components/footer/www/footer.jsx b/src/components/footer/www/footer.jsx index 1a07d1aaf..93e7c1bae 100644 --- a/src/components/footer/www/footer.jsx +++ b/src/components/footer/www/footer.jsx @@ -1,6 +1,5 @@ const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const MediaQuery = require('react-responsive').default; const connect = require('react-redux').connect; const PropTypes = require('prop-types'); @@ -10,6 +9,8 @@ const FooterBox = require('../container/footer.jsx'); const LanguageChooser = require('../../languagechooser/languagechooser.jsx'); const frameless = require('../../../lib/frameless'); +const intlShape = require('../../../lib/intl-shape'); +const {getLocale} = require('../../../lib/locales.js'); const getScratchWikiLink = require('../../../lib/scratch-wiki'); require('./footer.scss'); @@ -213,12 +214,12 @@ const Footer = props => ( - + ); Footer.propTypes = { - intl: intlShape.isRequired, + intl: intlShape.isRequired, // eslint-disable-line react/no-unused-prop-types scratchWikiLink: PropTypes.string }; diff --git a/src/components/forms/phone-input.jsx b/src/components/forms/phone-input.jsx index 4684da2bc..ce3cecd0d 100644 --- a/src/components/forms/phone-input.jsx +++ b/src/components/forms/phone-input.jsx @@ -8,10 +8,10 @@ const ReactPhoneInput = require('react-telephone-input/lib/withStyles').default; const Row = require('formsy-react-components').Row; const Help = require('formsy-react-components/release/components/help').default; const ErrorMessages = require('formsy-react-components/release/components/error-messages').default; +const intl = require('react-intl'); const defaultValidationHOC = require('./validations.jsx').defaultValidationHOC; const inputHOC = require('./input-hoc.jsx'); -const intl = require('../../lib/intl.jsx'); const validationHOCFactory = require('./validations.jsx').validationHOCFactory; require('./row.scss'); diff --git a/src/components/forms/validations.jsx b/src/components/forms/validations.jsx index b8b86a27f..310e5757c 100644 --- a/src/components/forms/validations.jsx +++ b/src/components/forms/validations.jsx @@ -1,5 +1,5 @@ const defaults = require('lodash.defaultsdeep'); -const intl = require('../../lib/intl.jsx'); +const intl = require('react-intl'); const omit = require('lodash.omit'); const PropTypes = require('prop-types'); const React = require('react'); diff --git a/src/components/helpwidget/helpwidget.jsx b/src/components/helpwidget/helpwidget.jsx index 0eb6ea1ca..992a2e07c 100644 --- a/src/components/helpwidget/helpwidget.jsx +++ b/src/components/helpwidget/helpwidget.jsx @@ -1,13 +1,14 @@ const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const bindAll = require('lodash.bindall'); const connect = require('react-redux').connect; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../lib/intl-shape'); const Button = require('../forms/button.jsx'); const Spinner = require('../spinner/spinner.jsx'); + require('./helpwidget.scss'); // map Scratch locale to supported Freshdesk locale diff --git a/src/components/join-flow/birthdate-step.jsx b/src/components/join-flow/birthdate-step.jsx index 6b6a7209f..7a86f4c42 100644 --- a/src/components/join-flow/birthdate-step.jsx +++ b/src/components/join-flow/birthdate-step.jsx @@ -3,9 +3,10 @@ const classNames = require('classnames'); const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); const FormattedMessage = require('react-intl').FormattedMessage; +const intlShape = require('../../lib/intl-shape'); const FormikSelect = require('../../components/formik-forms/formik-select.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); const InfoButton = require('../info-button/info-button.jsx'); diff --git a/src/components/join-flow/country-step.jsx b/src/components/join-flow/country-step.jsx index 625717c0e..cc9df59c1 100644 --- a/src/components/join-flow/country-step.jsx +++ b/src/components/join-flow/country-step.jsx @@ -3,9 +3,10 @@ const classNames = require('classnames'); const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); const countryData = require('../../lib/country-data'); +const intlShape = require('../../lib/intl-shape'); const FormikSelect = require('../../components/formik-forms/formik-select.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); const FormikCheckbox = require('../../components/formik-forms/formik-checkbox.jsx'); diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 448f3919c..8d7797f74 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -3,14 +3,16 @@ const classNames = require('classnames'); const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); const FormattedMessage = require('react-intl').FormattedMessage; +const intlShape = require('../../lib/intl-shape'); const validate = require('../../lib/validate'); const JoinFlowStep = require('./join-flow-step.jsx'); const FormikInput = require('../../components/formik-forms/formik-input.jsx'); const InfoButton = require('../info-button/info-button.jsx'); const Captcha = require('../../components/captcha/captcha.jsx'); + require('./join-flow-steps.scss'); class EmailStep extends React.Component { diff --git a/src/components/join-flow/gender-step.jsx b/src/components/join-flow/gender-step.jsx index 30089899d..3c3d35646 100644 --- a/src/components/join-flow/gender-step.jsx +++ b/src/components/join-flow/gender-step.jsx @@ -3,9 +3,10 @@ const classNames = require('classnames'); const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); const FormattedMessage = require('react-intl').FormattedMessage; +const intlShape = require('../../lib/intl-shape'); const FormikRadioButton = require('../../components/formik-forms/formik-radio-button.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); const InfoButton = require('../info-button/info-button.jsx'); diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index f065e730d..0acf3984e 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -3,10 +3,10 @@ const connect = require('react-redux').connect; const defaults = require('lodash.defaultsdeep'); const PropTypes = require('prop-types'); const React = require('react'); +const injectIntl = require('react-intl').injectIntl; const api = require('../../lib/api'); -const injectIntl = require('../../lib/intl.jsx').injectIntl; -const intlShape = require('../../lib/intl.jsx').intlShape; +const intlShape = require('../../lib/intl-shape'); const sessionActions = require('../../redux/session.js'); const validate = require('../../lib/validate'); diff --git a/src/components/join-flow/next-step-button.jsx b/src/components/join-flow/next-step-button.jsx index 04b30ac43..6e6c4cd61 100644 --- a/src/components/join-flow/next-step-button.jsx +++ b/src/components/join-flow/next-step-button.jsx @@ -3,7 +3,7 @@ const React = require('react'); const PropTypes = require('prop-types'); const injectIntl = require('react-intl').injectIntl; -const intl = require('../../lib/intl.jsx'); +const intlShape = require('../../lib/intl-shape'); const Spinner = require('../../components/spinner/spinner.jsx'); const ModalTitle = require('../modal/base/modal-title.jsx'); @@ -29,7 +29,7 @@ const NextStepButton = props => ( NextStepButton.propTypes = { content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), - intl: intl.intlShape, + intl: intlShape, waiting: PropTypes.bool }; diff --git a/src/components/join-flow/registration-error-step.jsx b/src/components/join-flow/registration-error-step.jsx index a7151840d..bda20953f 100644 --- a/src/components/join-flow/registration-error-step.jsx +++ b/src/components/join-flow/registration-error-step.jsx @@ -2,8 +2,9 @@ const bindAll = require('lodash.bindall'); const React = require('react'); const PropTypes = require('prop-types'); const FormattedMessage = require('react-intl').FormattedMessage; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); +const intlShape = require('../../lib/intl-shape'); const JoinFlowStep = require('./join-flow-step.jsx'); require('./join-flow-steps.scss'); diff --git a/src/components/join-flow/username-step.jsx b/src/components/join-flow/username-step.jsx index 15cf1b7ac..dc9da0f9a 100644 --- a/src/components/join-flow/username-step.jsx +++ b/src/components/join-flow/username-step.jsx @@ -3,8 +3,9 @@ const classNames = require('classnames'); const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); +const intlShape = require('../../lib/intl-shape'); const validate = require('../../lib/validate'); const FormikInput = require('../../components/formik-forms/formik-input.jsx'); const FormikCheckbox = require('../../components/formik-forms/formik-checkbox.jsx'); diff --git a/src/components/join-flow/welcome-step.jsx b/src/components/join-flow/welcome-step.jsx index 305ec5899..818d5ce7d 100644 --- a/src/components/join-flow/welcome-step.jsx +++ b/src/components/join-flow/welcome-step.jsx @@ -3,8 +3,9 @@ const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; const FormattedMessage = require('react-intl').FormattedMessage; -const {injectIntl, intlShape} = require('react-intl'); +const {injectIntl} = require('react-intl'); +const intlShape = require('../../lib/intl-shape'); const JoinFlowStep = require('./join-flow-step.jsx'); require('./join-flow-steps.scss'); diff --git a/src/components/languagechooser/languagechooser.jsx b/src/components/languagechooser/languagechooser.jsx index 2919521f1..d60644c1b 100644 --- a/src/components/languagechooser/languagechooser.jsx +++ b/src/components/languagechooser/languagechooser.jsx @@ -1,10 +1,10 @@ const bindAll = require('lodash.bindall'); const classNames = require('classnames'); const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../lib/intl-shape'); const jar = require('../../lib/jar.js'); const languages = require('scratch-l10n').default; const Form = require('../forms/form.jsx'); diff --git a/src/components/login/canceled-deletion-modal.jsx b/src/components/login/canceled-deletion-modal.jsx index c98028f7d..3a042b11d 100644 --- a/src/components/login/canceled-deletion-modal.jsx +++ b/src/components/login/canceled-deletion-modal.jsx @@ -3,8 +3,8 @@ const connect = require('react-redux').connect; const FormattedMessage = require('react-intl').FormattedMessage; const PropTypes = require('prop-types'); const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; +const intlShape = require('../../lib/intl-shape'); const navigationActions = require('../../redux/navigation.js'); const Modal = require('../modal/base/modal.jsx'); diff --git a/src/components/modal/addtostudio/presentation.jsx b/src/components/modal/addtostudio/presentation.jsx index bf6725897..e4097901f 100644 --- a/src/components/modal/addtostudio/presentation.jsx +++ b/src/components/modal/addtostudio/presentation.jsx @@ -2,9 +2,9 @@ const PropTypes = require('prop-types'); const React = require('react'); const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const Modal = require('../base/modal.jsx'); +const intlShape = require('../../../lib/intl-shape'); const Form = require('../../forms/form.jsx'); const Button = require('../../forms/button.jsx'); const Spinner = require('../../spinner/spinner.jsx'); diff --git a/src/components/modal/comments/delete-comment.jsx b/src/components/modal/comments/delete-comment.jsx index 5ddccee4a..95aa380bd 100644 --- a/src/components/modal/comments/delete-comment.jsx +++ b/src/components/modal/comments/delete-comment.jsx @@ -2,9 +2,9 @@ const PropTypes = require('prop-types'); const React = require('react'); const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const Modal = require('../base/modal.jsx'); +const intlShape = require('../../../lib/intl-shape'); const Button = require('../../forms/button.jsx'); const FlexRow = require('../../flex-row/flex-row.jsx'); diff --git a/src/components/modal/comments/report-comment.jsx b/src/components/modal/comments/report-comment.jsx index 613e6dffd..332b877dd 100644 --- a/src/components/modal/comments/report-comment.jsx +++ b/src/components/modal/comments/report-comment.jsx @@ -2,9 +2,9 @@ const PropTypes = require('prop-types'); const React = require('react'); const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const Modal = require('../base/modal.jsx'); +const intlShape = require('../../../lib/intl-shape'); const Button = require('../../forms/button.jsx'); const FlexRow = require('../../flex-row/flex-row.jsx'); diff --git a/src/components/modal/mute/modal.jsx b/src/components/modal/mute/modal.jsx index 0cd6ec806..6ee6aefa3 100644 --- a/src/components/modal/mute/modal.jsx +++ b/src/components/modal/mute/modal.jsx @@ -3,7 +3,6 @@ const PropTypes = require('prop-types'); const React = require('react'); const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const Modal = require('../base/modal.jsx'); const ModalInnerContent = require('../base/modal-inner-content.jsx'); const Button = require('../../forms/button.jsx'); @@ -12,9 +11,11 @@ const FlexRow = require('../../flex-row/flex-row.jsx'); const MuteStep = require('./mute-step.jsx'); const FeedbackForm = require('./feedback-form.jsx'); const classNames = require('classnames'); -require('./modal.scss'); const api = require('../../../lib/api'); +const intlShape = require('../../../lib/intl-shape'); + +require('./modal.scss'); const steps = { COMMENT_ISSUE: 0, diff --git a/src/components/modal/report/modal.jsx b/src/components/modal/report/modal.jsx index 70ec8e63a..82736c868 100644 --- a/src/components/modal/report/modal.jsx +++ b/src/components/modal/report/modal.jsx @@ -4,9 +4,9 @@ const React = require('react'); const connect = require('react-redux').connect; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const Modal = require('../base/modal.jsx'); +const intlShape = require('../../../lib/intl-shape'); const ModalTitle = require('../base/modal-title.jsx'); const ModalInnerContent = require('../base/modal-inner-content.jsx'); const Select = require('../../forms/select.jsx'); diff --git a/src/components/modal/social/presentation.jsx b/src/components/modal/social/presentation.jsx index ebbe485fe..792604d2a 100644 --- a/src/components/modal/social/presentation.jsx +++ b/src/components/modal/social/presentation.jsx @@ -1,9 +1,9 @@ const PropTypes = require('prop-types'); const React = require('react'); const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const classNames = require('classnames'); +const intlShape = require('../../../lib/intl-shape'); const Modal = require('../base/modal.jsx'); const ModalTitle = require('../base/modal-title.jsx'); const ModalInnerContent = require('../base/modal-inner-content.jsx'); diff --git a/src/components/navigation/www/navigation.jsx b/src/components/navigation/www/navigation.jsx index 46e31ff52..bfd65b7c7 100644 --- a/src/components/navigation/www/navigation.jsx +++ b/src/components/navigation/www/navigation.jsx @@ -3,10 +3,10 @@ const classNames = require('classnames'); const connect = require('react-redux').connect; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../../lib/intl-shape'); const messageCountActions = require('../../../redux/message-count.js'); const navigationActions = require('../../../redux/navigation.js'); const sessionActions = require('../../../redux/session.js'); diff --git a/src/components/registration/phone-number-step.jsx b/src/components/registration/phone-number-step.jsx index 4cb7040d4..7390a21aa 100644 --- a/src/components/registration/phone-number-step.jsx +++ b/src/components/registration/phone-number-step.jsx @@ -1,11 +1,11 @@ /* eslint-disable react/no-multi-comp */ const bindAll = require('lodash.bindall'); const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intl = require('react-intl'); -const intl = require('../../lib/intl.jsx'); +const intlShape = require('../../lib/intl-shape'); const Card = require('../../components/card/card.jsx'); const Checkbox = require('../../components/forms/checkbox.jsx'); diff --git a/src/components/registration/steps.jsx b/src/components/registration/steps.jsx index 8dc4d9d4a..055e6c394 100644 --- a/src/components/registration/steps.jsx +++ b/src/components/registration/steps.jsx @@ -1,14 +1,13 @@ /* eslint-disable react/no-multi-comp */ const bindAll = require('lodash.bindall'); -const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; +const {injectIntl, FormattedMessage} = require('react-intl'); const omit = require('lodash.omit'); const PropTypes = require('prop-types'); const React = require('react'); const api = require('../../lib/api'); const countryData = require('../../lib/country-data'); -const intl = require('../../lib/intl.jsx'); +const intlShape = require('../../lib/intl-shape'); const Avatar = require('../../components/avatar/avatar.jsx'); const Button = require('../../components/forms/button.jsx'); @@ -174,7 +173,7 @@ class UsernameStep extends React.Component { {this.props.title ? ( this.props.title ) : ( - + )}

@@ -182,9 +181,9 @@ class UsernameStep extends React.Component { this.props.description ) : ( -   +   - + )} @@ -281,7 +280,7 @@ class UsernameStep extends React.Component { /> } + text={} waiting={this.props.waiting || this.state.waiting} /> @@ -298,7 +297,7 @@ class UsernameStep extends React.Component { UsernameStep.propTypes = { activeStep: PropTypes.number, description: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), - intl: intl.intlShape, + intl: intlShape, onNextStep: PropTypes.func, showPassword: PropTypes.bool, title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), @@ -339,7 +338,7 @@ class ChoosePasswordStep extends React.Component { {this.props.intl.formatMessage({id: 'registration.choosePasswordStepTitle'})}

- + } + text={} waiting={this.props.waiting || this.state.waiting} /> @@ -501,12 +500,12 @@ class DemographicsStep extends React.Component { return (

- +

{this.props.description ? this.props.description : - + } } + text={} waiting={this.props.waiting} /> @@ -629,10 +628,10 @@ const IntlDemographicsStep = injectIntl(DemographicsStep); const NameStep = props => (

- +

- + ( }} /> } + text={} waiting={props.waiting} /> @@ -748,10 +747,10 @@ class OrganizationStep extends React.Component { return (

- +

- +

- +

- +

- +

- +

} + text={} waiting={this.props.waiting} /> @@ -906,10 +905,10 @@ class AddressStep extends React.Component { return (

- +

- + : [] } - + {this.state.countryChoice === 'us' ? [] :

- +

} } + text={} waiting={this.props.waiting || this.state.waiting} /> @@ -1062,10 +1061,10 @@ class UseScratchStep extends React.Component { return (

- +

- + } + text={} waiting={this.props.waiting} /> @@ -1192,10 +1191,10 @@ class EmailStep extends React.Component { return (

- +

- + } + text={} waiting={this.props.waiting} /> @@ -1272,6 +1271,7 @@ EmailStep.defaultProps = { const IntlEmailStep = injectIntl(EmailStep); +const EducatorResourcesLink = chunks => {chunks}; /* * TEACHER APPROVAL STEP @@ -1279,17 +1279,17 @@ const IntlEmailStep = injectIntl(EmailStep); const TeacherApprovalStep = props => (

- +

- +

{props.confirmed || !props.email ? [] : ( -

+

-
+
{props.email}

@@ -1297,16 +1297,19 @@ const TeacherApprovalStep = props => ( } {props.invited ? -

+

- +

: [] } -

+

- +

diff --git a/src/components/relative-time/relative-time.jsx b/src/components/relative-time/relative-time.jsx new file mode 100644 index 000000000..7825f726c --- /dev/null +++ b/src/components/relative-time/relative-time.jsx @@ -0,0 +1,39 @@ +const React = require('react'); +const {useEffect, useState} = React; +const PropTypes = require('prop-types'); +const {FormattedRelativeTime} = require('react-intl'); +const {selectUnit} = require('../../lib/select-unit'); + +const RelativeTime = ({value}) => { + const [selectedUnit, setSelectedUnit] = useState(selectUnit(value)); + + useEffect(() => { + // It is unlikely that users will leave this running for days. Don't + // auto-update beyond hours. + if (!['second', 'minute', 'hour'].includes(selectedUnit.unit)) return; + + const timerId = setInterval(() => { + const nextSelectedUnit = selectUnit(value); + if (selectedUnit.value !== nextSelectedUnit.value || + selectUnit.unit !== nextSelectedUnit.unit) { + setSelectedUnit(nextSelectedUnit); + } + }, 10000); + + return () => clearTimeout(timerId); + }, [value, selectedUnit]); + + return ( + + ); +}; + +RelativeTime.propTypes = { + value: PropTypes.instanceOf(Date) +}; + +module.exports = RelativeTime; diff --git a/src/components/social-message/social-message.jsx b/src/components/social-message/social-message.jsx index 5bb893494..fb174171a 100644 --- a/src/components/social-message/social-message.jsx +++ b/src/components/social-message/social-message.jsx @@ -1,9 +1,9 @@ const classNames = require('classnames'); -const FormattedRelative = require('react-intl').FormattedRelative; const PropTypes = require('prop-types'); const React = require('react'); const FlexRow = require('../flex-row/flex-row.jsx'); +const RelativeTime = require('../relative-time/relative-time.jsx'); require('./social-message.scss'); @@ -24,7 +24,7 @@ const SocialMessage = props => ( - + diff --git a/src/init.js b/src/init.js index a770fea95..bdfddfc8c 100644 --- a/src/init.js +++ b/src/init.js @@ -1,13 +1,12 @@ import 'regenerator-runtime/runtime'; // Needed for async/await const jar = require('./lib/jar'); -import intlPolyfill from './lib/intl-polyfill'; /** * ----------------------------------------------------------------------------- * L10N * ----------------------------------------------------------------------------- */ -(async () => { +(() => { /* * Bind locale code from cookie if available. Uses navigator language API as a fallback. * @@ -37,7 +36,6 @@ import intlPolyfill from './lib/intl-polyfill'; window._locale = updateLocale(); document.documentElement.lang = window._locale; - await intlPolyfill(window._locale); })(); /** diff --git a/src/l10n.json b/src/l10n.json index 256ee3cb0..41ce896c0 100644 --- a/src/l10n.json +++ b/src/l10n.json @@ -166,6 +166,7 @@ "registration.cantCreateAccount": "Scratch could not create your account.", "registration.checkOutResources": "Get Started with Resources", "registration.checkOutResourcesDescription": "Explore materials for educators and facilitators written by the Scratch Team, including tips, tutorials, and guides.", + "registration.checkOutResourcesDescriptionHTML": "Explore materials for educators and facilitators written by the Scratch Team, including tips, tutorials, and guides.", "registration.choosePasswordStepDescription": "Type in a new password for your account. You will use this password the next time you log into Scratch.", "registration.choosePasswordStepTitle": "Create a password", "registration.choosePasswordStepTooltip": "Don't use your name or anything that's easy for someone else to guess.", diff --git a/src/lib/intl-polyfill.js b/src/lib/intl-polyfill.js index 491bde480..31c139f2c 100644 --- a/src/lib/intl-polyfill.js +++ b/src/lib/intl-polyfill.js @@ -1,9 +1,9 @@ -// this file should only be `required` in the format-time -// when Intl.RelativeTimeFormat is not available (Safari < 14), but -// we're not currently able to do the code splitting in www, and it -// is always included. To reduce the amount of data that's loaded limit -// the number of languages loaded to just the top few that are still using -// safari <14. These seven account for most uses. +// This file polyfills the required Intl objects and locale data. +// The react-intl library uses PluralRules, RelativeTimeFormat, NumberFormat, +// and DateTimeFormat. Even if browsers support these objects, it is possible +// that the browser does not support the specific locale. +// There are a small number of Scratch locales that do not have polyfill locale +// data available. See /src/lib/locales.js for how they are handled. // relativetimeformat depends on locale which also needs to be polyfilled in // safari <14 // The plural rules is required for safari 12. @@ -11,6 +11,8 @@ import 'regenerator-runtime/runtime'; // Needed for async/await import {shouldPolyfill as shouldPolyfillLocale} from '@formatjs/intl-locale/should-polyfill'; import {shouldPolyfill as shouldPolyfillRelativeTimeFormat} from '@formatjs/intl-relativetimeformat/should-polyfill'; import {shouldPolyfill as shouldPolyfillPluralRules} from '@formatjs/intl-pluralrules/should-polyfill'; +import {shouldPolyfill as shouldPolyfillNumberFormat} from '@formatjs/intl-numberformat/should-polyfill'; +import {shouldPolyfill as shouldPolyfillDateTimeFormat} from '@formatjs/intl-datetimeformat/should-polyfill'; /** * polyfill all the parts needed from intl * @param {string} locale currently selected locale @@ -19,293 +21,458 @@ import {shouldPolyfill as shouldPolyfillPluralRules} from '@formatjs/intl-plural const intlPolyfill = async function (locale) { if (!(shouldPolyfillLocale() || shouldPolyfillPluralRules(locale) || - shouldPolyfillRelativeTimeFormat(locale))) { + shouldPolyfillRelativeTimeFormat(locale) || + shouldPolyfillNumberFormat(locale) || + shouldPolyfillDateTimeFormat(locale))) { return; } - if (shouldPolyfillRelativeTimeFormat(locale)) { - await import('@formatjs/intl-relativetimeformat/polyfill'); + if (shouldPolyfillLocale()) { + await import('@formatjs/intl-locale/polyfill-force'); } if (shouldPolyfillPluralRules(locale)) { - await import('@formatjs/intl-pluralrules/polyfill'); + await import('@formatjs/intl-pluralrules/polyfill-force'); } - if (shouldPolyfillLocale(locale)) { - await import('@formatjs/intl-locale/polyfill'); + if (shouldPolyfillRelativeTimeFormat(locale)) { + await import('@formatjs/intl-relativetimeformat/polyfill-force'); + } + + if (shouldPolyfillNumberFormat(locale)) { + await import('@formatjs/intl-numberformat/polyfill-force'); + } + + if (shouldPolyfillDateTimeFormat(locale)) { + await import('@formatjs/intl-datetimeformat/polyfill-force'); } switch (locale.toLowerCase().split('-')[0]) { case 'af': - await import('@formatjs/intl-relativetimeformat/locale-data/af'); await import('@formatjs/intl-pluralrules/locale-data/af'); + await import('@formatjs/intl-relativetimeformat/locale-data/af'); + await import('@formatjs/intl-numberformat/locale-data/af'); + await import('@formatjs/intl-datetimeformat/locale-data/af'); break; case 'ar': - await import('@formatjs/intl-relativetimeformat/locale-data/ar'); await import('@formatjs/intl-pluralrules/locale-data/ar'); + await import('@formatjs/intl-relativetimeformat/locale-data/ar'); + await import('@formatjs/intl-numberformat/locale-data/ar'); + await import('@formatjs/intl-datetimeformat/locale-data/ar'); break; case 'am': - await import('@formatjs/intl-relativetimeformat/locale-data/am'); await import('@formatjs/intl-pluralrules/locale-data/am'); + await import('@formatjs/intl-relativetimeformat/locale-data/am'); + await import('@formatjs/intl-numberformat/locale-data/am'); + await import('@formatjs/intl-datetimeformat/locale-data/am'); break; - case 'an': - await import('@formatjs/intl-relativetimeformat/locale-data/en'); - await import('@formatjs/intl-pluralrules/locale-data/an'); + case 'ast': + await import('@formatjs/intl-pluralrules/locale-data/ast'); + await import('@formatjs/intl-relativetimeformat/locale-data/ast'); + await import('@formatjs/intl-numberformat/locale-data/ast'); + await import('@formatjs/intl-datetimeformat/locale-data/ast'); break; case 'az': - await import('@formatjs/intl-relativetimeformat/locale-data/az'); await import('@formatjs/intl-pluralrules/locale-data/az'); + await import('@formatjs/intl-relativetimeformat/locale-data/az'); + await import('@formatjs/intl-numberformat/locale-data/az'); + await import('@formatjs/intl-datetimeformat/locale-data/az'); break; case 'id': - await import('@formatjs/intl-relativetimeformat/locale-data/id'); await import('@formatjs/intl-pluralrules/locale-data/id'); + await import('@formatjs/intl-relativetimeformat/locale-data/id'); + await import('@formatjs/intl-numberformat/locale-data/id'); + await import('@formatjs/intl-datetimeformat/locale-data/id'); break; case 'bn': - await import('@formatjs/intl-relativetimeformat/locale-data/bn'); await import('@formatjs/intl-pluralrules/locale-data/bn'); + await import('@formatjs/intl-relativetimeformat/locale-data/bn'); + await import('@formatjs/intl-numberformat/locale-data/bn'); + await import('@formatjs/intl-datetimeformat/locale-data/bn'); break; case 'be': - await import('@formatjs/intl-relativetimeformat/locale-data/be'); await import('@formatjs/intl-pluralrules/locale-data/be'); + await import('@formatjs/intl-relativetimeformat/locale-data/be'); + await import('@formatjs/intl-numberformat/locale-data/be'); + await import('@formatjs/intl-datetimeformat/locale-data/be'); break; case 'bg': - await import('@formatjs/intl-relativetimeformat/locale-data/bg'); await import('@formatjs/intl-pluralrules/locale-data/bg'); + await import('@formatjs/intl-relativetimeformat/locale-data/bg'); + await import('@formatjs/intl-numberformat/locale-data/bg'); + await import('@formatjs/intl-datetimeformat/locale-data/bg'); break; case 'ca': - await import('@formatjs/intl-relativetimeformat/locale-data/ca'); await import('@formatjs/intl-pluralrules/locale-data/ca'); + await import('@formatjs/intl-relativetimeformat/locale-data/ca'); + await import('@formatjs/intl-numberformat/locale-data/ca'); + await import('@formatjs/intl-datetimeformat/locale-data/ca'); break; case 'cs': - await import('@formatjs/intl-relativetimeformat/locale-data/cs'); await import('@formatjs/intl-pluralrules/locale-data/cs'); + await import('@formatjs/intl-relativetimeformat/locale-data/cs'); + await import('@formatjs/intl-numberformat/locale-data/cs'); + await import('@formatjs/intl-datetimeformat/locale-data/cs'); break; case 'cy': - await import('@formatjs/intl-relativetimeformat/locale-data/cy'); await import('@formatjs/intl-pluralrules/locale-data/cy'); + await import('@formatjs/intl-relativetimeformat/locale-data/cy'); + await import('@formatjs/intl-numberformat/locale-data/cy'); + await import('@formatjs/intl-datetimeformat/locale-data/cy'); break; case 'da': - await import('@formatjs/intl-relativetimeformat/locale-data/da'); await import('@formatjs/intl-pluralrules/locale-data/da'); + await import('@formatjs/intl-relativetimeformat/locale-data/da'); + await import('@formatjs/intl-numberformat/locale-data/da'); + await import('@formatjs/intl-datetimeformat/locale-data/da'); break; case 'de': - await import('@formatjs/intl-relativetimeformat/locale-data/de'); await import('@formatjs/intl-pluralrules/locale-data/de'); + await import('@formatjs/intl-relativetimeformat/locale-data/de'); + await import('@formatjs/intl-numberformat/locale-data/de'); + await import('@formatjs/intl-datetimeformat/locale-data/de'); break; case 'et': - await import('@formatjs/intl-relativetimeformat/locale-data/et'); await import('@formatjs/intl-pluralrules/locale-data/et'); + await import('@formatjs/intl-relativetimeformat/locale-data/et'); + await import('@formatjs/intl-numberformat/locale-data/et'); + await import('@formatjs/intl-datetimeformat/locale-data/et'); break; case 'el': - await import('@formatjs/intl-relativetimeformat/locale-data/el'); await import('@formatjs/intl-pluralrules/locale-data/el'); + await import('@formatjs/intl-relativetimeformat/locale-data/el'); + await import('@formatjs/intl-numberformat/locale-data/el'); + await import('@formatjs/intl-datetimeformat/locale-data/el'); break; case 'en': - await import('@formatjs/intl-relativetimeformat/locale-data/en'); await import('@formatjs/intl-pluralrules/locale-data/en'); + await import('@formatjs/intl-relativetimeformat/locale-data/en'); + await import('@formatjs/intl-numberformat/locale-data/en'); + await import('@formatjs/intl-datetimeformat/locale-data/en'); break; case 'es': - case 'rap': - case 'qu': - await import('@formatjs/intl-relativetimeformat/locale-data/es'); await import('@formatjs/intl-pluralrules/locale-data/es'); + await import('@formatjs/intl-relativetimeformat/locale-data/es'); + await import('@formatjs/intl-numberformat/locale-data/es'); + await import('@formatjs/intl-datetimeformat/locale-data/es'); + break; + case 'eo': + await import('@formatjs/intl-pluralrules/locale-data/eo'); + await import('@formatjs/intl-relativetimeformat/locale-data/eo'); + await import('@formatjs/intl-numberformat/locale-data/eo'); + await import('@formatjs/intl-datetimeformat/locale-data/eo'); break; case 'eu': - await import('@formatjs/intl-relativetimeformat/locale-data/eu'); await import('@formatjs/intl-pluralrules/locale-data/eu'); + await import('@formatjs/intl-relativetimeformat/locale-data/eu'); + await import('@formatjs/intl-numberformat/locale-data/eu'); + await import('@formatjs/intl-datetimeformat/locale-data/eu'); break; case 'fa': - await import('@formatjs/intl-relativetimeformat/locale-data/fa'); await import('@formatjs/intl-pluralrules/locale-data/fa'); + await import('@formatjs/intl-relativetimeformat/locale-data/fa'); + await import('@formatjs/intl-numberformat/locale-data/fa'); + await import('@formatjs/intl-datetimeformat/locale-data/fa'); + break; + case 'fil': + await import('@formatjs/intl-pluralrules/locale-data/fil'); + await import('@formatjs/intl-relativetimeformat/locale-data/fil'); + await import('@formatjs/intl-numberformat/locale-data/fil'); + await import('@formatjs/intl-datetimeformat/locale-data/fil'); break; case 'fr': - case 'ht': - await import('@formatjs/intl-relativetimeformat/locale-data/fr'); await import('@formatjs/intl-pluralrules/locale-data/fr'); + await import('@formatjs/intl-relativetimeformat/locale-data/fr'); + await import('@formatjs/intl-numberformat/locale-data/fr'); + await import('@formatjs/intl-datetimeformat/locale-data/fr'); break; case 'fy': - await import('@formatjs/intl-relativetimeformat/locale-data/fy'); await import('@formatjs/intl-pluralrules/locale-data/fy'); + await import('@formatjs/intl-relativetimeformat/locale-data/fy'); + await import('@formatjs/intl-numberformat/locale-data/fy'); + await import('@formatjs/intl-datetimeformat/locale-data/fy'); break; case 'ga': - await import('@formatjs/intl-relativetimeformat/locale-data/ga'); await import('@formatjs/intl-pluralrules/locale-data/ga'); + await import('@formatjs/intl-relativetimeformat/locale-data/ga'); + await import('@formatjs/intl-numberformat/locale-data/ga'); + await import('@formatjs/intl-datetimeformat/locale-data/ga'); break; case 'gd': - await import('@formatjs/intl-relativetimeformat/locale-data/gd'); await import('@formatjs/intl-pluralrules/locale-data/gd'); + await import('@formatjs/intl-relativetimeformat/locale-data/gd'); + await import('@formatjs/intl-numberformat/locale-data/gd'); + await import('@formatjs/intl-datetimeformat/locale-data/gd'); break; case 'gl': - await import('@formatjs/intl-relativetimeformat/locale-data/gl'); await import('@formatjs/intl-pluralrules/locale-data/gl'); + await import('@formatjs/intl-relativetimeformat/locale-data/gl'); + await import('@formatjs/intl-numberformat/locale-data/gl'); + await import('@formatjs/intl-datetimeformat/locale-data/gl'); break; case 'ko': - await import('@formatjs/intl-relativetimeformat/locale-data/ko'); await import('@formatjs/intl-pluralrules/locale-data/ko'); + await import('@formatjs/intl-relativetimeformat/locale-data/ko'); + await import('@formatjs/intl-numberformat/locale-data/ko'); + await import('@formatjs/intl-datetimeformat/locale-data/ko'); + break; + case 'ha': + await import('@formatjs/intl-pluralrules/locale-data/ha'); + await import('@formatjs/intl-relativetimeformat/locale-data/ha'); + await import('@formatjs/intl-numberformat/locale-data/ha'); + await import('@formatjs/intl-datetimeformat/locale-data/ha'); break; case 'hy': - await import('@formatjs/intl-relativetimeformat/locale-data/hy'); await import('@formatjs/intl-pluralrules/locale-data/hy'); + await import('@formatjs/intl-relativetimeformat/locale-data/hy'); + await import('@formatjs/intl-numberformat/locale-data/hy'); + await import('@formatjs/intl-datetimeformat/locale-data/hy'); break; case 'he': - await import('@formatjs/intl-relativetimeformat/locale-data/he'); await import('@formatjs/intl-pluralrules/locale-data/he'); + await import('@formatjs/intl-relativetimeformat/locale-data/he'); + await import('@formatjs/intl-numberformat/locale-data/he'); + await import('@formatjs/intl-datetimeformat/locale-data/he'); break; case 'hr': - await import('@formatjs/intl-relativetimeformat/locale-data/hr'); await import('@formatjs/intl-pluralrules/locale-data/hr'); + await import('@formatjs/intl-relativetimeformat/locale-data/hr'); + await import('@formatjs/intl-numberformat/locale-data/hr'); + await import('@formatjs/intl-datetimeformat/locale-data/hr'); break; case 'xh': - await import('@formatjs/intl-relativetimeformat/locale-data/xh'); await import('@formatjs/intl-pluralrules/locale-data/xh'); + await import('@formatjs/intl-relativetimeformat/locale-data/xh'); + await import('@formatjs/intl-numberformat/locale-data/xh'); + await import('@formatjs/intl-datetimeformat/locale-data/xh'); break; case 'zu': - await import('@formatjs/intl-relativetimeformat/locale-data/zu'); await import('@formatjs/intl-pluralrules/locale-data/zu'); + await import('@formatjs/intl-relativetimeformat/locale-data/zu'); + await import('@formatjs/intl-numberformat/locale-data/zu'); + await import('@formatjs/intl-datetimeformat/locale-data/zu'); break; case 'is': - await import('@formatjs/intl-relativetimeformat/locale-data/is'); await import('@formatjs/intl-pluralrules/locale-data/is'); + await import('@formatjs/intl-relativetimeformat/locale-data/is'); + await import('@formatjs/intl-numberformat/locale-data/is'); + await import('@formatjs/intl-datetimeformat/locale-data/is'); break; case 'it': - await import('@formatjs/intl-relativetimeformat/locale-data/it'); await import('@formatjs/intl-pluralrules/locale-data/it'); + await import('@formatjs/intl-relativetimeformat/locale-data/it'); + await import('@formatjs/intl-numberformat/locale-data/it'); + await import('@formatjs/intl-datetimeformat/locale-data/it'); break; case 'ka': - await import('@formatjs/intl-relativetimeformat/locale-data/ka'); await import('@formatjs/intl-pluralrules/locale-data/ka'); + await import('@formatjs/intl-relativetimeformat/locale-data/ka'); + await import('@formatjs/intl-numberformat/locale-data/ka'); + await import('@formatjs/intl-datetimeformat/locale-data/ka'); break; case 'kk': - await import('@formatjs/intl-relativetimeformat/locale-data/kk'); await import('@formatjs/intl-pluralrules/locale-data/kk'); + await import('@formatjs/intl-relativetimeformat/locale-data/kk'); + await import('@formatjs/intl-numberformat/locale-data/kk'); + await import('@formatjs/intl-datetimeformat/locale-data/kk'); + break; + case 'qu': + await import('@formatjs/intl-pluralrules/locale-data/en'); + await import('@formatjs/intl-relativetimeformat/locale-data/qu'); + await import('@formatjs/intl-numberformat/locale-data/qu'); + await import('@formatjs/intl-datetimeformat/locale-data/qu'); break; case 'sw': - await import('@formatjs/intl-relativetimeformat/locale-data/sw'); await import('@formatjs/intl-pluralrules/locale-data/sw'); + await import('@formatjs/intl-relativetimeformat/locale-data/sw'); + await import('@formatjs/intl-numberformat/locale-data/sw'); + await import('@formatjs/intl-datetimeformat/locale-data/sw'); break; case 'ku': - await import('@formatjs/intl-relativetimeformat/locale-data/ku'); await import('@formatjs/intl-pluralrules/locale-data/ku'); + await import('@formatjs/intl-relativetimeformat/locale-data/ku'); + await import('@formatjs/intl-numberformat/locale-data/ku'); + await import('@formatjs/intl-datetimeformat/locale-data/ku'); break; case 'ckb': - await import('@formatjs/intl-relativetimeformat/locale-data/ckb'); await import('@formatjs/intl-pluralrules/locale-data/ckb'); + await import('@formatjs/intl-relativetimeformat/locale-data/ckb'); + await import('@formatjs/intl-numberformat/locale-data/ckb'); + await import('@formatjs/intl-datetimeformat/locale-data/ckb'); break; case 'lv': - await import('@formatjs/intl-relativetimeformat/locale-data/lv'); await import('@formatjs/intl-pluralrules/locale-data/lv'); + await import('@formatjs/intl-relativetimeformat/locale-data/lv'); + await import('@formatjs/intl-numberformat/locale-data/lv'); + await import('@formatjs/intl-datetimeformat/locale-data/lv'); break; case 'lt': - await import('@formatjs/intl-relativetimeformat/locale-data/lt'); await import('@formatjs/intl-pluralrules/locale-data/lt'); + await import('@formatjs/intl-relativetimeformat/locale-data/lt'); + await import('@formatjs/intl-numberformat/locale-data/lt'); + await import('@formatjs/intl-datetimeformat/locale-data/lt'); break; case 'hu': - await import('@formatjs/intl-relativetimeformat/locale-data/hu'); await import('@formatjs/intl-pluralrules/locale-data/hu'); + await import('@formatjs/intl-relativetimeformat/locale-data/hu'); + await import('@formatjs/intl-numberformat/locale-data/hu'); + await import('@formatjs/intl-datetimeformat/locale-data/hu'); break; case 'mi': - await import('@formatjs/intl-relativetimeformat/locale-data/mi'); await import('@formatjs/intl-pluralrules/locale-data/en'); + await import('@formatjs/intl-relativetimeformat/locale-data/mi'); + await import('@formatjs/intl-numberformat/locale-data/mi'); + await import('@formatjs/intl-datetimeformat/locale-data/mi'); break; case 'mn': - await import('@formatjs/intl-relativetimeformat/locale-data/mn'); await import('@formatjs/intl-pluralrules/locale-data/mn'); + await import('@formatjs/intl-relativetimeformat/locale-data/mn'); + await import('@formatjs/intl-numberformat/locale-data/mn'); + await import('@formatjs/intl-datetimeformat/locale-data/mn'); break; case 'nl': - await import('@formatjs/intl-relativetimeformat/locale-data/nl'); await import('@formatjs/intl-pluralrules/locale-data/nl'); + await import('@formatjs/intl-relativetimeformat/locale-data/nl'); + await import('@formatjs/intl-numberformat/locale-data/nl'); + await import('@formatjs/intl-datetimeformat/locale-data/nl'); break; case 'ja': - await import('@formatjs/intl-relativetimeformat/locale-data/ja'); await import('@formatjs/intl-pluralrules/locale-data/ja'); + await import('@formatjs/intl-relativetimeformat/locale-data/ja'); + await import('@formatjs/intl-numberformat/locale-data/ja'); + await import('@formatjs/intl-datetimeformat/locale-data/ja'); break; case 'nb': - await import('@formatjs/intl-relativetimeformat/locale-data/nb'); await import('@formatjs/intl-pluralrules/locale-data/nb'); + await import('@formatjs/intl-relativetimeformat/locale-data/nb'); + await import('@formatjs/intl-numberformat/locale-data/nb'); + await import('@formatjs/intl-datetimeformat/locale-data/nb'); break; case 'nn': - await import('@formatjs/intl-relativetimeformat/locale-data/nn'); await import('@formatjs/intl-pluralrules/locale-data/nn'); + await import('@formatjs/intl-relativetimeformat/locale-data/nn'); + await import('@formatjs/intl-numberformat/locale-data/nn'); + await import('@formatjs/intl-datetimeformat/locale-data/nn'); break; case 'or': - await import('@formatjs/intl-relativetimeformat/locale-data/or'); await import('@formatjs/intl-pluralrules/locale-data/or'); + await import('@formatjs/intl-relativetimeformat/locale-data/or'); + await import('@formatjs/intl-numberformat/locale-data/or'); + await import('@formatjs/intl-datetimeformat/locale-data/or'); break; case 'uz': - await import('@formatjs/intl-relativetimeformat/locale-data/uz'); await import('@formatjs/intl-pluralrules/locale-data/uz'); + await import('@formatjs/intl-relativetimeformat/locale-data/uz'); + await import('@formatjs/intl-numberformat/locale-data/uz'); + await import('@formatjs/intl-datetimeformat/locale-data/uz'); break; case 'th': - await import('@formatjs/intl-relativetimeformat/locale-data/th'); await import('@formatjs/intl-pluralrules/locale-data/th'); + await import('@formatjs/intl-relativetimeformat/locale-data/th'); + await import('@formatjs/intl-numberformat/locale-data/th'); + await import('@formatjs/intl-datetimeformat/locale-data/th'); break; case 'km': - await import('@formatjs/intl-relativetimeformat/locale-data/km'); await import('@formatjs/intl-pluralrules/locale-data/km'); + await import('@formatjs/intl-relativetimeformat/locale-data/km'); + await import('@formatjs/intl-numberformat/locale-data/km'); + await import('@formatjs/intl-datetimeformat/locale-data/km'); break; case 'pl': - await import('@formatjs/intl-relativetimeformat/locale-data/pl'); await import('@formatjs/intl-pluralrules/locale-data/pl'); + await import('@formatjs/intl-relativetimeformat/locale-data/pl'); + await import('@formatjs/intl-numberformat/locale-data/pl'); + await import('@formatjs/intl-datetimeformat/locale-data/pl'); break; case 'pt': - await import('@formatjs/intl-relativetimeformat/locale-data/pt'); await import('@formatjs/intl-pluralrules/locale-data/pt'); + await import('@formatjs/intl-relativetimeformat/locale-data/pt'); + await import('@formatjs/intl-numberformat/locale-data/pt'); + await import('@formatjs/intl-datetimeformat/locale-data/pt'); break; case 'ro': - await import('@formatjs/intl-relativetimeformat/locale-data/ro'); await import('@formatjs/intl-pluralrules/locale-data/ro'); + await import('@formatjs/intl-relativetimeformat/locale-data/ro'); + await import('@formatjs/intl-numberformat/locale-data/ro'); + await import('@formatjs/intl-datetimeformat/locale-data/ro'); break; case 'ru': - await import('@formatjs/intl-relativetimeformat/locale-data/ru'); await import('@formatjs/intl-pluralrules/locale-data/ru'); + await import('@formatjs/intl-relativetimeformat/locale-data/ru'); + await import('@formatjs/intl-numberformat/locale-data/ru'); + await import('@formatjs/intl-datetimeformat/locale-data/ru'); break; case 'nso': - await import('@formatjs/intl-relativetimeformat/locale-data/en'); await import('@formatjs/intl-pluralrules/locale-data/nso'); + await import('@formatjs/intl-relativetimeformat/locale-data/en'); + await import('@formatjs/intl-numberformat/locale-data/en'); + await import('@formatjs/intl-datetimeformat/locale-data/en'); break; case 'tn': - await import('@formatjs/intl-relativetimeformat/locale-data/en'); await import('@formatjs/intl-pluralrules/locale-data/tn'); + await import('@formatjs/intl-relativetimeformat/locale-data/en'); + await import('@formatjs/intl-numberformat/locale-data/en'); + await import('@formatjs/intl-datetimeformat/locale-data/en'); break; case 'sk': - await import('@formatjs/intl-relativetimeformat/locale-data/sk'); await import('@formatjs/intl-pluralrules/locale-data/sk'); + await import('@formatjs/intl-relativetimeformat/locale-data/sk'); + await import('@formatjs/intl-numberformat/locale-data/sk'); + await import('@formatjs/intl-datetimeformat/locale-data/sk'); break; case 'sl': - await import('@formatjs/intl-relativetimeformat/locale-data/sl'); await import('@formatjs/intl-pluralrules/locale-data/sl'); + await import('@formatjs/intl-relativetimeformat/locale-data/sl'); + await import('@formatjs/intl-numberformat/locale-data/sl'); + await import('@formatjs/intl-datetimeformat/locale-data/sl'); break; case 'sr': - await import('@formatjs/intl-relativetimeformat/locale-data/sr'); await import('@formatjs/intl-pluralrules/locale-data/sr'); + await import('@formatjs/intl-relativetimeformat/locale-data/sr'); + await import('@formatjs/intl-numberformat/locale-data/sr'); + await import('@formatjs/intl-datetimeformat/locale-data/sr'); break; case 'fi': - await import('@formatjs/intl-relativetimeformat/locale-data/fi'); await import('@formatjs/intl-pluralrules/locale-data/fi'); + await import('@formatjs/intl-relativetimeformat/locale-data/fi'); + await import('@formatjs/intl-numberformat/locale-data/fi'); + await import('@formatjs/intl-datetimeformat/locale-data/fi'); break; case 'sv': - await import('@formatjs/intl-relativetimeformat/locale-data/sv'); await import('@formatjs/intl-pluralrules/locale-data/sv'); + await import('@formatjs/intl-relativetimeformat/locale-data/sv'); + await import('@formatjs/intl-numberformat/locale-data/sv'); + await import('@formatjs/intl-datetimeformat/locale-data/sv'); break; case 'vi': - await import('@formatjs/intl-relativetimeformat/locale-data/vi'); await import('@formatjs/intl-pluralrules/locale-data/vi'); + await import('@formatjs/intl-relativetimeformat/locale-data/vi'); + await import('@formatjs/intl-numberformat/locale-data/vi'); + await import('@formatjs/intl-datetimeformat/locale-data/vi'); break; case 'tr': - await import('@formatjs/intl-relativetimeformat/locale-data/tr'); await import('@formatjs/intl-pluralrules/locale-data/tr'); + await import('@formatjs/intl-relativetimeformat/locale-data/tr'); + await import('@formatjs/intl-numberformat/locale-data/tr'); + await import('@formatjs/intl-datetimeformat/locale-data/tr'); break; case 'uk': - await import('@formatjs/intl-relativetimeformat/locale-data/uk'); await import('@formatjs/intl-pluralrules/locale-data/uk'); + await import('@formatjs/intl-relativetimeformat/locale-data/uk'); + await import('@formatjs/intl-numberformat/locale-data/uk'); + await import('@formatjs/intl-datetimeformat/locale-data/uk'); break; case 'zh': - await import('@formatjs/intl-relativetimeformat/locale-data/zh'); await import('@formatjs/intl-pluralrules/locale-data/zh'); + await import('@formatjs/intl-relativetimeformat/locale-data/zh'); + await import('@formatjs/intl-numberformat/locale-data/zh'); + await import('@formatjs/intl-datetimeformat/locale-data/zh'); break; default: - await import('@formatjs/intl-relativetimeformat/locale-data/en'); await import('@formatjs/intl-pluralrules/locale-data/en'); + await import('@formatjs/intl-relativetimeformat/locale-data/en'); + await import('@formatjs/intl-numberformat/locale-data/en'); + await import('@formatjs/intl-datetimeformat/locale-data/en'); break; } }; diff --git a/src/lib/intl-shape.js b/src/lib/intl-shape.js new file mode 100644 index 000000000..fd7e9a3f3 --- /dev/null +++ b/src/lib/intl-shape.js @@ -0,0 +1,10 @@ +const PropTypes = require('prop-types'); + +// intlShape was removed in react-intl@3 and replaced with a TypeScript interface. +// These are some of the commonly used properties from the intl object. +const intlShape = PropTypes.shape({ + locale: PropTypes.string.isRequired, + formatMessage: PropTypes.func.isRequired +}); + +module.exports = intlShape; diff --git a/src/lib/intl.jsx b/src/lib/intl.jsx deleted file mode 100644 index 93f61a717..000000000 --- a/src/lib/intl.jsx +++ /dev/null @@ -1,7 +0,0 @@ -const ReactIntl = require('react-intl'); - -// Add locale data to react intl for all supported languages -const localeData = require('scratch-l10n').localeData; -ReactIntl.addLocaleData(localeData); - -module.exports = ReactIntl; diff --git a/src/lib/locales.js b/src/lib/locales.js new file mode 100644 index 000000000..31ef90cc0 --- /dev/null +++ b/src/lib/locales.js @@ -0,0 +1,44 @@ +/** + * Scratch has some locales that are not recognized by Intl. Use an appropriate alternative for these locales. + * @param {string} locale Scratch's locale + * @returns {string} the locale to use in IntlProvider + */ +const scratchLocaleToIntlLocale = locale => { + switch (locale) { + case 'ab': + return 'ru'; + case 'an': + case 'rap': + return 'es'; + case 'ht': + case 'oc': + return 'fr'; + default: + return locale; + } +}; + +/** + * Gets the locale for the current window. + * @returns {string} locale + */ +const getLocale = () => { + // Get locale from global namespace (see "init.js") + let locale = window._locale || 'en'; + if (typeof window._messages !== 'undefined') { + if (typeof window._messages[locale] === 'undefined') { + // Fall back on the split + locale = locale.split('-')[0]; + } + if (typeof window._messages[locale] === 'undefined') { + // Language appears to not be supported – fall back to 'en' + locale = 'en'; + } + } + return locale; +}; + +module.exports = { + getLocale, + scratchLocaleToIntlLocale +}; diff --git a/src/lib/render.jsx b/src/lib/render.jsx index e17358616..bc2309b26 100644 --- a/src/lib/render.jsx +++ b/src/lib/render.jsx @@ -2,11 +2,13 @@ const React = require('react'); // eslint-disable-line const ReactDOM = require('react-dom'); const StoreProvider = require('react-redux').Provider; +const IntlProvider = require('react-intl').IntlProvider; -const IntlProvider = require('./intl.jsx').IntlProvider; +const {getLocale, scratchLocaleToIntlLocale} = require('./locales.js'); const permissionsActions = require('../redux/permissions.js'); const sessionActions = require('../redux/session.js'); const configureStore = require('./configure-store.js'); +import intlPolyfill from '../lib/intl-polyfill'; require('../main.scss'); @@ -20,38 +22,35 @@ require('../main.scss'); */ const render = (jsx, element, reducers, initialState, enhancer) => { // Get locale and messages from global namespace (see "init.js") - let locale = window._locale || 'en'; + const locale = getLocale(); let messages = {}; if (typeof window._messages !== 'undefined') { - if (typeof window._messages[locale] === 'undefined') { - // Fall back on the split - locale = locale.split('-')[0]; - } - if (typeof window._messages[locale] === 'undefined') { - // Language appears to not be supported – fall back to 'en' - locale = 'en'; - } messages = window._messages[locale]; } + + const intlLocale = scratchLocaleToIntlLocale(locale); + // react-intl needs Intl before rendering + intlPolyfill(intlLocale).then(() => { + const store = configureStore(reducers, initialState, enhancer); - const store = configureStore(reducers, initialState, enhancer); - - // Render view component - ReactDOM.render( - - - {jsx} - - , - element - ); - - // Get initial session & permissions - store.dispatch(permissionsActions.getPermissions()); - store.dispatch(sessionActions.refreshSession()); + // Render view component + ReactDOM.render( + + + {jsx} + + , + element + ); + + // Get initial session & permissions + store.dispatch(permissionsActions.getPermissions()); + store.dispatch(sessionActions.refreshSession()); + }); }; module.exports = render; diff --git a/src/lib/select-unit.js b/src/lib/select-unit.js new file mode 100644 index 000000000..e711712f3 --- /dev/null +++ b/src/lib/select-unit.js @@ -0,0 +1,82 @@ +const MILLISECONDS_PER_SECOND = 1000; +const SECONDS_PER_MINUTE = 60; +const MINUTES_PER_HOUR = 60; +const HOURS_PER_DAY = 24; + +/** + * Determines the best unit (seconds, minutes, hours, days, months, or years) + * and value to represent the time difference between two dates. + * @param {Date} time - date to calculate relative units + * @param {Date} [relativeTo] - optional relative date, defaults to now + * @returns {object} calculated best unit and value + */ +const selectUnit = (time, relativeTo) => { + // Default to now + if (!relativeTo) relativeTo = new Date(); + + const seconds = (time - relativeTo) / MILLISECONDS_PER_SECOND; + if (Math.abs(seconds) < SECONDS_PER_MINUTE) { + return { + value: Math.trunc(seconds), + unit: 'second' + }; + } + + const minutes = seconds / SECONDS_PER_MINUTE; + if (Math.abs(minutes) < MINUTES_PER_HOUR) { + return { + value: Math.trunc(minutes), + unit: 'minute' + }; + } + + const hours = minutes / MINUTES_PER_HOUR; + if (Math.abs(hours) < HOURS_PER_DAY) { + return { + value: Math.trunc(hours), + unit: 'hour' + }; + } + + const days = hours / HOURS_PER_DAY; + + let years = time.getFullYear() - relativeTo.getFullYear(); + let months = time.getMonth() - relativeTo.getMonth() + (12 * years); + + // Handle calendar months different but less than a complete month elapsed + if (months > 0 && time.getDate() < relativeTo.getDate()) months--; + if (months < 0 && time.getDate() > relativeTo.getDate()) months++; + + if (Math.abs(months) < 1) { + return { + value: Math.trunc(days), + unit: 'day' + }; + } + + // Handle calendar years different but less than a complete year elapsed + if (years > 0 && (time.getMonth() < relativeTo.getMonth() || + (time.getMonth() === relativeTo.getMonth() && time.getDate() < relativeTo.getDate()))) { + years--; + } + if (years < 0 && (time.getMonth() > relativeTo.getMonth() || + (time.getMonth() === relativeTo.getMonth() && time.getDate() > relativeTo.getDate()))) { + years++; + } + + if (Math.abs(years) < 1) { + return { + value: months, + unit: 'month' + }; + } + + return { + value: years, + unit: 'year' + }; +}; + +module.exports = { + selectUnit +}; diff --git a/src/views/annual-report/2019/annual-report.jsx b/src/views/annual-report/2019/annual-report.jsx index c85d5affb..f38274b04 100644 --- a/src/views/annual-report/2019/annual-report.jsx +++ b/src/views/annual-report/2019/annual-report.jsx @@ -4,8 +4,8 @@ const React = require('react'); const MediaQuery = require('react-responsive').default; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; +const intlShape = require('../../../lib/intl-shape'); const render = require('../../../lib/render.jsx'); const frameless = require('../../../lib/frameless'); diff --git a/src/views/annual-report/2020/annual-report.jsx b/src/views/annual-report/2020/annual-report.jsx index c884401af..beff00816 100644 --- a/src/views/annual-report/2020/annual-report.jsx +++ b/src/views/annual-report/2020/annual-report.jsx @@ -4,8 +4,8 @@ const React = require('react'); const MediaQuery = require('react-responsive').default; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; +const intlShape = require('../../../lib/intl-shape'); const render = require('../../../lib/render.jsx'); const frameless = require('../../../lib/frameless'); @@ -2129,6 +2129,7 @@ class AnnualReport extends React.Component { comment={this.props.intl.formatMessage( {id: 'annualReport.2020.communityQuote2Text'} )} + datetimeCreated="2020-01-01" /> diff --git a/src/views/annual-report/2021/annual-report.jsx b/src/views/annual-report/2021/annual-report.jsx index 4d5b02ab1..4c4343e99 100644 --- a/src/views/annual-report/2021/annual-report.jsx +++ b/src/views/annual-report/2021/annual-report.jsx @@ -4,8 +4,8 @@ const React = require('react'); const MediaQuery = require('react-responsive').default; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; +const intlShape = require('../../../lib/intl-shape'); const render = require('../../../lib/render.jsx'); const frameless = require('../../../lib/frameless'); diff --git a/src/views/boost/boost.jsx b/src/views/boost/boost.jsx index 7f88b6d94..9f86be639 100644 --- a/src/views/boost/boost.jsx +++ b/src/views/boost/boost.jsx @@ -1,8 +1,9 @@ const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); +const intlShape = require('../../lib/intl-shape'); + const Page = require('../../components/page/www/page.jsx'); const render = require('../../lib/render.jsx'); diff --git a/src/views/camp/camp.jsx b/src/views/camp/camp.jsx index b57ccf17d..499290bd2 100644 --- a/src/views/camp/camp.jsx +++ b/src/views/camp/camp.jsx @@ -1,7 +1,6 @@ const React = require('react'); const injectIntl = require('react-intl').injectIntl; const FormattedMessage = require('react-intl').FormattedMessage; -const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage; const render = require('../../lib/render.jsx'); const TitleBanner = require('../../components/title-banner/title-banner.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); @@ -10,6 +9,10 @@ const Page = require('../../components/page/www/page.jsx'); require('./camp.scss'); +const MainStudio = chunks => {chunks}; +const FinalStudio = chunks => {chunks}; +const CounselorsStudio = chunks => {chunks}; + const Camp = injectIntl(() => (
@@ -40,7 +43,10 @@ const Camp = injectIntl(() => (

- + }} + />

@@ -63,7 +69,10 @@ const Camp = injectIntl(() => (

- +

@@ -86,7 +95,10 @@ const Camp = injectIntl(() => (

- +

@@ -109,7 +121,10 @@ const Camp = injectIntl(() => (

- +

@@ -132,7 +147,10 @@ const Camp = injectIntl(() => ( src="/images/camp/dolphin.svg" />

- +

diff --git a/src/views/camp/l10n.json b/src/views/camp/l10n.json index dffd9ecc0..4defb95ed 100644 --- a/src/views/camp/l10n.json +++ b/src/views/camp/l10n.json @@ -3,19 +3,24 @@ "camp.dates": "July 24th - August 13th", "camp.welcome": "Welcome to Scratch Camp 2017!", "camp.welcomeIntro": "Come take a dive into the ocean with us and design your very own creation. Your creation can be anything you might find in the ocean - real or made up!
In this year’s camp, dive down deep with us in these three parts:", + "camp.welcomeIntroHTML": "Come take a dive into the ocean with us and design your very own creation. Your creation can be anything you might find in the ocean - real or made up!{br}In this year’s camp, dive down deep with us in these three parts:", "camp.part1Dates":"Part 1 (July 24th - July 30th)", "camp.detailsTitle": "Details:", "camp.part1Details": "Create a project introducing us to a character, real or imagined, that lives in the ocean. You could create a monster from the depths, a cute little starfish, a taco eating shark, or anything else you can imagine.", "camp.particpateTitle": "How to Participate:", "camp.part1Particpate": "Part 1 of camp will take place in the Main Camp Cabin studio. Here you can ask questions, view other Scratchers' creations, and submit your own. Go to the studio to learn more!", + "camp.part1ParticpateHTML": "Part 1 of camp will take place in the Main Camp Cabin studio. Here you can ask questions, view other Scratchers' creations, and submit your own. Go to the studio to learn more!", "camp.part2Dates": "Part 2 (July 31st - August 6th)", "camp.part2Details": "Now make your character interactive! Does your character have questions to ask us? What happens when you click on it? Does it have any special powers? And more!", "camp.part2Particpate":"Part 2 of camp will also take place in the Main Camp Cabin studio. Here you can ask questions, view other Scratchers' creations, and submit your own. Go to the studio to learn more!", + "camp.part2ParticpateHTML":"Part 2 of camp will also take place in the Main Camp Cabin studio. Here you can ask questions, view other Scratchers' creations, and submit your own. Go to the studio to learn more!", "camp.part3Dates": "Part 3 (August 7th - August 13th)", "camp.part3Details": "Create a project using your own creation along with other Scratchers’ creations. It could be a game, story, animation, or anything you come up with!", "camp.part3Particpate":"The Final Projects Camp Cabin studio will hold part 3 of this year's Scratch Camp. Here you can submit your final project, give feedback to others, and celebrate Scratch Camp! Swim on over to the studio when part 3 comes out!", + "camp.part3ParticpateHTML":"The Final Projects Camp Cabin studio will hold part 3 of this year's Scratch Camp. Here you can submit your final project, give feedback to others, and celebrate Scratch Camp! Swim on over to the studio when part 3 comes out!", "camp.helpfulInfo": "Helpful Information", "camp.infoCounselors": "The Camp Counselors studio offers a variety of examples for your ocean creation. You can also directly communicate with the Counselors there.", + "camp.infoCounselorsHTML": "The Camp Counselors studio offers a variety of examples for your ocean creation. You can also directly communicate with the Counselors there.", "camp.infoPart3":"Remember, in part 3, you must use some other creations made for this Scratch Camp. Use their part 2 project to learn about the character's personality!", "camp.infoTime":"Don't worry if you aren't around the whole time, you can always participate in whatever part you are available for! Just have fun and dive deep!" } diff --git a/src/views/contact-us/contact-us.jsx b/src/views/contact-us/contact-us.jsx index 2e57f148a..9e022e4cf 100644 --- a/src/views/contact-us/contact-us.jsx +++ b/src/views/contact-us/contact-us.jsx @@ -1,9 +1,9 @@ const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const HelpForm = require('../../components/helpform/helpform.jsx'); diff --git a/src/views/download/download.jsx b/src/views/download/download.jsx index 26f0538bb..92c5eb94b 100644 --- a/src/views/download/download.jsx +++ b/src/views/download/download.jsx @@ -1,12 +1,12 @@ const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); const bindAll = require('lodash.bindall'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const detectOS = require('../../lib/detect-os.js').default; const OS_ENUM = require('../../lib/os-enum.js'); diff --git a/src/views/download/scratch-link/download.jsx b/src/views/download/scratch-link/download.jsx index 9a81da83d..ac0a88402 100644 --- a/src/views/download/scratch-link/download.jsx +++ b/src/views/download/scratch-link/download.jsx @@ -1,7 +1,8 @@ import React, {useState} from 'react'; -import {FormattedMessage, injectIntl, intlShape} from 'react-intl'; +import {FormattedMessage, injectIntl} from 'react-intl'; import Page from '../../../components/page/www/page.jsx'; +const intlShape = require('../../../lib/intl-shape'); import render from '../../../lib/render.jsx'; import FlexRow from '../../../components/flex-row/flex-row.jsx'; diff --git a/src/views/download/scratch2/download.jsx b/src/views/download/scratch2/download.jsx index 1bb90e664..e4b633d26 100644 --- a/src/views/download/scratch2/download.jsx +++ b/src/views/download/scratch2/download.jsx @@ -1,10 +1,9 @@ -const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const api = require('../../../lib/api'); +const intlShape = require('../../../lib/intl-shape'); const FlexRow = require('../../../components/flex-row/flex-row.jsx'); const SubNavigation = require('../../../components/subnavigation/subnavigation.jsx'); const TitleBanner = require('../../../components/title-banner/title-banner.jsx'); @@ -119,7 +118,10 @@ class Download extends React.Component {

{'1'}

-

+

{chunks}}} + />

@@ -208,8 +210,14 @@ class Download extends React.Component {

-

-

+

{chunks}}} + />

+

{chunks}}} + />

@@ -217,7 +225,10 @@ class Download extends React.Component {

-

+

{chunks}}} + />

Adobe AIR", + "download.airBodyHTML": "If you don't already have it, download and install the latest Adobe AIR", "download.macOSX": "Mac OS X", "download.macOlder": "Mac OS 10.5 & Older", "download.windows": "Windows", @@ -20,7 +21,9 @@ "download.currentVersion": "The current version is {version}.", "download.otherVersionsTitle": "Other Versions of Scratch", "download.otherVersionsOlder": "If you have an older computer, or cannot install the Scratch 2.0 offline editor, you can try installing Scratch 1.4.", + "download.otherVersionsOlderHTML": "If you have an older computer, or cannot install the Scratch 2.0 offline editor, you can try installing Scratch 1.4.", "download.otherVersionsAdmin": "If you are a network administrator: a Scratch 2.0 MSI has been created and maintained by a member of the community and hosted for public download here.", + "download.otherVersionsAdminHTML": "If you are a network administrator: a Scratch 2.0 MSI has been created and maintained by a member of the community and hosted for public download here.", "download.knownIssuesTitle": "Known issues", "download.knownIssuesOne": "If your offline editor is crashing directly after Scratch is opened, install the Scratch 2 offline editor again (see step 2 above). This issue is due to a bug introduced in Adobe AIR version 14 (released April 2014).", "download.knownIssuesTwo": "Graphic effects blocks (in \"Looks\") may slow down projects due to a known Flash bug.", diff --git a/src/views/ev3/ev3.jsx b/src/views/ev3/ev3.jsx index 187c29d7f..562715e28 100644 --- a/src/views/ev3/ev3.jsx +++ b/src/views/ev3/ev3.jsx @@ -1,10 +1,10 @@ const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); diff --git a/src/views/explore/explore.jsx b/src/views/explore/explore.jsx index b248605fd..4bd84f2f9 100644 --- a/src/views/explore/explore.jsx +++ b/src/views/explore/explore.jsx @@ -1,12 +1,13 @@ const bindAll = require('lodash.bindall'); const classNames = require('classnames'); const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const render = require('../../lib/render.jsx'); const api = require('../../lib/api'); +const intlShape = require('../../lib/intl-shape'); +const {getLocale} = require('../../lib/locales.js'); const Page = require('../../components/page/www/page.jsx'); const Tabs = require('../../components/tabs/tabs.jsx'); @@ -79,7 +80,7 @@ class Explore extends React.Component { handleGetExploreMore () { const qText = `&q=${this.state.acceptableTabs[this.state.category]}` || '*'; const mode = `&mode=${(this.state.mode ? this.state.mode : 'trending')}`; - const locale = this.props.intl.locale; + const locale = getLocale(); const queryString = `limit=${this.state.loadNumber}&offset=${this.state.offset}&language=${locale}${mode}${qText}`; diff --git a/src/views/faq/faq.jsx b/src/views/faq/faq.jsx index 9d6eaac0e..b622ce55f 100644 --- a/src/views/faq/faq.jsx +++ b/src/views/faq/faq.jsx @@ -1,9 +1,9 @@ const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const InformationPage = require('../../components/informationpage/informationpage.jsx'); diff --git a/src/views/gdxfor/gdxfor.jsx b/src/views/gdxfor/gdxfor.jsx index f4a3a9e60..ecd0f1b48 100644 --- a/src/views/gdxfor/gdxfor.jsx +++ b/src/views/gdxfor/gdxfor.jsx @@ -1,9 +1,9 @@ const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); diff --git a/src/views/ideas/ideas.jsx b/src/views/ideas/ideas.jsx index 2f6166d31..8680cbdc4 100644 --- a/src/views/ideas/ideas.jsx +++ b/src/views/ideas/ideas.jsx @@ -1,8 +1,6 @@ const bindAll = require('lodash.bindall'); -const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const Button = require('../../components/forms/button.jsx'); @@ -13,6 +11,7 @@ const TTTModal = require('../../components/modal/ttt/modal.jsx'); const TTTTile = require('../../components/ttt-tile/ttt-tile.jsx'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const Tiles = require('./ttt.json'); @@ -99,7 +98,7 @@ class Ideas extends React.Component {

- +

@@ -152,7 +151,7 @@ class Ideas extends React.Component {

- +

- +

@@ -220,7 +219,10 @@ class Ideas extends React.Component {

- + {chunks}}} + />

@@ -232,7 +234,13 @@ class Ideas extends React.Component {

- + {chunks}, + forum: chunks => {chunks} + }} + />

diff --git a/src/views/ideas/l10n.json b/src/views/ideas/l10n.json index 5ba0df501..68ac299c0 100644 --- a/src/views/ideas/l10n.json +++ b/src/views/ideas/l10n.json @@ -29,9 +29,10 @@ "ideas.educatorGuide": "Educator Guide", "ideas.desktopEditorHeader": "Scratch App Download", "ideas.desktopEditorBody": "To create projects without an Internet connection, you can download the Scratch app.", + "ideas.desktopEditorBodyHTML": "To create projects without an Internet connection, you can download the Scratch app.", "ideas.questionsHeader": "Questions", "ideas.questionsBody": "Have more questions? See the Frequently Asked Questions or visit the Help with Scripts Forum.", - + "ideas.questionsBodyHTML": "Have more questions? See the Frequently Asked Questions or visit the Help with Scripts Forum.", "ideas.cardsPurchase": "Purchase Printed Set", "ideas.MakeItFlyTitle": "Make It Fly", "ideas.MakeItFlyDescription": "Choose any character and make it fly!", diff --git a/src/views/messages/message-rows/comment-message.jsx b/src/views/messages/message-rows/comment-message.jsx index 26c064413..fb1f2f008 100644 --- a/src/views/messages/message-rows/comment-message.jsx +++ b/src/views/messages/message-rows/comment-message.jsx @@ -3,10 +3,10 @@ const classNames = require('classnames'); const connect = require('react-redux').connect; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../../lib/intl-shape'); const Comment = require('../../../components/comment/comment.jsx'); const FlexRow = require('../../../components/flex-row/flex-row.jsx'); const SocialMessage = require('../../../components/social-message/social-message.jsx'); diff --git a/src/views/messages/message-rows/curator-invite.jsx b/src/views/messages/message-rows/curator-invite.jsx index 1461391f5..72a40525a 100644 --- a/src/views/messages/message-rows/curator-invite.jsx +++ b/src/views/messages/message-rows/curator-invite.jsx @@ -1,10 +1,10 @@ const classNames = require('classnames'); const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../../lib/intl-shape'); const SocialMessage = require('../../../components/social-message/social-message.jsx'); const CuratorInviteMessage = props => ( diff --git a/src/views/messages/message-rows/scratcher-invite.jsx b/src/views/messages/message-rows/scratcher-invite.jsx index 661b1f25f..5fbd9a020 100644 --- a/src/views/messages/message-rows/scratcher-invite.jsx +++ b/src/views/messages/message-rows/scratcher-invite.jsx @@ -1,10 +1,10 @@ const FormattedDate = require('react-intl').FormattedDate; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../../lib/intl-shape'); const Button = require('../../../components/forms/button.jsx'); const FlexRow = require('../../../components/flex-row/flex-row.jsx'); diff --git a/src/views/messages/message-rows/user-join.jsx b/src/views/messages/message-rows/user-join.jsx index 308779937..f2392ba0b 100644 --- a/src/views/messages/message-rows/user-join.jsx +++ b/src/views/messages/message-rows/user-join.jsx @@ -1,10 +1,10 @@ const classNames = require('classnames'); const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../../lib/intl-shape'); const SocialMessage = require('../../../components/social-message/social-message.jsx'); const UserJoinMessage = props => ( diff --git a/src/views/messages/presentation.jsx b/src/views/messages/presentation.jsx index b551fdc72..10316c53e 100644 --- a/src/views/messages/presentation.jsx +++ b/src/views/messages/presentation.jsx @@ -2,10 +2,10 @@ const bindAll = require('lodash.bindall'); const FormattedMessage = require('react-intl').FormattedMessage; const FormattedNumber = require('react-intl').FormattedNumber; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const PropTypes = require('prop-types'); const React = require('react'); +const intlShape = require('../../lib/intl-shape'); const Button = require('../../components/forms/button.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); const Form = require('../../components/forms/form.jsx'); diff --git a/src/views/microbit/microbit.jsx b/src/views/microbit/microbit.jsx index cbcbefefc..c53b3f6f7 100644 --- a/src/views/microbit/microbit.jsx +++ b/src/views/microbit/microbit.jsx @@ -1,10 +1,9 @@ const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); - const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); diff --git a/src/views/preview/comment/comment.jsx b/src/views/preview/comment/comment.jsx index b1a1771ca..51e9db9d3 100644 --- a/src/views/preview/comment/comment.jsx +++ b/src/views/preview/comment/comment.jsx @@ -6,11 +6,11 @@ const classNames = require('classnames'); const FlexRow = require('../../../components/flex-row/flex-row.jsx'); const Avatar = require('../../../components/avatar/avatar.jsx'); const EmojiText = require('../../../components/emoji-text/emoji-text.jsx'); -const FormattedRelative = require('react-intl').FormattedRelative; const FormattedMessage = require('react-intl').FormattedMessage; const ComposeComment = require('./compose-comment.jsx'); const DeleteCommentModal = require('../../../components/modal/comments/delete-comment.jsx'); const ReportCommentModal = require('../../../components/modal/comments/report-comment.jsx'); +const RelativeTime = require('../../../components/relative-time/relative-time.jsx'); const decorateText = require('../../../lib/decorate-text.jsx'); require('./comment.scss'); @@ -224,7 +224,7 @@ class Comment extends React.Component { - + {(canReply && visible) ? ( { diff --git a/src/views/teacherregistration/l10n.json b/src/views/teacherregistration/l10n.json index 555610c84..4079b2e44 100644 --- a/src/views/teacherregistration/l10n.json +++ b/src/views/teacherregistration/l10n.json @@ -1,5 +1,6 @@ { "teacherRegistration.nameStepTitle": "First & Last Name", + "teacherRegistration.nameStepTitleNew": "First & Last Name", "teacherRegistration.nameStepDescription": "Your name will not be displayed publicly, and will be kept confidential and secure.", "teacherRegistration.firstName": "First Name", "teacherRegistration.lastName": "Last Name", diff --git a/src/views/teacherregistration/teacherregistration.jsx b/src/views/teacherregistration/teacherregistration.jsx index 5ed13a600..285aa673b 100644 --- a/src/views/teacherregistration/teacherregistration.jsx +++ b/src/views/teacherregistration/teacherregistration.jsx @@ -3,10 +3,10 @@ const connect = require('react-redux').connect; const defaults = require('lodash.defaultsdeep'); const PropTypes = require('prop-types'); const React = require('react'); +const injectIntl = require('react-intl').injectIntl; const api = require('../../lib/api'); -const injectIntl = require('../../lib/intl.jsx').injectIntl; -const intlShape = require('../../lib/intl.jsx').intlShape; +const intlShape = require('../../lib/intl-shape'); const sessionActions = require('../../redux/session.js'); const Deck = require('../../components/deck/deck.jsx'); diff --git a/src/views/teachers/faq/faq.jsx b/src/views/teachers/faq/faq.jsx index 47bba2a72..ec04db428 100644 --- a/src/views/teachers/faq/faq.jsx +++ b/src/views/teachers/faq/faq.jsx @@ -1,14 +1,16 @@ -const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage; const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); const Page = require('../../../components/page/www/page.jsx'); +const intlShape = require('../../../lib/intl-shape'); const render = require('../../../lib/render.jsx'); const InformationPage = require('../../../components/informationpage/informationpage.jsx'); +const RequestFormLink = chunks => {chunks}; +const ScratchEdLink = chunks => {chunks}; + const TeacherFaq = props => (
@@ -47,7 +49,10 @@ const TeacherFaq = props => ( width="565" />
-
+
@@ -76,9 +81,12 @@ const TeacherFaq = props => ( />
-
+
-
+
  • @@ -86,7 +94,7 @@ const TeacherFaq = props => (
-
+
@@ -187,7 +195,7 @@ const TeacherFaq = props => (
-
+
diff --git a/src/views/teachers/faq/l10n.json b/src/views/teachers/faq/l10n.json index b3d7f37cd..635c5ceca 100644 --- a/src/views/teachers/faq/l10n.json +++ b/src/views/teachers/faq/l10n.json @@ -8,6 +8,7 @@ "teacherfaq.teacherWhatBody": "A Scratch Teacher Account provides educators with additional features to manage student participation on Scratch, including the ability to create student accounts, organize student projects into studios, and monitor student comments. Learn more about Teacher Accounts in the video below:", "teacherfaq.teacherSignUpTitle": "How do I request a teacher account?", "teacherfaq.teacherSignUpBody": "To request a Teacher Account, please go to the teacher account request form.", + "teacherfaq.teacherSignUpBodyHTML": "To request a Teacher Account, please go to the teacher account request form.", "teacherfaq.classMultipleTeachersTitle": "Can a class have multiple teachers?", "teacherfaq.classMultipleTeachersBody": "A class can only have one teacher account associated with it.", "teacherfaq.teacherPersonalTitle": "Why do you need to know my personal information during registration?", @@ -16,6 +17,7 @@ "teacherfaq.teacherGoogleBody": "No, Scratch does not connect with any classroom management services.", "teacherfaq.teacherEdTitle": "Are Scratch Teacher accounts linked to ScratchEd accounts?", "teacherfaq.teacherEdBody": "No, Scratch Teacher accounts are not linked to ScratchEd accounts.", + "teacherfaq.teacherEdBodyHTML": "No, Scratch Teacher accounts are not linked to ScratchEd accounts.", "teacherfaq.teacherFeaturesTitle": "Does this feature exist, and if not, can you please add it?", "teacherfaq.teacherFeaturesBody": "Many features are commonly requested, including:", "teacherfaq.teacherFeaturesConvert": "Converting existing Scratch Accounts into Student Accounts", diff --git a/src/views/teachers/landing/landing.jsx b/src/views/teachers/landing/landing.jsx index 20c9937f1..008a1774f 100644 --- a/src/views/teachers/landing/landing.jsx +++ b/src/views/teachers/landing/landing.jsx @@ -1,6 +1,5 @@ const FormattedMessage = require('react-intl').FormattedMessage; const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const React = require('react'); @@ -10,6 +9,7 @@ const TitleBanner = require('../../../components/title-banner/title-banner.jsx') const Button = require('../../../components/forms/button.jsx'); const Page = require('../../../components/page/www/page.jsx'); +const intlShape = require('../../../lib/intl-shape'); const render = require('../../../lib/render.jsx'); require('./landing.scss'); @@ -275,7 +275,7 @@ const Landing = props => ( id="teacherlanding.codeClub" values={{ codeClubLink: ( - + ) diff --git a/src/views/wedo2-legacy/l10n.json b/src/views/wedo2-legacy/l10n.json index 82669cd90..a20e95b33 100644 --- a/src/views/wedo2-legacy/l10n.json +++ b/src/views/wedo2-legacy/l10n.json @@ -8,6 +8,7 @@ "wedoLegacy.downloadWin": "Download for Windows 10+", "wedoLegacy.setupTitle": "2. Setup & Help", "wedoLegacy.setupText": "Connect your WeDo 2.0 by following the steps in the Tips Window", + "wedoLegacy.setupTextHTML": "Connect your WeDo 2.0 by following the steps in the Tips Window", "wedoLegacy.createTitle": "3. Create", "wedoLegacy.createText": "Use the WeDo extension blocks to turn on lights, control motors, and make your project interactive", "wedoLegacy.wedo2SetupInstructions": "WeDo 2.0 Setup Instructions", diff --git a/src/views/wedo2-legacy/wedo2.jsx b/src/views/wedo2-legacy/wedo2.jsx index 3ab161941..c77f2e7a7 100644 --- a/src/views/wedo2-legacy/wedo2.jsx +++ b/src/views/wedo2-legacy/wedo2.jsx @@ -1,4 +1,3 @@ -const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); @@ -7,6 +6,8 @@ const render = require('../../lib/render.jsx'); require('./wedo2.scss'); +const TipsWindowLink = chunks => {chunks}; + const Wedo2 = () => (
@@ -40,7 +41,7 @@ const Wedo2 = () => (

- +
@@ -57,7 +58,10 @@ const Wedo2 = () => (

- +

diff --git a/src/views/wedo2/wedo2.jsx b/src/views/wedo2/wedo2.jsx index e1187050d..c42e52ec9 100644 --- a/src/views/wedo2/wedo2.jsx +++ b/src/views/wedo2/wedo2.jsx @@ -1,9 +1,9 @@ const injectIntl = require('react-intl').injectIntl; -const intlShape = require('react-intl').intlShape; const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const Page = require('../../components/page/www/page.jsx'); +const intlShape = require('../../lib/intl-shape'); const render = require('../../lib/render.jsx'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); diff --git a/test/helpers/intl-helpers.jsx b/test/helpers/intl-helpers.jsx index 8c9a057b4..43bbfb7c3 100644 --- a/test/helpers/intl-helpers.jsx +++ b/test/helpers/intl-helpers.jsx @@ -1,35 +1,50 @@ /* * Helpers for using enzyme and react-test-renderer with react-intl - * Directly from https://github.com/yahoo/react-intl/wiki/Testing-with-React-Intl */ import React from 'react'; import renderer from 'react-test-renderer'; -import {IntlProvider, intlShape} from 'react-intl'; +import {createIntl, IntlProvider} from 'react-intl'; import {mount, shallow} from 'enzyme'; +import intlShape from '../../src/lib/intl-shape'; -const intlProvider = new IntlProvider({locale: 'en'}, {}); -const {intl} = intlProvider.getChildContext(); +const shallowWithIntl = (node, {context} = {}) => { + return shallow( + node, + { + context: Object.assign({}, context), + wrappingComponent: IntlProvider, + wrappingComponentProps: { + locale: 'en', + messages: {} + } + } + ).dive(); +}; -const nodeWithIntlProp = node => React.cloneElement(node, {intl}); - -const shallowWithIntl = (node, {context} = {}) => shallow( - nodeWithIntlProp(node), - { - context: Object.assign({}, context, {intl}) - } -); - -const mountWithIntl = (node, {context, childContextTypes} = {}) => mount( - nodeWithIntlProp(node), - { - context: Object.assign({}, context, {intl}), - childContextTypes: Object.assign({}, {intl: intlShape}, childContextTypes) - } -); +const mountWithIntl = (node, {context, childContextTypes} = {}) => { + const intl = createIntl({locale: 'en', messages: {}}); + return mount( + node, + { + context: Object.assign({}, context, {intl}), + childContextTypes: Object.assign({}, {intl: intlShape}, childContextTypes), + wrappingComponent: IntlProvider, + wrappingComponentProps: { + locale: 'en', + messages: {} + } + } + ); +}; // react-test-renderer component for use with snapshot testing const componentWithIntl = (children, props = {locale: 'en'}) => renderer.create( - {children} + + {children} + ); export { diff --git a/test/unit/components/commenting-status.test.jsx b/test/unit/components/commenting-status.test.jsx index a96c40c15..d2b3709b3 100644 --- a/test/unit/components/commenting-status.test.jsx +++ b/test/unit/components/commenting-status.test.jsx @@ -1,10 +1,10 @@ const React = require('react'); -const {shallowWithIntl} = require('../../helpers/intl-helpers.jsx'); +const {shallow} = require('enzyme'); const CommentingStatus = require('../../../src/components/commenting-status/commenting-status.jsx'); describe('CommentingStatus', () => { test('Basic render', () => { - const component = shallowWithIntl( + const component = shallow( ); expect(component.find('div.commenting-status').exists()).toBe(true); @@ -12,7 +12,7 @@ describe('CommentingStatus', () => { }); test('ClassNames added', () => { - const component = shallowWithIntl( + const component = shallow( { }); test('Children added', () => { - const component = shallowWithIntl( + const component = shallow( diff --git a/test/unit/components/compose-comment.test.jsx b/test/unit/components/compose-comment.test.jsx index ddd0ff4ae..2d0687e24 100644 --- a/test/unit/components/compose-comment.test.jsx +++ b/test/unit/components/compose-comment.test.jsx @@ -48,7 +48,7 @@ describe('Compose Comment test', () => { /> , {context: {store}} ); - return wrapper.dive(); // unwrap redux connect(injectIntl(ComposeComment)) + return wrapper; }; test('status is EDITING when props do not contain a muteStatus ', () => { diff --git a/test/unit/components/email-confirmation-banner.test.jsx b/test/unit/components/email-confirmation-banner.test.jsx index 4eefcdf8f..6b470c362 100644 --- a/test/unit/components/email-confirmation-banner.test.jsx +++ b/test/unit/components/email-confirmation-banner.test.jsx @@ -13,7 +13,7 @@ describe('EmailConfirmationBanner', () => { expect(component.text()).not.toContain('MockEmailConfirmationModal'); const confirmWrapper = component.find({id: 'emailConfirmationBanner.confirm'}); - const confirmLink = mountWithIntl(confirmWrapper.instance().props.values.confirmLink); + const confirmLink = mountWithIntl(confirmWrapper.props().values.confirmLink); confirmLink.simulate('click'); component.update(); diff --git a/test/unit/components/email-confirmation-modal.test.jsx b/test/unit/components/email-confirmation-modal.test.jsx index 853736a88..c9c78522f 100644 --- a/test/unit/components/email-confirmation-modal.test.jsx +++ b/test/unit/components/email-confirmation-modal.test.jsx @@ -39,7 +39,7 @@ describe('Modal', () => { ); const tipsLinkWrapper = component.find({id: 'emailConfirmationModal.havingTrouble'}); - const tipsLink = mountWithIntl(tipsLinkWrapper.instance().props.values.tipsLink); + const tipsLink = mountWithIntl(tipsLinkWrapper.props().values.tipsLink); tipsLink.simulate('click'); expect(component.text()).toContain('emailConfirmationModal.confirmingTips'); }); diff --git a/test/unit/components/studio-comments.test.jsx b/test/unit/components/studio-comments.test.jsx index 0eec8b580..a8923f05c 100644 --- a/test/unit/components/studio-comments.test.jsx +++ b/test/unit/components/studio-comments.test.jsx @@ -9,6 +9,8 @@ jest.mock('../../../src/views/studio/studio-comment.js', () => ( )); describe('Studio comments', () => { + const testComments = [{id: 123, author: {}, datetime_created: new Date().toISOString()}]; + test('if there are no comments, they get loaded', () => { const loadComments = jest.fn(); const component = mountWithIntl( @@ -25,7 +27,7 @@ describe('Studio comments', () => { // When updated to have comments, load is not called again loadComments.mockClear(); - component.setProps({comments: [{id: 123, author: {}}]}); + component.setProps({comments: testComments}); component.update(); expect(loadComments).not.toHaveBeenCalled(); @@ -42,7 +44,7 @@ describe('Studio comments', () => { ); @@ -69,7 +71,7 @@ describe('Studio comments', () => { ); @@ -81,7 +83,7 @@ describe('Studio comments', () => { ); @@ -94,7 +96,7 @@ describe('Studio comments', () => { @@ -110,7 +112,7 @@ describe('Studio comments', () => { @@ -129,7 +131,7 @@ describe('Studio comments', () => { @@ -146,7 +148,7 @@ describe('Studio comments', () => { ); @@ -159,7 +161,7 @@ describe('Studio comments', () => { ); diff --git a/test/unit/lib/select-unit.test.js b/test/unit/lib/select-unit.test.js new file mode 100644 index 000000000..e47a777ee --- /dev/null +++ b/test/unit/lib/select-unit.test.js @@ -0,0 +1,63 @@ +const {selectUnit} = require('../../../src/lib/select-unit'); + +describe('unit test lib/select-unit.js', () => { + test('selects seconds', () => { + const result = selectUnit( + new Date('2023-02-03T12:00:00.000Z'), + new Date('2023-02-03T12:00:05.000Z') + ); + + expect(result.unit).toEqual('second'); + expect(result.value).toEqual(-5); + }); + + test('selects minutes', () => { + const result = selectUnit( + new Date('2023-02-03T12:01:10.000Z'), + new Date('2023-02-03T12:00:00.000Z') + ); + + expect(result.unit).toEqual('minute'); + expect(result.value).toEqual(1); + }); + + test('selects hours', () => { + const result = selectUnit( + new Date('2023-02-03T12:10:00.000Z'), + new Date('2023-02-03T14:00:00.000Z') + ); + + expect(result.unit).toEqual('hour'); + expect(result.value).toEqual(-1); + }); + + test('selects days', () => { + const result = selectUnit( + new Date('2023-02-03T12:00:00.000Z'), + new Date('2023-03-02T12:00:00.000Z') + ); + + expect(result.unit).toEqual('day'); + expect(result.value).toEqual(-27); + }); + + test('selects months', () => { + const result = selectUnit( + new Date('2023-02-03T12:00:00.000Z'), + new Date('2024-02-02T12:00:00.000Z') + ); + + expect(result.unit).toEqual('month'); + expect(result.value).toEqual(-11); + }); + + test('selects years', () => { + const result = selectUnit( + new Date('2023-02-03T12:00:00.000Z'), + new Date('2025-02-04T12:00:00.000Z') + ); + + expect(result.unit).toEqual('year'); + expect(result.value).toEqual(-2); + }); +});