From 0c81bccfca942d626f19c48bf394d262396addc0 Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Thu, 19 Oct 2023 09:27:45 +0100 Subject: [PATCH] Ensure that translation values are correctly escaped (#15252) GitOrigin-RevId: 5a38b4c01921fd4d95dbdb7b9e756443fdb00b80 --- package-lock.json | 1012 +++++++++++------ services/web/.eslintrc | 4 + .../web/frontend/extracted-translations.json | 2 - .../file-tree-create/error-message.jsx | 2 + .../modes/file-tree-upload-doc.jsx | 2 + .../file-tree-create/redirect-to-login.jsx | 2 + .../modals/file-tree-modal-error.jsx | 2 + .../file-view/components/file-view-header.tsx | 6 + .../components/group-members.tsx | 2 + .../managed-users-list-alert.tsx | 10 + .../diff-view/toolbar/toolbar-datetime.tsx | 4 + .../utils/highlights-from-diff-response.ts | 2 +- .../components/compile-timeout-messages.tsx | 4 + .../components/pdf-preview-error.jsx | 2 + .../components/timeout-upgrade-prompt-new.tsx | 4 + .../current-plan-widget/group-plan.tsx | 2 + .../current-plan-widget/individual-plan.tsx | 2 + .../notifications/ads/inr-banner.tsx | 2 + .../notifications/ads/latam-banner.tsx | 2 + .../affiliation/reconfirm-affiliation.tsx | 4 + .../notifications/groups/common.tsx | 10 + .../notifications/groups/confirm-email.tsx | 2 + .../group-invitation-cancel-subscription.tsx | 2 + .../group-invitation-join.tsx | 2 + .../notifications/groups/institution.tsx | 12 + .../notifications/translation-message.tsx | 2 + .../table/cells/last-updated-cell.tsx | 1 + .../components/table/project-list-table.tsx | 12 +- .../make-primary/confirmation-modal.tsx | 2 + .../settings/components/emails/add-email.tsx | 2 + .../emails/add-email/sso-linking-info.tsx | 2 + .../reconfirmation-info-prompt.tsx | 4 + .../reconfirmation-info-success.tsx | 2 + .../settings/components/emails/row.tsx | 4 + .../settings/components/emails/sso-alert.tsx | 6 + .../settings/components/leave/modal-form.tsx | 2 + .../components/managed-account-alert.tsx | 2 + ...-collaborators-upgrade-content-default.jsx | 2 + ...-collaborators-upgrade-content-variant.jsx | 2 + .../components/transfer-ownership-modal.jsx | 1 + .../group-subscription-membership.tsx | 2 + .../dashboard/institution-memberships.tsx | 2 + .../dashboard/managed-group-subscriptions.tsx | 4 + .../dashboard/managed-institution.tsx | 2 + .../dashboard/managed-publisher.tsx | 2 + ...rsonal-subscription-recurly-sync-email.tsx | 2 + .../dashboard/states/active/active.tsx | 4 + .../cancel-plan/cancel-subscription.tsx | 4 + .../modals/change-to-group-modal.tsx | 25 +- .../modals/confirm-change-plan-modal.tsx | 2 + .../modals/keep-current-plan-modal.tsx | 2 + .../active/pending-additional-licenses.tsx | 2 + .../states/active/pending-plan-change.tsx | 4 + .../states/active/subscription-remainder.tsx | 4 + .../dashboard/states/active/trial-ending.tsx | 2 + .../components/dashboard/states/canceled.tsx | 4 + .../successful-subscription.tsx | 2 + services/web/frontend/js/i18n.js | 4 + services/web/package.json | 8 +- .../table/project-list-table.test.tsx | 8 +- .../frontend/infrastructure/i18n.spec.tsx | 144 +++ 61 files changed, 1018 insertions(+), 361 deletions(-) create mode 100644 services/web/test/frontend/infrastructure/i18n.spec.tsx diff --git a/package-lock.json b/package-lock.json index a4b4e20405..1f72d6d56f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,6 +91,17 @@ "mongodb": "*" } }, + "libraries/eslint-plugin": { + "name": "@overleaf/eslint-plugin", + "version": "0.1.0", + "license": "AGPL-3.0-only", + "dependencies": { + "eslint": "^8.51.0" + }, + "devDependencies": { + "@typescript-eslint/parser": "^6.7.5" + } + }, "libraries/fetch-utils": { "name": "@overleaf/fetch-utils", "version": "0.1.0", @@ -533,6 +544,14 @@ "mocha": "^10.2.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -3005,11 +3024,11 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", - "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -3048,6 +3067,11 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/@babel/template": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", @@ -3750,7 +3774,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -3765,7 +3788,6 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -3774,24 +3796,22 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true, + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz", - "integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==", - "dev": true, + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.9.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -3800,13 +3820,15 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", - "dev": true, + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dependencies": { "type-fest": "^0.20.2" }, @@ -3817,6 +3839,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/js": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@fal-works/esbuild-plugin-global-externals": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", @@ -5217,24 +5247,34 @@ "integrity": "sha512-aKmlCO57XFZ26wso4rJsW4oTUnrgTFw2jh3io7CAtO9w4UltBNwRXvXIVzzyfkaaLRo3nluP/19msA8vDUUuKw==" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "node_modules/@icons/material": { "version": "0.2.4", @@ -7517,6 +7557,10 @@ "resolved": "services/document-updater", "link": true }, + "node_modules/@overleaf/eslint-plugin": { + "resolved": "libraries/eslint-plugin", + "link": true + }, "node_modules/@overleaf/fetch-utils": { "resolved": "libraries/fetch-utils", "link": true @@ -17648,6 +17692,237 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/parser": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.5", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@uppy/companion-client": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-1.10.2.tgz", @@ -24395,46 +24670,47 @@ } }, "node_modules/eslint": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", - "integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==", - "dev": true, + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dependencies": { - "@eslint/eslintrc": "^1.2.3", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -25055,7 +25331,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -25070,7 +25345,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -25083,59 +25357,35 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -25144,10 +25394,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dependencies": { "type-fest": "^0.20.2" }, @@ -25159,17 +25408,16 @@ } }, "node_modules/eslint/node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -25179,7 +25427,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -25204,22 +25451,25 @@ } }, "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dependencies": { - "acorn": "^8.7.1", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "bin": { "acorn": "bin/acorn" }, @@ -25228,11 +25478,14 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -25261,10 +25514,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dependencies": { "estraverse": "^5.1.0" }, @@ -26167,7 +26419,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -26797,12 +27048,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -27775,8 +28020,7 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/graphlib": { "version": "2.1.8", @@ -28581,22 +28825,36 @@ } }, "node_modules/i18next": { - "version": "19.9.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz", - "integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==", + "version": "23.5.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.5.1.tgz", + "integrity": "sha512-JelYzcaCoFDaa+Ysbfz2JsGAKkrHiMG6S61+HLBUEIPaF40WMwW9hCPymlQGrP+wWawKxKPuSuD71WZscCsWHg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], "dependencies": { - "@babel/runtime": "^7.12.0" + "@babel/runtime": "^7.22.5" } }, "node_modules/i18next-fs-backend": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.4.tgz", - "integrity": "sha512-/MfAGMP0jHonV966uFf9PkWWuDjPYLIcsipnSO3NxpNtAgRUKLTwvm85fEmsF6hGeu0zbZiCQ3W74jwO6K9uXA==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.2.0.tgz", + "integrity": "sha512-VOPHhdDX0M/csRqEw+9Ectpf6wvTIg1MZDfAHxc3JKnAlJz7fcZSAKAeyDohOq0xuLx57esYpJopIvBaRb0Bag==" }, "node_modules/i18next-http-middleware": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.1.5.tgz", - "integrity": "sha512-kk67719/uiURzRI9fhdfWjrM05ycXyPHHxGmqnFIsw55yHqEbfPgTl2JEA32lxYJclrr4qY2ifd/VVer4l+WMw==" + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.4.1.tgz", + "integrity": "sha512-5zYt+2WKZLKmhC0qSUKXAE98MNiM2ysXzHVQ2LoGkLjE5qXkMC7Nf570fc+SWnFF/yMh4Ur+gywgzLiBojfjZA==" }, "node_modules/i18next-scanner": { "version": "4.4.0", @@ -30363,8 +30621,7 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "node_modules/json-stringify-safe": { "version": "5.0.1", @@ -30936,7 +31193,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -32759,8 +33015,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "node_modules/ncp": { "version": "2.0.0", @@ -34828,7 +35083,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -35970,16 +36224,16 @@ } }, "node_modules/react-i18next": { - "version": "11.18.6", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", - "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.3.0.tgz", + "integrity": "sha512-FlR9xjYHSPIJfQspEmkN0yOlxgRyNuiJKJ8gCaZH08UJ7SZHG+VrptEPcpEMEchjNoCOZdKcvJ3PnmHEZhkeXg==", "dev": true, "dependencies": { - "@babel/runtime": "^7.14.5", + "@babel/runtime": "^7.22.5", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { - "i18next": ">= 19.0.0", + "i18next": ">= 23.2.3", "react": ">= 16.8.0" }, "peerDependenciesMeta": { @@ -39407,8 +39661,7 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "node_modules/thirty-two": { "version": "1.0.2", @@ -39812,7 +40065,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -39833,7 +40085,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true, "engines": { "node": ">=10" }, @@ -40286,12 +40537,6 @@ "uuid": "bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", @@ -43638,9 +43883,9 @@ "fuse.js": "^3.0.0", "globby": "^5.0.0", "helmet": "^6.0.1", - "i18next": "^19.6.3", - "i18next-fs-backend": "^1.0.7", - "i18next-http-middleware": "^3.0.2", + "i18next": "^23.5.1", + "i18next-fs-backend": "^2.2.0", + "i18next-http-middleware": "^3.4.1", "jose": "^4.3.8", "json2csv": "^4.3.3", "jsonwebtoken": "^9.0.0", @@ -43845,7 +44090,7 @@ "react-dom": "^17.0.2", "react-error-boundary": "^2.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^11.18.6", + "react-i18next": "^13.3.0", "react-linkify": "^1.0.0-alpha", "react-refresh": "^0.14.0", "react-resizable-panels": "^0.0.55", @@ -44146,34 +44391,6 @@ } } }, - "services/web/node_modules/@typescript-eslint/parser": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", - "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "services/web/node_modules/@typescript-eslint/scope-manager": { "version": "6.7.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", @@ -45122,6 +45339,11 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==" + }, "@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -46914,11 +47136,18 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "@babel/runtime": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", - "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "requires": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + } } }, "@babel/runtime-corejs2": { @@ -47404,7 +47633,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, "requires": { "eslint-visitor-keys": "^3.3.0" }, @@ -47412,27 +47640,24 @@ "eslint-visitor-keys": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==" } } }, "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==" }, "@eslint/eslintrc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz", - "integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==", - "dev": true, + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.9.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -47441,16 +47666,20 @@ }, "dependencies": { "globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", - "dev": true, + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "requires": { "type-fest": "^0.20.2" } } } }, + "@eslint/js": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==" + }, "@fal-works/esbuild-plugin-global-externals": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", @@ -48582,21 +48811,24 @@ } }, "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, "@icons/material": { "version": "0.2.4", @@ -50688,6 +50920,13 @@ } } }, + "@overleaf/eslint-plugin": { + "version": "file:libraries/eslint-plugin", + "requires": { + "@typescript-eslint/parser": "^6.7.5", + "eslint": "^8.51.0" + } + }, "@overleaf/fetch-utils": { "version": "file:libraries/fetch-utils", "requires": { @@ -51903,9 +52142,9 @@ "handlebars-loader": "^1.7.3", "helmet": "^6.0.1", "html-webpack-plugin": "^5.5.1", - "i18next": "^19.6.3", - "i18next-fs-backend": "^1.0.7", - "i18next-http-middleware": "^3.0.2", + "i18next": "^23.5.1", + "i18next-fs-backend": "^2.2.0", + "i18next-http-middleware": "^3.4.1", "i18next-scanner": "^4.4.0", "isomorphic-unfetch": "^3.0.0", "jose": "^4.3.8", @@ -51972,7 +52211,7 @@ "react-dom": "^17.0.2", "react-error-boundary": "^2.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^11.18.6", + "react-i18next": "^13.3.0", "react-linkify": "^1.0.0-alpha", "react-refresh": "^0.14.0", "react-resizable-panels": "^0.0.55", @@ -52224,19 +52463,6 @@ "ts-api-utils": "^1.0.1" } }, - "@typescript-eslint/parser": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", - "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "6.7.4", - "@typescript-eslint/types": "6.7.4", - "@typescript-eslint/typescript-estree": "6.7.4", - "@typescript-eslint/visitor-keys": "6.7.4", - "debug": "^4.3.4" - } - }, "@typescript-eslint/scope-manager": { "version": "6.7.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", @@ -59967,6 +60193,152 @@ "@types/node": "*" } }, + "@typescript-eslint/parser": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" + } + }, + "@typescript-eslint/types": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.5", + "eslint-visitor-keys": "^3.4.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + } + } + }, "@uppy/companion-client": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-1.10.2.tgz", @@ -65132,53 +65504,53 @@ } }, "eslint": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz", - "integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==", - "dev": true, + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "requires": { - "@eslint/eslintrc": "^1.2.3", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -65187,82 +65559,58 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "requires": { "is-glob": "^4.0.3" } }, "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "requires": { "type-fest": "^0.20.2" } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" } }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -65699,24 +66047,24 @@ "integrity": "sha512-8/2+iFfcB5FMJDBWXmXCY/4GSaI8sMCWUmq2laroQc3y9AI53QMm5Ew25DkW9FMaM8dBH8hmvOr2l3qChJ2JgA==" }, "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "requires": { - "acorn": "^8.7.1", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "dependencies": { "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" } } }, @@ -65732,10 +66080,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "requires": { "estraverse": "^5.1.0" } @@ -66435,7 +66782,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "requires": { "flat-cache": "^3.0.4" } @@ -66910,12 +67256,6 @@ "functions-have-names": "^1.2.2" } }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -67652,8 +67992,7 @@ "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "graphlib": { "version": "2.1.8", @@ -68301,22 +68640,22 @@ "dev": true }, "i18next": { - "version": "19.9.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz", - "integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==", + "version": "23.5.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.5.1.tgz", + "integrity": "sha512-JelYzcaCoFDaa+Ysbfz2JsGAKkrHiMG6S61+HLBUEIPaF40WMwW9hCPymlQGrP+wWawKxKPuSuD71WZscCsWHg==", "requires": { - "@babel/runtime": "^7.12.0" + "@babel/runtime": "^7.22.5" } }, "i18next-fs-backend": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.4.tgz", - "integrity": "sha512-/MfAGMP0jHonV966uFf9PkWWuDjPYLIcsipnSO3NxpNtAgRUKLTwvm85fEmsF6hGeu0zbZiCQ3W74jwO6K9uXA==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.2.0.tgz", + "integrity": "sha512-VOPHhdDX0M/csRqEw+9Ectpf6wvTIg1MZDfAHxc3JKnAlJz7fcZSAKAeyDohOq0xuLx57esYpJopIvBaRb0Bag==" }, "i18next-http-middleware": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.1.5.tgz", - "integrity": "sha512-kk67719/uiURzRI9fhdfWjrM05ycXyPHHxGmqnFIsw55yHqEbfPgTl2JEA32lxYJclrr4qY2ifd/VVer4l+WMw==" + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.4.1.tgz", + "integrity": "sha512-5zYt+2WKZLKmhC0qSUKXAE98MNiM2ysXzHVQ2LoGkLjE5qXkMC7Nf570fc+SWnFF/yMh4Ur+gywgzLiBojfjZA==" }, "i18next-scanner": { "version": "4.4.0", @@ -69607,8 +69946,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json-stringify-safe": { "version": "5.0.1", @@ -70045,7 +70383,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -71558,8 +71895,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "ncp": { "version": "2.0.0", @@ -73234,8 +73570,7 @@ "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, "prettier": { "version": "2.5.1", @@ -74157,12 +74492,12 @@ } }, "react-i18next": { - "version": "11.18.6", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", - "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.3.0.tgz", + "integrity": "sha512-FlR9xjYHSPIJfQspEmkN0yOlxgRyNuiJKJ8gCaZH08UJ7SZHG+VrptEPcpEMEchjNoCOZdKcvJ3PnmHEZhkeXg==", "dev": true, "requires": { - "@babel/runtime": "^7.14.5", + "@babel/runtime": "^7.22.5", "html-parse-stringify": "^3.0.1" } }, @@ -76832,8 +77167,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "thirty-two": { "version": "1.0.2", @@ -77165,7 +77499,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "requires": { "prelude-ls": "^1.2.1" } @@ -77179,8 +77512,7 @@ "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, "type-is": { "version": "1.6.18", @@ -77514,12 +77846,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", diff --git a/services/web/.eslintrc b/services/web/.eslintrc index 239ea7d1c3..6638f6f2b5 100644 --- a/services/web/.eslintrc +++ b/services/web/.eslintrc @@ -7,6 +7,7 @@ "standard", "prettier" ], + "plugins": ["@overleaf"], "env": { "es2020": true }, @@ -113,6 +114,9 @@ // "files": ["**/frontend/js/**/components/**/*.{js,jsx,ts,tsx}", "**/frontend/js/**/hooks/**/*.{js,jsx,ts,tsx}"], "rules": { + "@overleaf/no-empty-trans": "off", + "@overleaf/should-unescape-trans": "error", + // https://astexplorer.net/ "no-restricted-syntax": [ "error", diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 9f0631c583..8608aa7c4d 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -78,7 +78,6 @@ "are_you_getting_an_undefined_control_sequence_error": "", "are_you_still_at": "", "are_you_sure": "", - "ascending": "", "ask_proj_owner_to_upgrade_for_full_history": "", "ask_proj_owner_to_upgrade_for_longer_compiles": "", "ask_proj_owner_to_upgrade_for_references_search": "", @@ -251,7 +250,6 @@ "demonstrating_git_integration": "", "demonstrating_track_changes_feature": "", "department": "", - "descending": "", "description": "", "dictionary": "", "did_you_know_institution_providing_professional": "", diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.jsx index 1fdeef2566..ac89755518 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.jsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/error-message.jsx @@ -34,6 +34,8 @@ export default function ErrorMessage({ error }) { values={{ nameLimit: fileNameLimit, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.jsx index 4fbda08c3c..f8422bfbcf 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.jsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.jsx @@ -215,6 +215,8 @@ function UploadErrorMessage({ error, maxNumberOfFiles }) { ) diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/redirect-to-login.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/redirect-to-login.jsx index 0c20abfcc2..4b0f1c9c41 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-create/redirect-to-login.jsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/redirect-to-login.jsx @@ -34,6 +34,8 @@ export default function RedirectToLogin() { ) } diff --git a/services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-error.jsx b/services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-error.jsx index a9af162786..248c371447 100644 --- a/services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-error.jsx +++ b/services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-error.jsx @@ -46,6 +46,8 @@ function FileTreeModalError() { i18nKey="file_already_exists_in_this_location" components={[]} // eslint-disable-line react/jsx-key values={{ fileName: error.entityName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) case InvalidFilenameError: diff --git a/services/web/frontend/js/features/file-view/components/file-view-header.tsx b/services/web/frontend/js/features/file-view/components/file-view-header.tsx index 0f6a9d41a3..5de43e79bd 100644 --- a/services/web/frontend/js/features/file-view/components/file-view-header.tsx +++ b/services/web/frontend/js/features/file-view/components/file-view-header.tsx @@ -123,6 +123,8 @@ function UrlProvider({ file }: UrlProviderProps) { formattedDate: formatTime(file.created), relativeDate: relativeDate(file.created), }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

) @@ -156,6 +158,8 @@ function ProjectFilePathProvider({ file }: ProjectFilePathProviderProps) { formattedDate: formatTime(file.created), relativeDate: relativeDate(file.created), }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

/* esline-enable jsx-a11y/anchor-has-content, react/jsx-key */ @@ -189,6 +193,8 @@ function ProjectOutputFileProvider({ file }: ProjectOutputFileProviderProps) { formattedDate: formatTime(file.created), relativeDate: relativeDate(file.created), }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

) diff --git a/services/web/frontend/js/features/group-management/components/group-members.tsx b/services/web/frontend/js/features/group-management/components/group-members.tsx index 481acd1809..fb624b31a0 100644 --- a/services/web/frontend/js/features/group-management/components/group-members.tsx +++ b/services/web/frontend/js/features/group-management/components/group-members.tsx @@ -68,6 +68,8 @@ export default function GroupMembers() { i18nKey="you_have_added_x_of_group_size_y" components={[, ]} // eslint-disable-line react/jsx-key values={{ addedUsersSize: users.length, groupSize }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> )} diff --git a/services/web/frontend/js/features/group-management/components/managed-users/managed-users-list-alert.tsx b/services/web/frontend/js/features/group-management/components/managed-users/managed-users-list-alert.tsx index 277e780a16..018f2a59b6 100644 --- a/services/web/frontend/js/features/group-management/components/managed-users/managed-users-list-alert.tsx +++ b/services/web/frontend/js/features/group-management/components/managed-users/managed-users-list-alert.tsx @@ -69,6 +69,8 @@ function ResendManagedUserInviteSuccess({ values={{ email: invitedUserEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -89,6 +91,8 @@ function FailedToResendManagedInvite({ values={{ email: invitedUserEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -109,6 +113,8 @@ function ResendGroupInviteSuccess({ values={{ email: invitedUserEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -129,6 +135,8 @@ function FailedToResendGroupInvite({ values={{ email: invitedUserEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -149,6 +157,8 @@ function TooManyRequests({ values={{ email: invitedUserEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-datetime.tsx b/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-datetime.tsx index 8068948516..c5ff3af1ae 100644 --- a/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-datetime.tsx +++ b/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-datetime.tsx @@ -24,6 +24,8 @@ export default function ToolbarDatetime({ selection }: ToolbarDatetimeProps) { 'Do MMMM · h:mm a' ), }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) : ( )} diff --git a/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts b/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts index 4238d982fe..eddc55a8cc 100644 --- a/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts +++ b/services/web/frontend/js/features/history/utils/highlights-from-diff-response.ts @@ -2,7 +2,7 @@ import displayNameForUser from '../../../ide/history/util/displayNameForUser' import moment from 'moment/moment' import ColorManager from '../../../ide/colors/ColorManager' import { DocDiffChunk, Highlight } from '../services/types/doc' -import { TFunction } from 'react-i18next' +import { TFunction } from 'i18next' export function highlightsFromDiffResponse( chunks: DocDiffChunk[], diff --git a/services/web/frontend/js/features/pdf-preview/components/compile-timeout-messages.tsx b/services/web/frontend/js/features/pdf-preview/components/compile-timeout-messages.tsx index 35b1df2c13..9735c3a34a 100644 --- a/services/web/frontend/js/features/pdf-preview/components/compile-timeout-messages.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/compile-timeout-messages.tsx @@ -201,6 +201,8 @@ function CompileTimeoutMessages() { i18nKey="compile_timeout_will_be_reduced_project_exceeds_limit_speed_up_compile" components={compileTimeoutBlogLinks} values={{ date: 'October 27 2023' }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />{' '}

@@ -222,6 +224,8 @@ function CompileTimeoutMessages() { i18nKey="compile_timeout_will_be_reduced_project_exceeds_limit_speed_up_compile" components={compileTimeoutBlogLinks} values={{ date: 'October 27 2023' }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.jsx b/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.jsx index 6c9d533352..e41e8b1489 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.jsx +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.jsx @@ -72,6 +72,8 @@ function PdfPreviewError({ error }) { getMeta('ol-compilesUserContentDomain') ).hostname, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ , /* eslint-disable-next-line jsx-a11y/anchor-has-content */ diff --git a/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-prompt-new.tsx b/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-prompt-new.tsx index 4866dd5f38..ea0cb23809 100644 --- a/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-prompt-new.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-prompt-new.tsx @@ -112,6 +112,7 @@ const CompileTimeout = memo(function CompileTimeout({ )} } + // @ts-ignore entryAriaLabel={t('your_compile_timed_out')} level="error" /> @@ -163,6 +164,8 @@ const PreventTimeoutHelpMessage = memo(function PreventTimeoutHelpMessage({ />, ]} values={{ date: 'October 27 2023' }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> )} @@ -229,6 +232,7 @@ const PreventTimeoutHelpMessage = memo(function PreventTimeoutHelpMessage({

} + // @ts-ignore entryAriaLabel={t('other_ways_to_prevent_compile_timeouts')} level="raw" /> diff --git a/services/web/frontend/js/features/project-list/components/current-plan-widget/group-plan.tsx b/services/web/frontend/js/features/project-list/components/current-plan-widget/group-plan.tsx index 816eed4fdc..773e776fe8 100644 --- a/services/web/frontend/js/features/project-list/components/current-plan-widget/group-plan.tsx +++ b/services/web/frontend/js/features/project-list/components/current-plan-widget/group-plan.tsx @@ -25,6 +25,8 @@ function GroupPlan({ i18nKey="trial_remaining_days" components={{ b: }} values={{ days: remainingTrialDays }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) ) : ( diff --git a/services/web/frontend/js/features/project-list/components/current-plan-widget/individual-plan.tsx b/services/web/frontend/js/features/project-list/components/current-plan-widget/individual-plan.tsx index e407a9adee..f031df05de 100644 --- a/services/web/frontend/js/features/project-list/components/current-plan-widget/individual-plan.tsx +++ b/services/web/frontend/js/features/project-list/components/current-plan-widget/individual-plan.tsx @@ -24,6 +24,8 @@ function IndividualPlan({ i18nKey="trial_remaining_days" components={{ b: }} values={{ days: remainingTrialDays }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) ) : ( diff --git a/services/web/frontend/js/features/project-list/components/notifications/ads/inr-banner.tsx b/services/web/frontend/js/features/project-list/components/notifications/ads/inr-banner.tsx index ac930cf7d1..840d94f772 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/ads/inr-banner.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/ads/inr-banner.tsx @@ -123,6 +123,8 @@ export default function INRBanner({ variant, splitTestName }: INRBannerProps) { i18nKey="inr_discount_offer_green_banner" components={[,
]} // eslint-disable-line react/jsx-key values={{ flag: '🇮🇳' }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> diff --git a/services/web/frontend/js/features/project-list/components/notifications/ads/latam-banner.tsx b/services/web/frontend/js/features/project-list/components/notifications/ads/latam-banner.tsx index e1e7b9e956..d36fb876e1 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/ads/latam-banner.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/ads/latam-banner.tsx @@ -89,6 +89,8 @@ export default function LATAMBanner() { i18nKey="latam_discount_offer" components={[]} // eslint-disable-line react/jsx-key values={{ flag, currencyName, discountPercent }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx index d801228104..45d94fb86a 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx @@ -62,6 +62,8 @@ function ReconfirmAffiliation({ i18nKey="please_check_your_inbox_to_confirm" components={[]} // eslint-disable-line react/jsx-key values={{ institutionName: institution.name }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />   {isLoading ? ( @@ -113,6 +115,8 @@ function ReconfirmAffiliation({ i18nKey="are_you_still_at" components={[]} // eslint-disable-line react/jsx-key values={{ institutionName: institution.name }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />   }} values={{ projectName: notification.messageOpts.projectName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) : ( )} @@ -136,6 +140,8 @@ function CommonNotification({ notification }: CommonNotificationProps) { values={{ institutionName: notification.messageOpts.university_name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />
{notification.messageOpts.ssoEnabled ? ( @@ -163,6 +169,8 @@ function CommonNotification({ notification }: CommonNotificationProps) { values={{ institutionName: notification.messageOpts.university_name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />
{t('add_email_to_claim_features')} @@ -219,6 +227,8 @@ function CommonNotification({ notification }: CommonNotificationProps) { i18nKey="dropbox_duplicate_project_names" components={[]} // eslint-disable-line react/jsx-key values={{ projectName: notification.messageOpts.projectName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx index 09409c3924..29ba07b7a6 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx @@ -116,6 +116,8 @@ function ConfirmEmailNotification({ userEmail }: { userEmail: UserEmailData }) { institutionName: userEmail.affiliation?.institution.name, emailAddress: userEmail.email, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[]} // eslint-disable-line react/jsx-key /> diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-cancel-subscription.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-cancel-subscription.tsx index a73ef74b99..0091e24ad5 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-cancel-subscription.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-cancel-subscription.tsx @@ -31,6 +31,8 @@ export default function GroupInvitationCancelIndividualSubscriptionNotification( values={{ inviterName, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-join.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-join.tsx index ddca55838b..8e00c72606 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-join.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/group-invitation/group-invitation-join.tsx @@ -29,6 +29,8 @@ export default function GroupInvitationNotificationJoin({ values={{ inviterName, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/institution.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/institution.tsx index 4b28215264..14632c8295 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/institution.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/institution.tsx @@ -48,6 +48,8 @@ function Institution() { i18nKey="can_link_institution_email_acct_to_institution_acct" components={{ b: }} values={{ appName, email, institutionName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

@@ -55,6 +57,8 @@ function Institution() { i18nKey="doing_this_allow_log_in_through_institution" components={{ b: }} values={{ appName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />{' '} {t('learn_more')} @@ -82,6 +86,8 @@ function Institution() { i18nKey="account_has_been_link_to_institution_account" components={{ b: }} values={{ appName, email, institutionName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> @@ -97,11 +103,15 @@ function Institution() { i18nKey="tried_to_log_in_with_email" components={{ b: }} values={{ appName, email: requestedEmail }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />{' '} }} values={{ email: institutionEmail }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> @@ -117,6 +127,8 @@ function Institution() { i18nKey="tried_to_register_with_email" components={{ b: }} values={{ appName, email }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />{' '} {t('we_logged_you_in')} diff --git a/services/web/frontend/js/features/project-list/components/notifications/translation-message.tsx b/services/web/frontend/js/features/project-list/components/notifications/translation-message.tsx index 30cdd7fc11..6aab72c809 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/translation-message.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/translation-message.tsx @@ -23,6 +23,8 @@ function TranslationMessage() { i18nKey="click_here_to_view_sl_in_lng" components={[]} // eslint-disable-line react/jsx-key values={{ lngName: config.lngName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) : ( fromNowDate(project.lastUpdated) diff --git a/services/web/frontend/js/features/project-list/components/table/project-list-table.tsx b/services/web/frontend/js/features/project-list/components/table/project-list-table.tsx index 0a5be4c6ec..bd67402ea4 100644 --- a/services/web/frontend/js/features/project-list/components/table/project-list-table.tsx +++ b/services/web/frontend/js/features/project-list/components/table/project-list-table.tsx @@ -68,8 +68,8 @@ function ProjectListTable() { aria-sort={ sort.by === 'title' ? sort.order === 'asc' - ? t('ascending') - : t('descending') + ? 'ascending' + : 'descending' : undefined } > @@ -92,8 +92,8 @@ function ProjectListTable() { aria-sort={ sort.by === 'owner' ? sort.order === 'asc' - ? t('ascending') - : t('descending') + ? 'ascending' + : 'descending' : undefined } > @@ -110,8 +110,8 @@ function ProjectListTable() { aria-sort={ sort.by === 'lastUpdated' ? sort.order === 'asc' - ? t('ascending') - : t('descending') + ? 'ascending' + : 'descending' : undefined } > diff --git a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx index 8009ebb9b9..d7130d3a0d 100644 --- a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx +++ b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx @@ -33,6 +33,8 @@ function ConfirmationModal({ i18nKey="do_you_want_to_change_your_primary_email_address_to" components={{ b: }} values={{ email }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

{t('log_in_with_primary_email_address')}

diff --git a/services/web/frontend/js/features/settings/components/emails/add-email.tsx b/services/web/frontend/js/features/settings/components/emails/add-email.tsx index 7b9a21715d..aae4e5926c 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email.tsx @@ -117,6 +117,8 @@ function AddEmail() { values={{ emailAddressLimit, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[]} // eslint-disable-line react/jsx-key /> diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx index bd8f6cb47c..d9fa7bd036 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-email/sso-linking-info.tsx @@ -36,6 +36,7 @@ function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) { values={{ institutionName: domainInfo.university.name }} // eslint-disable-next-line react/jsx-boolean-value shouldUnescape={true} + tOptions={{ interpolation: { escapeValue: true } }} />

@@ -45,6 +46,7 @@ function SsoLinkingInfo({ domainInfo, email }: SSOLinkingInfoProps) { values={{ institutionName: domainInfo.university.name }} // eslint-disable-next-line react/jsx-boolean-value shouldUnescape={true} + tOptions={{ interpolation: { escapeValue: true } }} />{' '} ] @@ -155,6 +157,8 @@ function ReconfirmationInfoPromptText({ values={{ institutionName, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={ /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */ [] diff --git a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-success.tsx b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-success.tsx index a19474b06c..eaf9d1e353 100644 --- a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-success.tsx +++ b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-success.tsx @@ -17,6 +17,8 @@ function ReconfirmationInfoSuccess({ ]} // eslint-disable-line react/jsx-key />{' '} {t('thank_you_exclamation')} diff --git a/services/web/frontend/js/features/settings/components/emails/row.tsx b/services/web/frontend/js/features/settings/components/emails/row.tsx index e9582b901b..f7749c0345 100644 --- a/services/web/frontend/js/features/settings/components/emails/row.tsx +++ b/services/web/frontend/js/features/settings/components/emails/row.tsx @@ -98,6 +98,8 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) { values={{ institutionName: userEmailData.affiliation?.institution.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

@@ -120,6 +122,8 @@ function SSOAffiliationInfo({ userEmailData }: SSOAffiliationInfoProps) { institutionName: userEmailData.affiliation?.institution.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={ /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */ [] diff --git a/services/web/frontend/js/features/settings/components/emails/sso-alert.tsx b/services/web/frontend/js/features/settings/components/emails/sso-alert.tsx index 3d75d8de6f..fb082d420d 100644 --- a/services/web/frontend/js/features/settings/components/emails/sso-alert.tsx +++ b/services/web/frontend/js/features/settings/components/emails/sso-alert.tsx @@ -64,6 +64,8 @@ export function SSOAlert() { i18nKey="institution_acct_successfully_linked_2" components={[]} // eslint-disable-line react/jsx-key values={{ institutionName: institutionLinked.universityName }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

{institutionLinked.hasEntitlement && ( @@ -72,6 +74,8 @@ export function SSOAlert() { i18nKey="this_grants_access_to_features_2" components={[]} // eslint-disable-line react/jsx-key values={{ featureType: t('professional') }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

)} @@ -92,6 +96,8 @@ export function SSOAlert() { i18nKey="in_order_to_match_institutional_metadata_2" components={[]} // eslint-disable-line react/jsx-key values={{ email: institutionEmailNonCanonical }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

diff --git a/services/web/frontend/js/features/settings/components/leave/modal-form.tsx b/services/web/frontend/js/features/settings/components/leave/modal-form.tsx index c0486c26ab..6d44fa3fe9 100644 --- a/services/web/frontend/js/features/settings/components/leave/modal-form.tsx +++ b/services/web/frontend/js/features/settings/components/leave/modal-form.tsx @@ -107,6 +107,8 @@ function LeaveModalForm({ values={{ userDefaultEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> {error ? : null} diff --git a/services/web/frontend/js/features/settings/components/managed-account-alert.tsx b/services/web/frontend/js/features/settings/components/managed-account-alert.tsx index a327debc26..a4aea24f7c 100644 --- a/services/web/frontend/js/features/settings/components/managed-account-alert.tsx +++ b/services/web/frontend/js/features/settings/components/managed-account-alert.tsx @@ -25,6 +25,8 @@ export default function ManagedAccountAlert() { values={{ admin: currentManagedUserAdminEmail, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />
diff --git a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-default.jsx b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-default.jsx index cc7727202b..3dd7a4dffd 100644 --- a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-default.jsx +++ b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-default.jsx @@ -21,6 +21,8 @@ export default function AddCollaboratorsUpgradeContentDefault() {
  • diff --git a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-variant.jsx b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-variant.jsx index 8e7293681e..5f094cc3ee 100644 --- a/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-variant.jsx +++ b/services/web/frontend/js/features/share-project-modal/components/add-collaborators-upgrade-content-variant.jsx @@ -24,6 +24,8 @@ export default function AddCollaboratorsUpgradeContentVariant() {
  • diff --git a/services/web/frontend/js/features/share-project-modal/components/transfer-ownership-modal.jsx b/services/web/frontend/js/features/share-project-modal/components/transfer-ownership-modal.jsx index 668f08cb98..48cbf64830 100644 --- a/services/web/frontend/js/features/share-project-modal/components/transfer-ownership-modal.jsx +++ b/services/web/frontend/js/features/share-project-modal/components/transfer-ownership-modal.jsx @@ -44,6 +44,7 @@ export default function TransferOwnershipModal({ member, cancel }) { components={[, ]} // eslint-disable-next-line react/jsx-boolean-value shouldUnescape={true} + tOptions={{ interpolation: { escapeValue: true } }} />

    diff --git a/services/web/frontend/js/features/subscription/components/dashboard/group-subscription-membership.tsx b/services/web/frontend/js/features/subscription/components/dashboard/group-subscription-membership.tsx index 5920c42507..b8b00828b8 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/group-subscription-membership.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/group-subscription-membership.tsx @@ -37,6 +37,8 @@ export default function GroupSubscriptionMembership({ groupName: subscription.teamName || '', adminEmail: subscription.admin_id.email, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

    {subscription.teamNotice && ( diff --git a/services/web/frontend/js/features/subscription/components/dashboard/institution-memberships.tsx b/services/web/frontend/js/features/subscription/components/dashboard/institution-memberships.tsx index 97a72b772e..970a62e7f3 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/institution-memberships.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/institution-memberships.tsx @@ -31,6 +31,8 @@ function InstitutionMemberships() { planName: 'Professional', institutionName: institution.name || '', }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
    , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx index 2aa38b4c73..0843f5dc03 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx @@ -30,6 +30,8 @@ export default function ManagedGroupSubscriptions() { groupName: subscription.teamName || '', adminEmail: subscription.admin_id.email, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) : ( )}

    diff --git a/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx b/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx index 2837b909e2..54a1793372 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/managed-institution.tsx @@ -48,6 +48,8 @@ export default function ManagedInstitution({ values={{ institutionName: institution.name || '', }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

    , ]} // eslint-disable-line react/jsx-key values={{ recurlyEmail, userEmail }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />

    diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx index f96c499e0c..d711389518 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx @@ -39,6 +39,8 @@ export function ActiveSubscription({ values={{ planName: subscription.plan.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -95,6 +97,8 @@ export function ActiveSubscription({ paymentAmmount: subscription.recurly.displayPrice, collectionDate: subscription.recurly.nextPaymentDueAt, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx index b1c6d45622..a307b51822 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/cancel-subscription.tsx @@ -78,6 +78,8 @@ function NotCancelOption({ values={{ days: 14, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -105,6 +107,8 @@ function NotCancelOption({ values={{ price: planToDowngradeTo.displayPrice, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx index d3a34d1781..e6e92d6b4c 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx @@ -27,6 +27,8 @@ function GroupPlanCollaboratorCount({ planCode }: { planCode: string }) { values={{ collabcount: 10, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> ) @@ -44,6 +46,8 @@ function EducationDiscountAppliedOrNot({ groupSize }: { groupSize: string }) {

    ) @@ -54,6 +58,8 @@ function EducationDiscountAppliedOrNot({ groupSize }: { groupSize: string }) {

    ) @@ -92,6 +98,8 @@ function GroupPrice({ )} @@ -105,6 +113,8 @@ function GroupPrice({ values={{ price: perUserPrice, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> @@ -116,6 +126,8 @@ function GroupPrice({ values={{ price: perUserPrice, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> )} @@ -208,6 +220,8 @@ export function ChangeToGroupModal() { values={{ percent: '30', }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} />
    @@ -296,6 +310,8 @@ export function ChangeToGroupModal() { percent: educationalPercentDiscount, size: groupSizeForEducationalDiscount, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} /> @@ -345,6 +361,8 @@ export function ChangeToGroupModal() { subtotal: groupPlanToChangeToPrice.subtotal, tax: groupPlanToChangeToPrice.tax, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ /* eslint-disable-next-line react/jsx-key */ , @@ -375,7 +393,12 @@ export function ChangeToGroupModal() {
    diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx index e03df26544..04aaef757a 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx @@ -69,6 +69,8 @@ export function ConfirmChangePlanModal() { values={{ planName: plan.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx index ba42cde5f3..788539b90b 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx @@ -57,6 +57,8 @@ export function KeepCurrentPlanModal() { values={{ planName: personalSubscription.plan.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-additional-licenses.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-additional-licenses.tsx index ee58117152..d01774cc6e 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-additional-licenses.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-additional-licenses.tsx @@ -14,6 +14,8 @@ export function PendingAdditionalLicenses({ additionalLicenses, totalLicenses, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-plan-change.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-plan-change.tsx index b5c99fd627..5d375c822a 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-plan-change.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/pending-plan-change.tsx @@ -16,6 +16,8 @@ export function PendingPlanChange({ values={{ pendingPlanName: subscription.pendingPlan.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -35,6 +37,8 @@ export function PendingPlanChange({ subscription.recurly.pendingAdditionalLicenses, pendingTotalLicenses: subscription.recurly.pendingTotalLicenses, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/subscription-remainder.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/subscription-remainder.tsx index c619aabe8a..cb343f5f60 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/subscription-remainder.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/subscription-remainder.tsx @@ -17,6 +17,8 @@ function SubscriptionRemainder({ subscription }: SubscriptionRemainderProps) { values={{ terminationDate: subscription.recurly.nextPaymentDueAt, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -28,6 +30,8 @@ function SubscriptionRemainder({ subscription }: SubscriptionRemainderProps) { values={{ terminationDate: subscription.recurly.nextPaymentDueAt, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/trial-ending.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/trial-ending.tsx index 8e031e7454..3e7ce439a4 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/trial-ending.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/trial-ending.tsx @@ -10,6 +10,8 @@ export function TrialEnding({ , diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/canceled.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/canceled.tsx index 2f051395db..63f361ab0c 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/canceled.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/canceled.tsx @@ -17,6 +17,8 @@ export function CanceledSubscription({ values={{ planName: subscription.plan.name, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , @@ -29,6 +31,8 @@ export function CanceledSubscription({ values={{ terminateDate: subscription.recurly.nextPaymentDueAt, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[ // eslint-disable-next-line react/jsx-key , diff --git a/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx b/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx index 5b4b07934b..28f656dac7 100644 --- a/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx +++ b/services/web/frontend/js/features/subscription/components/successful-subscription/successful-subscription.tsx @@ -35,6 +35,8 @@ function SuccessfulSubscription() { paymentAmmount: subscription.recurly.displayPrice, collectionDate: subscription.recurly.nextPaymentDueAt, }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} components={[, ]} // eslint-disable-line react/jsx-key />

    diff --git a/services/web/frontend/js/i18n.js b/services/web/frontend/js/i18n.js index da02f61a07..6e95c574e8 100644 --- a/services/web/frontend/js/i18n.js +++ b/services/web/frontend/js/i18n.js @@ -33,6 +33,10 @@ i18n.use(initReactI18next).init({ // injection via another nested value skipOnVariables: true, + // Do not escape values, as `t` + React will already escape them + // (`escapeValue: true` and `shouldUnescape` must be set on each use of `Trans`) + escapeValue: false, + defaultVariables: { appName: window.ExposedSettings.appName, }, diff --git a/services/web/package.json b/services/web/package.json index 49c835b27e..a766d13117 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -109,9 +109,9 @@ "fuse.js": "^3.0.0", "globby": "^5.0.0", "helmet": "^6.0.1", - "i18next": "^19.6.3", - "i18next-fs-backend": "^1.0.7", - "i18next-http-middleware": "^3.0.2", + "i18next": "^23.5.1", + "i18next-fs-backend": "^2.2.0", + "i18next-http-middleware": "^3.4.1", "jose": "^4.3.8", "json2csv": "^4.3.3", "jsonwebtoken": "^9.0.0", @@ -316,7 +316,7 @@ "react-dom": "^17.0.2", "react-error-boundary": "^2.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^11.18.6", + "react-i18next": "^13.3.0", "react-linkify": "^1.0.0-alpha", "react-refresh": "^0.14.0", "react-resizable-panels": "^0.0.55", diff --git a/services/web/test/frontend/features/project-list/components/table/project-list-table.test.tsx b/services/web/test/frontend/features/project-list/components/table/project-list-table.test.tsx index b756b6402a..1eb0ce5e23 100644 --- a/services/web/test/frontend/features/project-list/components/table/project-list-table.test.tsx +++ b/services/web/test/frontend/features/project-list/components/table/project-list-table.test.tsx @@ -31,7 +31,7 @@ describe('', function () { const columns = screen.getAllByRole('columnheader') columns.forEach(col => { if (col.getAttribute('aria-label') === 'Last Modified') { - expect(col.getAttribute('aria-sort')).to.equal('Descending') + expect(col.getAttribute('aria-sort')).to.equal('descending') foundSortedColumn = true } else { expect(col.getAttribute('aria-sort')).to.be.null @@ -46,14 +46,14 @@ describe('', function () { name: /last modified/i, }) const lastModifiedCol = lastModifiedBtn.closest('th') - expect(lastModifiedCol?.getAttribute('aria-sort')).to.equal('Descending') + expect(lastModifiedCol?.getAttribute('aria-sort')).to.equal('descending') const ownerBtn = screen.getByRole('button', { name: /owner/i }) const ownerCol = ownerBtn.closest('th') expect(ownerCol?.getAttribute('aria-sort')).to.be.null fireEvent.click(ownerBtn) - expect(ownerCol?.getAttribute('aria-sort')).to.equal('Descending') + expect(ownerCol?.getAttribute('aria-sort')).to.equal('descending') fireEvent.click(ownerBtn) - expect(ownerCol?.getAttribute('aria-sort')).to.equal('Ascending') + expect(ownerCol?.getAttribute('aria-sort')).to.equal('ascending') }) it('renders buttons for sorting all sortable columns', function () { diff --git a/services/web/test/frontend/infrastructure/i18n.spec.tsx b/services/web/test/frontend/infrastructure/i18n.spec.tsx new file mode 100644 index 0000000000..d456882789 --- /dev/null +++ b/services/web/test/frontend/infrastructure/i18n.spec.tsx @@ -0,0 +1,144 @@ +import { Trans, useTranslation } from 'react-i18next' + +describe('i18n', function () { + describe('t', function () { + it('translates a plain string', function () { + const Test = () => { + const { t } = useTranslation() + return
    {t('accept')}
    + } + cy.mount() + cy.findByText('Accept') + }) + + it('uses defaultValues', function () { + const Test = () => { + const { t } = useTranslation() + return
    {t('welcome_to_sl')}
    + } + cy.mount() + cy.findByText('Welcome to Overleaf!') + }) + + it('uses values', function () { + const Test = () => { + const { t } = useTranslation() + return
    {t('sort_by_x', { x: 'name' })}
    + } + cy.mount() + cy.findByText('Sort by name') + }) + }) + + describe('Trans', function () { + it('translates a plain string', function () { + const Test = () => { + return ( +
    + +
    + ) + } + cy.mount() + cy.findByText('Accept') + }) + + it('uses defaultValues', function () { + const Test = () => { + return ( +
    + +
    + ) + } + cy.mount() + cy.findByText('Welcome to Overleaf!') + }) + + it('uses values', function () { + const Test = () => { + return ( +
    + +
    + ) + } + cy.mount() + cy.findByText('Sort by name') + }) + + it('uses an object of components', function () { + const Test = () => { + return ( +
    + }} + values={{ email: 'test@example.com' }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} + /> +
    + ) + } + cy.mount() + cy.findByTestId('container') + .should( + 'have.text', + 'In order to match your institutional metadata, your account is associated with the email test@example.com.' + ) + .find('b') + .should('have.length', 1) + .should('have.text', 'test@example.com') + }) + + it('uses an array of components', function () { + const Test = () => { + return ( +
    + ]} // eslint-disable-line react/jsx-key + values={{ institutionName: 'Test' }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} + /> +
    + ) + } + cy.mount() + cy.findByTestId('container') + .should('have.text', 'Are you still at Test?') + .find('b') + .should('have.length', 1) + .should('have.text', 'Test') + }) + + it('escapes special characters', function () { + const Test = () => { + return ( +
    + ]} // eslint-disable-line react/jsx-key + values={{ institutionName: "T&e'sting" }} + shouldUnescape + tOptions={{ interpolation: { escapeValue: true } }} + /> +
    + ) + } + cy.mount() + cy.findByTestId('container') + .should('have.text', "Are you still at T&e'sting?") + .find('b') + .should('have.length', 1) + .should('have.text', "T&e'sting") + }) + }) +})