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'st
ing" }}
+ shouldUnescape
+ tOptions={{ interpolation: { escapeValue: true } }}
+ />
+
+ )
+ }
+ cy.mount()
+ cy.findByTestId('container')
+ .should('have.text', "Are you still at T&e'st
ing?")
+ .find('b')
+ .should('have.length', 1)
+ .should('have.text', "T&e'st
ing")
+ })
+ })
+})