diff --git a/.github/workflows/webapp-ci.yml b/.github/workflows/webapp-ci.yml index 67bb02708a8..6bd49d3f834 100644 --- a/.github/workflows/webapp-ci.yml +++ b/.github/workflows/webapp-ci.yml @@ -41,18 +41,10 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: ci/setup uses: ./.github/actions/webapp-setup - - name: ci/lint + - name: ci/i18n-extract working-directory: webapp/channels run: | - cp src/i18n/en.json /tmp/en.json - mkdir -p /tmp/fake-mobile-dir/assets/base/i18n/ - echo '{}' > /tmp/fake-mobile-dir/assets/base/i18n/en.json - npm run mmjstool -- i18n extract-webapp --webapp-dir ./src --mobile-dir /tmp/fake-mobile-dir - diff /tmp/en.json src/i18n/en.json - # Address weblate behavior which does not remove whole translation item when translation string is set to empty - npm run mmjstool -- i18n clean-empty --webapp-dir ./src --mobile-dir /tmp/fake-mobile-dir --check - npm run mmjstool -- i18n check-empty-src --webapp-dir ./src --mobile-dir /tmp/fake-mobile-dir - rm -rf tmp + npm run i18n-extract:check check-types: needs: check-lint diff --git a/e2e-tests/cypress/package-lock.json b/e2e-tests/cypress/package-lock.json index 08aee13e696..96ba04cb05d 100644 --- a/e2e-tests/cypress/package-lock.json +++ b/e2e-tests/cypress/package-lock.json @@ -93,7 +93,6 @@ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -1071,7 +1070,6 @@ "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1114,6 +1112,7 @@ "integrity": "sha512-N4ntErOlKvcbTt01rr5wj3y55xnIdx1ymrfIr8C2WnM1Y9glFgWaGDEULJIazOX3XM9NRzhfJ6zZnQ1sBNWU+w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -1150,7 +1149,6 @@ "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.28.0", "@babel/types": "^7.28.0", @@ -1168,7 +1166,6 @@ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", @@ -1186,7 +1183,6 @@ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1197,7 +1193,6 @@ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" @@ -1212,7 +1207,6 @@ "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", @@ -1231,7 +1225,6 @@ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1252,7 +1245,6 @@ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1263,7 +1255,6 @@ "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.2" @@ -1278,7 +1269,6 @@ "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.28.0" }, @@ -1305,7 +1295,6 @@ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", @@ -1321,7 +1310,6 @@ "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", @@ -1341,7 +1329,6 @@ "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" @@ -1813,7 +1800,6 @@ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -1825,7 +1811,6 @@ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.0.0" } @@ -1836,7 +1821,6 @@ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -1847,8 +1831,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.30", @@ -1856,7 +1839,6 @@ "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1884,6 +1866,7 @@ "integrity": "sha512-2795KUkp2EkuJ9NVohPkJmrgKunt6OZiLyo8zUoIWPJjxQ0upjiWJz/KenABx38v8+QfpSEN8tZSBN3lsZCueg==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "typescript": "^4.3.0 || ^5.0.0" }, @@ -2866,7 +2849,6 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2878,7 +2860,6 @@ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -3179,6 +3160,7 @@ "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.39.1", "@typescript-eslint/types": "8.39.1", @@ -3397,7 +3379,6 @@ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -3408,24 +3389,21 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", @@ -3433,7 +3411,6 @@ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -3445,8 +3422,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", @@ -3454,7 +3430,6 @@ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3468,7 +3443,6 @@ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -3479,7 +3453,6 @@ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -3489,8 +3462,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", @@ -3498,7 +3470,6 @@ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3516,7 +3487,6 @@ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -3531,7 +3501,6 @@ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3545,7 +3514,6 @@ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -3561,7 +3529,6 @@ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -3572,16 +3539,14 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/accepts": { "version": "2.0.0", @@ -3603,6 +3568,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3616,7 +3582,6 @@ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.13.0" }, @@ -3671,7 +3636,6 @@ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -3690,7 +3654,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3707,8 +3670,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ally.js": { "version": "1.4.1", @@ -4340,8 +4302,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/byte-length": { "version": "1.0.2", @@ -4462,8 +4423,7 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "CC-BY-4.0", - "peer": true + "license": "CC-BY-4.0" }, "node_modules/caseless": { "version": "0.12.0", @@ -4558,7 +4518,6 @@ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.0" } @@ -4848,8 +4807,7 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/cookie": { "version": "0.7.2", @@ -4935,6 +4893,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@cypress/request": "^3.0.9", "@cypress/xvfb": "^1.2.4", @@ -5423,8 +5382,7 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -5473,6 +5431,7 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -5603,8 +5562,7 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -5702,6 +5660,7 @@ "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -5903,6 +5862,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6535,8 +6495,7 @@ "url": "https://opencollective.com/fastify" } ], - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/fast-xml-parser": { "version": "5.2.5", @@ -6916,7 +6875,6 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -7083,8 +7041,7 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/minimatch": { "version": "10.0.3", @@ -8046,7 +8003,6 @@ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -8062,7 +8018,6 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -8079,6 +8034,7 @@ "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -8116,7 +8072,6 @@ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jsesc": "bin/jsesc" }, @@ -8136,8 +8091,7 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json-schema": { "version": "0.4.0", @@ -8173,7 +8127,6 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "json5": "lib/cli.js" }, @@ -8449,7 +8402,6 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.11.5" } @@ -8652,7 +8604,6 @@ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "yallist": "^3.0.2" } @@ -8874,6 +8825,7 @@ "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", @@ -9417,8 +9369,7 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/node-ensure": { "version": "0.0.0", @@ -9432,8 +9383,7 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/notp": { "version": "2.0.3", @@ -10619,7 +10569,6 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -10852,7 +10801,6 @@ "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -10891,7 +10839,6 @@ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -10904,8 +10851,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -10972,6 +10918,7 @@ "integrity": "sha512-b0IrY3b1gVMsWvJppCf19g1p3JSnS0hQi6xu4Hi40CIhf0Lx8pQHcvBL+xunShpmOiQzg1NOia812NAWdSaShw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@servie/events": "^1.0.0", "byte-length": "^1.0.2", @@ -11229,7 +11176,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -11240,7 +11186,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -11659,7 +11604,6 @@ "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", @@ -11679,7 +11623,6 @@ "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -11714,8 +11657,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/thirty-two": { "version": "0.0.2", @@ -12038,6 +11980,7 @@ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12106,6 +12049,7 @@ "integrity": "sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.41.0", "@typescript-eslint/types": "8.41.0", @@ -12394,7 +12338,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -12513,7 +12456,6 @@ "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -12528,7 +12470,6 @@ "integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -12578,7 +12519,6 @@ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.13.0" } @@ -12589,7 +12529,6 @@ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -12604,7 +12543,6 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 0.6" } @@ -12615,7 +12553,6 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -12629,7 +12566,6 @@ "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -12906,8 +12842,7 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", diff --git a/e2e-tests/cypress/tests/integration/channels/accessibility/accessibility_popovers_spec.js b/e2e-tests/cypress/tests/integration/channels/accessibility/accessibility_popovers_spec.js index 27bbb892e77..e188633515d 100644 --- a/e2e-tests/cypress/tests/integration/channels/accessibility/accessibility_popovers_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/accessibility/accessibility_popovers_spec.js @@ -50,7 +50,7 @@ describe('Verify Accessibility Support in Popovers', () => { {ariaLabel: 'People & Body', header: 'People & Body'}, {ariaLabel: 'Animals & Nature', header: 'Animals & Nature'}, {ariaLabel: 'Food & Drink', header: 'Food & Drink'}, - {ariaLabel: 'Travel Places', header: 'Travel Places'}, + {ariaLabel: 'Travel & Places', header: 'Travel & Places'}, {ariaLabel: 'Activities', header: 'Activities'}, {ariaLabel: 'Objects', header: 'Objects'}, {ariaLabel: 'Symbols', header: 'Symbols'}, diff --git a/e2e-tests/cypress/tests/integration/channels/account_settings/profile/email_spec.ts b/e2e-tests/cypress/tests/integration/channels/account_settings/profile/email_spec.ts index 4339ae49753..3891822871d 100644 --- a/e2e-tests/cypress/tests/integration/channels/account_settings/profile/email_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/account_settings/profile/email_spec.ts @@ -85,7 +85,7 @@ describe('Profile > Profile Settings > Email', () => { cy.get('#primaryEmail').should('be.visible').click().blur(); // * Check that the correct error message is shown. - cy.get('#error_primaryEmail').should('be.visible').should('have.text', 'Please enter a valid email address'); + cy.get('#error_primaryEmail').should('be.visible').should('have.text', 'Please enter a valid email address.'); }); it('MM-T2067 email address already taken error', () => { diff --git a/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_1_spec.ts b/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_1_spec.ts index 8f3b02e29a3..6f4061bb835 100644 --- a/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_1_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_1_spec.ts @@ -61,7 +61,7 @@ describe('Authentication', () => { cy.get('#input_name').clear().type(`test${getRandomId()}`); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Make sure account was created successfully and we are at the select team page cy.findByText('Teams you can join:', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible'); @@ -113,7 +113,7 @@ describe('Authentication', () => { cy.get('#input_name').clear().type(`test${getRandomId()}`); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Make sure account was not created successfully cy.get('.AlertBanner__title').scrollIntoView().should('be.visible'); @@ -146,7 +146,7 @@ describe('Authentication', () => { cy.get('#input_name').clear().type(username); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Make sure account was created successfully and we are on the team joining page cy.findByText('Teams you can join:', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible'); diff --git a/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_2_spec.ts b/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_2_spec.ts index 9a3d2064d56..7198829b4f8 100644 --- a/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_2_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/auth_sso/authentication_2_spec.ts @@ -61,14 +61,14 @@ describe('Authentication', () => { cy.get('#input_password-input').clear().type('less'); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Assert the error is what is expected; cy.findByText('Your password must be 7-72 characters long.').should('be.visible'); cy.get('#input_password-input').clear().type('greaterthan7'); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Assert that we are not shown an MFA screen and instead a Teams You Can join page cy.findByText('Teams you can join:', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible'); @@ -114,7 +114,7 @@ describe('Authentication', () => { ['NOLOWERCASE123!', 'noupppercase123!', 'NoNumber!', 'NoSymbol123'].forEach((option) => { cy.get('#input_password-input').clear().type(option); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Assert the error is what is expected; cy.findByText('Your password must be 5-72 characters long and include both lowercase and uppercase letters, numbers, and special characters.').should('be.visible'); diff --git a/e2e-tests/cypress/tests/integration/channels/enterprise/accessibility/accessibility_input_fields_spec.ts b/e2e-tests/cypress/tests/integration/channels/enterprise/accessibility/accessibility_input_fields_spec.ts index 365b59a755f..09455c0e342 100644 --- a/e2e-tests/cypress/tests/integration/channels/enterprise/accessibility/accessibility_input_fields_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/enterprise/accessibility/accessibility_input_fields_spec.ts @@ -49,7 +49,7 @@ describe('Verify Accessibility Support in different input fields', () => { // * Verify Accessibility Support in Add or Invite People input field cy.get('.users-emails-input__control').should('be.visible').within(() => { - cy.get('input').should('have.attr', 'aria-label', 'Add or Invite People').and('have.attr', 'aria-autocomplete', 'list'); + cy.get('input').should('have.attr', 'aria-label', 'Invite People').and('have.attr', 'aria-autocomplete', 'list'); cy.get('.users-emails-input__placeholder').should('have.text', 'Enter a name or email address'); }); @@ -58,7 +58,7 @@ describe('Verify Accessibility Support in different input fields', () => { // * Verify Accessibility Support in Invite People input field cy.get('.users-emails-input__control').should('be.visible').within(() => { - cy.get('input').should('have.attr', 'aria-label', 'Add or Invite People').and('have.attr', 'aria-autocomplete', 'list'); + cy.get('input').should('have.attr', 'aria-label', 'Invite People').and('have.attr', 'aria-autocomplete', 'list'); cy.get('.users-emails-input__placeholder').should('have.text', 'Enter a name or email address'); }); diff --git a/e2e-tests/cypress/tests/integration/channels/enterprise/auth_sso/authentication_spec.ts b/e2e-tests/cypress/tests/integration/channels/enterprise/auth_sso/authentication_spec.ts index 00b914f9d26..22b2701697b 100644 --- a/e2e-tests/cypress/tests/integration/channels/enterprise/auth_sso/authentication_spec.ts +++ b/e2e-tests/cypress/tests/integration/channels/enterprise/auth_sso/authentication_spec.ts @@ -58,7 +58,7 @@ describe('Authentication', () => { cy.get('#input_name').clear().type(`Test${getRandomId()}`); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // * Make sure account was not created successfully cy.get('.AlertBanner__title').scrollIntoView().should('be.visible'); diff --git a/e2e-tests/cypress/tests/integration/channels/multi_team_and_dm/gm_header_spec.js b/e2e-tests/cypress/tests/integration/channels/multi_team_and_dm/gm_header_spec.js index 3bb9e501647..4a211564899 100644 --- a/e2e-tests/cypress/tests/integration/channels/multi_team_and_dm/gm_header_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/multi_team_and_dm/gm_header_spec.js @@ -61,7 +61,7 @@ describe('Multi-user group header', () => { cy.get('#editChannelHeaderModalLabel').should('be.visible').wait(TIMEOUTS.ONE_SEC); // # Add the header in the modal - cy.findByPlaceholderText('Edit the Channel Header...').should('be.visible').type(`${header}{enter}`); + cy.findByPlaceholderText('Enter the Channel Header').should('be.visible').type(`${header}{enter}`); // # Wait for modal to disappear cy.waitUntil(() => cy.get('#editChannelHeaderModalLabel').should('not.be.visible')); diff --git a/e2e-tests/cypress/tests/integration/channels/onboarding/existing_email_adress_spec.js b/e2e-tests/cypress/tests/integration/channels/onboarding/existing_email_adress_spec.js index 6849be8aaa5..c0c74a79c75 100644 --- a/e2e-tests/cypress/tests/integration/channels/onboarding/existing_email_adress_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/onboarding/existing_email_adress_spec.js @@ -32,7 +32,7 @@ function signupWithEmail(name, pw) { cy.get('#input_password-input').type(pw); // # Click on Create Account button - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); } describe('Cloud Onboarding', () => { diff --git a/e2e-tests/cypress/tests/integration/channels/onboarding/login_page_link_account_creation_spec.js b/e2e-tests/cypress/tests/integration/channels/onboarding/login_page_link_account_creation_spec.js index 19e79f25459..14f55a8f762 100644 --- a/e2e-tests/cypress/tests/integration/channels/onboarding/login_page_link_account_creation_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/onboarding/login_page_link_account_creation_spec.js @@ -71,7 +71,7 @@ describe('Onboarding', () => { cy.get('#input_email').should('be.focused').and('be.visible').type(email); cy.get('#input_name').should('be.visible').type(username); cy.get('#input_password-input').should('be.visible').type(password); - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); cy.findByText('You’re almost done!').should('be.visible'); diff --git a/e2e-tests/cypress/tests/integration/channels/onboarding/use_team_invite_link_to_sign_up_spec.js b/e2e-tests/cypress/tests/integration/channels/onboarding/use_team_invite_link_to_sign_up_spec.js index ea10dd6eb64..92eb39043d5 100644 --- a/e2e-tests/cypress/tests/integration/channels/onboarding/use_team_invite_link_to_sign_up_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/onboarding/use_team_invite_link_to_sign_up_spec.js @@ -71,8 +71,8 @@ describe('Onboarding', () => { cy.get('#input_name').should('be.visible').type(username); cy.get('#input_password-input').should('be.visible').type(password); - // # Attempt to create an account by clicking on the 'Create Account' button - cy.findByText('Create Account').click(); + // # Attempt to create an account by clicking on the 'Create account' button + cy.findByText('Create account').click(); cy.wait(TIMEOUTS.HALF_SEC); diff --git a/e2e-tests/cypress/tests/integration/channels/signin_authentication/forgot_password_spec.js b/e2e-tests/cypress/tests/integration/channels/signin_authentication/forgot_password_spec.js index c53c510b088..ea0037c59e3 100644 --- a/e2e-tests/cypress/tests/integration/channels/signin_authentication/forgot_password_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/signin_authentication/forgot_password_spec.js @@ -91,7 +91,7 @@ describe('Signin/Authentication', () => { cy.url().should('contain', '/login?extra=password_change'); // * Should show that the password is updated successfully - cy.get('.AlertBanner.success').should('be.visible').and('have.text', ' Password updated successfully'); + cy.get('.AlertBanner.success').should('be.visible').and('have.text', 'Password updated successfully'); // # Type email and new password, then click login button cy.get('#input_loginId').should('be.visible').type(testUser.username); diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js index f79a019a9fb..9512f2bf3c1 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/closed_team_invite_by_email_spec.js @@ -85,7 +85,7 @@ describe('Team Settings', () => { cy.get('.InviteAs').findByTestId('inviteMembersLink').click(); } - cy.findByRole('combobox', {name: 'Add or Invite People'}).type(email, {force: true}).wait(TIMEOUTS.HALF_SEC).type('{enter}', {force: true}); + cy.findByRole('combobox', {name: 'Invite People'}).type(email, {force: true}).wait(TIMEOUTS.HALF_SEC).type('{enter}', {force: true}); cy.findByTestId('inviteButton').click(); // # Wait for a while to ensure that email notification is sent and logout from sysadmin account @@ -115,7 +115,7 @@ describe('Team Settings', () => { cy.get('#input_password-input').type(password); // # Attempt to create an account by clicking on the 'Create Account' button - cy.findByText('Create Account').click(); + cy.findByText('Create account').click(); // # Close the onboarding tutorial cy.uiCloseOnboardingTaskList(); diff --git a/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js b/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js index 0e5096cff4f..976ad356bc3 100644 --- a/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js +++ b/e2e-tests/cypress/tests/integration/channels/team_settings/join_closed_team_with_not_allowed_email_spec.js @@ -87,8 +87,8 @@ describe('Team Settings', () => { cy.get('#input_name').type(username); cy.get('#input_password-input').type(password); - // # Attempt to create an account by clicking on the 'Create Account' button - cy.findByText('Create Account').click(); + // # Attempt to create an account by clicking on the 'Create account' button + cy.findByText('Create account').click(); // * Assert that the expected error message from creating an account with an email not from the allowed email domain exists and is visible cy.findByText(errorMessage).should('be.visible'); diff --git a/e2e-tests/cypress/tests/support/ui/compliance_export.js b/e2e-tests/cypress/tests/support/ui/compliance_export.js index 75a9a5f74fe..9dac1d1676e 100644 --- a/e2e-tests/cypress/tests/support/ui/compliance_export.js +++ b/e2e-tests/cypress/tests/support/ui/compliance_export.js @@ -6,7 +6,7 @@ import * as TIMEOUTS from '../../fixtures/timeouts'; Cypress.Commands.add('uiEnableComplianceExport', (exportFormat = 'csv') => { // * Verify that the page is loaded cy.findByText('Enable Compliance Export:').should('be.visible'); - cy.findByText('Compliance Export time:').should('be.visible'); + cy.findByText('Compliance Export Time:').should('be.visible'); cy.findByText('Export Format:').should('be.visible'); // # Enable compliance export diff --git a/e2e-tests/cypress/tests/utils/admin_console.js b/e2e-tests/cypress/tests/utils/admin_console.js index b18c0ffc406..d990cb0c25e 100644 --- a/e2e-tests/cypress/tests/utils/admin_console.js +++ b/e2e-tests/cypress/tests/utils/admin_console.js @@ -241,7 +241,7 @@ export const adminConsoleNavigation = [ }, { type: ['team', 'e20', 'cloud_enterprise'], - header: 'Email Authentication', + header: 'Email', sidebar: 'Email', url: 'admin_console/authentication/email', }, diff --git a/webapp/Makefile b/webapp/Makefile index a01f59d0602..f2ae6d22ae9 100644 --- a/webapp/Makefile +++ b/webapp/Makefile @@ -63,6 +63,18 @@ check-types: node_modules ## Checks TS file for TypeScript confirmity npm run check-types +.PHONY: i18n-extract +i18n-extract: node_modules ## Extracts i18n messages from code to en.json + @echo Extracting i18n messages + + npm run i18n-extract + +.PHONY: i18n-extract-check +i18n-extract-check: node_modules ## Checks if en.json is in sync with code + @echo Checking i18n message sync + + npm run i18n-extract:check + .PHONY: dist dist: node_modules ## Builds all web app packages @echo Packaging Mattermost Web App diff --git a/webapp/channels/.eslintrc.json b/webapp/channels/.eslintrc.json index 793badea192..0505b4e282b 100644 --- a/webapp/channels/.eslintrc.json +++ b/webapp/channels/.eslintrc.json @@ -8,7 +8,10 @@ "no-only-tests" ], "settings": { - "import/resolver": "webpack" + "import/resolver": "webpack", + "formatjs": { + "additionalFunctionNames": ["localizeMessage", "defineMessage"] + } }, "rules": { "react/prop-types": [ @@ -32,7 +35,16 @@ "react/style-prop-object": [2, { "allow": ["Timestamp"] }], + "formatjs/enforce-default-message": 2, + "formatjs/enforce-id": 2, + "formatjs/enforce-placeholders": 2, + "formatjs/no-invalid-icu": 2, + "formatjs/no-multiple-plurals": 1, "formatjs/no-multiple-whitespaces": 2, + "formatjs/no-literal-string-in-jsx": 1, + "formatjs/prefer-formatted-message": 1, + "formatjs/no-useless-message": 1, + "formatjs/prefer-pound-in-plural": 0, "react/jsx-fragments": ["error", "syntax"] }, "overrides": [ diff --git a/webapp/channels/.gitignore b/webapp/channels/.gitignore index c1c7faa7e23..f9f49334830 100644 --- a/webapp/channels/.gitignore +++ b/webapp/channels/.gitignore @@ -24,3 +24,6 @@ Session.vim *~ .eslintcache .stylelintcache + +# i18n temporary check file +.i18n-check.tmp.json diff --git a/webapp/channels/package.json b/webapp/channels/package.json index b1ca6c63b74..746555ffa37 100644 --- a/webapp/channels/package.json +++ b/webapp/channels/package.json @@ -99,7 +99,6 @@ "@deanwhillier/jest-matchmedia-mock": "1.2.0", "@mattermost/calls-common": "0.27.0", "@mattermost/eslint-plugin": "*", - "@mattermost/mmjstool": "github:mattermost/mattermost-utilities#7b63833d208d482ba4a1c12230bb3e68dd9c5e5e", "@stylistic/stylelint-plugin": "3.1.2", "@testing-library/dom": "10.4.1", "@testing-library/jest-dom": "6.8.0", @@ -188,10 +187,8 @@ "test-ci": "cross-env TZ=Etc/UTC LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 jest --ci --maxWorkers=100% --forceExit --detectOpenHandles --logHeapUsage --coverage", "clean": "rm -rf dist node_modules .eslintcache .stylelintcache tsconfig.tsbuildinfo", "stats": "cross-env NODE_ENV=production webpack --profile --json > webpack_stats.json", - "mmjstool": "mmjstool", - "i18n-extract": "npm run mmjstool -- i18n extract-webapp --webapp-dir ./src", - "i18n-clean-empty": "npm run mmjstool -- i18n clean-empty --webapp-dir ./src", - "i18n-check-empty-src": "npm run mmjstool -- i18n check-empty-src --webapp-dir ./src", + "i18n-extract": "formatjs extract 'src/**/*.{js,jsx,ts,tsx}' --additional-function-names localizeMessage --ignore 'src/**/*.d.ts' --ignore 'src/**/*.test.{js,jsx,ts,tsx}' --out-file src/i18n/en.json --format scripts/formatter.js --id-interpolation-pattern '[sha512:contenthash:base64:6]' --preserve-whitespace", + "i18n-extract:check": "npm run i18n-extract -- --throws --out-file .i18n-check.tmp.json && diff src/i18n/en.json .i18n-check.tmp.json && rm -f .i18n-check.tmp.json || (rm -f .i18n-check.tmp.json && echo '\nen.json is out of sync with code. \nTo update: npm run i18n-extract' && exit 1)", "check-types": "tsc -b", "make-emojis": "node --experimental-json-modules build/emoji/make_emojis.mjs" } diff --git a/webapp/channels/scripts/formatter.js b/webapp/channels/scripts/formatter.js new file mode 100644 index 00000000000..c7f170a612c --- /dev/null +++ b/webapp/channels/scripts/formatter.js @@ -0,0 +1,45 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +/** + * Custom formatjs formatter matching mmjstool's behavior + * + * Based on formatjs simple formatter with case-insensitive sorting + * to match mmjstool's sortJson({ignoreCase: true}) + */ + +/** + * Format function - extract defaultMessage from message objects + * Same as formatjs simple formatter + */ +module.exports.format = (msgs) => { + return Object.keys(msgs).reduce((all, k) => { + all[k] = msgs[k].defaultMessage; + return all; + }, {}); +}; + +/** + * Compile function - pass through (identity) + * Same as formatjs simple formatter + */ +module.exports.compile = (msgs) => msgs; + +/** + * Custom comparator for case-insensitive alphabetical sorting + * with underscore before dot (to match existing en.json ordering) + */ +module.exports.compareMessages = (el1, el2) => { + // Normalize keys: replace _ with a character that sorts before . + // Use \x00 (null char) which sorts before all printable characters + const key1 = el1.key.toLowerCase().replace(/_/g, '\x00'); + const key2 = el2.key.toLowerCase().replace(/_/g, '\x00'); + + if (key1 < key2) { + return -1; + } + if (key1 > key2) { + return 1; + } + return 0; +}; diff --git a/webapp/channels/src/actions/apps.ts b/webapp/channels/src/actions/apps.ts index 1ebf45504fd..bd2b495cfa5 100644 --- a/webapp/channels/src/actions/apps.ts +++ b/webapp/channels/src/actions/apps.ts @@ -1,6 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import type {IntlShape} from 'react-intl'; import type {AnyAction} from 'redux'; import type {AppCallResponse, AppForm, AppCallRequest, AppContext, AppBinding} from '@mattermost/types/apps'; @@ -76,7 +77,7 @@ export function handleBindingClick(binding: AppBinding, context: Ap }; } -export function doAppSubmit(inCall: AppCallRequest, intl: any): ThunkActionFunc>> { +export function doAppSubmit(inCall: AppCallRequest, intl: IntlShape): ThunkActionFunc>> { return async () => { try { const call: AppCallRequest = { @@ -98,7 +99,7 @@ export function doAppSubmit(inCall: AppCallRequest, intl: any): Thu if (!res.form?.submit) { const errMsg = intl.formatMessage({ id: 'apps.error.responses.form.no_form', - defaultMessage: 'Response type is `form`, but no valid form was included in response.', + defaultMessage: 'Response type is `form`, but no form was included in response.', }); return {error: makeCallErrorResponse(errMsg)}; } @@ -153,7 +154,7 @@ export function doAppFetchForm(call: AppCallRequest, intl: any): Th if (!res.form?.submit) { const errMsg = intl.formatMessage({ id: 'apps.error.responses.form.no_form', - defaultMessage: 'Response type is `form`, but no valid form was included in response.', + defaultMessage: 'Response type is `form`, but no form was included in response.', }); return {error: makeCallErrorResponse(errMsg)}; } diff --git a/webapp/channels/src/actions/command.test.js b/webapp/channels/src/actions/command.test.js index 2aa719a0f15..17111484722 100644 --- a/webapp/channels/src/actions/command.test.js +++ b/webapp/channels/src/actions/command.test.js @@ -168,7 +168,7 @@ describe('executeCommand', () => { expect(result).toEqual({ error: { - message: 'Keyboard shortcuts are not supported on your device', + message: 'Keyboard shortcuts are not supported on your device.', }, }); }); diff --git a/webapp/channels/src/actions/command.ts b/webapp/channels/src/actions/command.ts index 446ebcea2df..54a7c4b4d5d 100644 --- a/webapp/channels/src/actions/command.ts +++ b/webapp/channels/src/actions/command.ts @@ -25,14 +25,14 @@ import KeyboardShortcutsModal from 'components/keyboard_shortcuts/keyboard_short import LeaveChannelModal from 'components/leave_channel_modal'; import MarketplaceModal from 'components/plugin_marketplace/marketplace_modal'; import {AppCommandParser} from 'components/suggestion/command_provider/app_command_parser/app_command_parser'; -import {intlShim} from 'components/suggestion/command_provider/app_command_parser/app_command_parser_dependencies'; import UserSettingsModal from 'components/user_settings/modal'; import {getHistory} from 'utils/browser_history'; import {Constants, ModalIdentifiers} from 'utils/constants'; +import {getIntl} from 'utils/i18n'; import {isUrlSafe, getSiteURL} from 'utils/url'; import * as UserAgent from 'utils/user_agent'; -import {localizeMessage, getUserIdFromChannelName} from 'utils/utils'; +import {getUserIdFromChannelName} from 'utils/utils'; import type {ActionFuncAsync} from 'types/store'; @@ -47,6 +47,7 @@ export type ExecuteCommandReturnType = { export function executeCommand(message: string, args: CommandArgs): ActionFuncAsync { return async (dispatch, getState) => { + const intl = getIntl(); const state = getState(); let msg = message; @@ -64,7 +65,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs return {data: {frontendHandled: true}}; case '/shortcuts': if (UserAgent.isMobile()) { - const error = {message: localizeMessage({id: 'create_post.shortcutsNotSupported', defaultMessage: 'Keyboard shortcuts are not supported on your device'})}; + const error = {message: intl.formatMessage({id: 'create_post.shortcutsNotSupported', defaultMessage: 'Keyboard shortcuts are not supported on your device.'})}; return {error}; } @@ -118,12 +119,12 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs case '/marketplace': // check if user has permissions to access the read plugins if (!haveICurrentTeamPermission(state, Permissions.SYSCONSOLE_WRITE_PLUGINS)) { - return {error: {message: localizeMessage({id: 'marketplace_command.no_permission', defaultMessage: 'You do not have the appropriate permissions to access the marketplace.'})}}; + return {error: {message: intl.formatMessage({id: 'marketplace_command.no_permission', defaultMessage: 'You do not have the appropriate permissions to access the marketplace.'})}}; } // check config to see if marketplace is enabled if (!isMarketplaceEnabled(state)) { - return {error: {message: localizeMessage({id: 'marketplace_command.disabled', defaultMessage: 'The marketplace is disabled. Please contact your System Administrator for details.'})}}; + return {error: {message: intl.formatMessage({id: 'marketplace_command.disabled', defaultMessage: 'The marketplace is disabled. Please contact your System Administrator for details.'})}}; } dispatch(openModal({modalId: ModalIdentifiers.PLUGIN_MARKETPLACE, dialogType: MarketplaceModal})); @@ -139,7 +140,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs const createErrorMessage = (errMessage: string) => { return {error: {message: errMessage}}; }; - const parser = new AppCommandParser({dispatch, getState: getGlobalState} as any, intlShim, args.channel_id, args.team_id, args.root_id); + const parser = new AppCommandParser({dispatch, getState: getGlobalState} as any, intl, args.channel_id, args.team_id, args.root_id); if (parser.isAppCommand(msg)) { try { const {creq, errorMessage} = await parser.composeCommandSubmitCall(msg); @@ -147,11 +148,11 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs return createErrorMessage(errorMessage!); } - const res = await dispatch(doAppSubmit(creq, intlShim)); + const res = await dispatch(doAppSubmit(creq, intl)); if (res.error) { const errorResponse = res.error; - return createErrorMessage(errorResponse.text || intlShim.formatMessage({ + return createErrorMessage(errorResponse.text || intl.formatMessage({ id: 'apps.error.unknown', defaultMessage: 'Unknown error occurred.', })); @@ -172,7 +173,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs case AppCallResponseTypes.NAVIGATE: return {data: {appResponse: callResp}}; default: - return createErrorMessage(intlShim.formatMessage( + return createErrorMessage(intl.formatMessage( { id: 'apps.error.responses.unknown_type', defaultMessage: 'App response type not supported. Response type: {type}.', @@ -183,7 +184,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs )); } } catch (err: any) { - const message = err.message || intlShim.formatMessage({ + const message = err.message || intl.formatMessage({ id: 'apps.error.unknown', defaultMessage: 'Unknown error occurred.', }); diff --git a/webapp/channels/src/actions/invite_actions.ts b/webapp/channels/src/actions/invite_actions.ts index 669c74fdb3a..5d97852aea6 100644 --- a/webapp/channels/src/actions/invite_actions.ts +++ b/webapp/channels/src/actions/invite_actions.ts @@ -121,6 +121,7 @@ export function sendMembersInvites(teamId: string, users: UserProfile[], emails: email, reason: defineMessage({ id: 'admin.environment.smtp.smtpFailure', + // eslint-disable-next-line formatjs/enforce-placeholders -- a placeholder provided via messageWithLink when path is set defaultMessage: 'SMTP is not configured in System Console. Can be configured here.', }), path: ConsolePages.SMTP, @@ -229,6 +230,7 @@ export async function sendGuestInviteForUser( user, reason: defineMessage({ id: 'invite.guests.new-member', + // eslint-disable-next-line formatjs/enforce-placeholders -- count provided via values property, consumed by FormattedMessage in result_table defaultMessage: 'This guest has been added to the team and {count, plural, one {channel} other {channels}}.', values: { count: channels.length, @@ -301,6 +303,7 @@ export function sendGuestsInvites( email: res.email, reason: defineMessage({ id: 'admin.environment.smtp.smtpFailure', + // eslint-disable-next-line formatjs/enforce-placeholders -- a placeholder provided via messageWithLink when path is set defaultMessage: 'SMTP is not configured in System Console. Can be configured here.', }), path: ConsolePages.SMTP, @@ -445,6 +448,7 @@ export function sendMembersInvitesToChannels( email, reason: defineMessage({ id: 'admin.environment.smtp.smtpFailure', + // eslint-disable-next-line formatjs/enforce-placeholders -- a placeholder provided via messageWithLink when path is set defaultMessage: 'SMTP is not configured in System Console. Can be configured here.', }), path: ConsolePages.SMTP, diff --git a/webapp/channels/src/actions/marketplace.ts b/webapp/channels/src/actions/marketplace.ts index 234c6b8bc29..1ad62d948b3 100644 --- a/webapp/channels/src/actions/marketplace.ts +++ b/webapp/channels/src/actions/marketplace.ts @@ -12,11 +12,11 @@ import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getFilter, getPlugin} from 'selectors/views/marketplace'; -import {intlShim} from 'components/suggestion/command_provider/app_command_parser/app_command_parser_dependencies'; import type {DoAppCallResult} from 'components/suggestion/command_provider/app_command_parser/app_command_parser_dependencies'; import {createCallContext, createCallRequest} from 'utils/apps'; import {ActionTypes} from 'utils/constants'; +import {getIntl} from 'utils/i18n'; import type {ActionFuncAsync, ThunkActionFunc} from 'types/store'; @@ -125,6 +125,7 @@ export function installPlugin(id: string): ThunkActionFunc { // On success, it also requests the current state of the apps to reflect the newly installed app. export function installApp(id: string): ThunkActionFunc> { return async (dispatch, getState) => { + const intl = getIntl(); dispatch({ type: ActionTypes.INSTALLING_MARKETPLACE_ITEM, id, @@ -155,7 +156,7 @@ export function installApp(id: string): ThunkActionFunc> { const creq = createCallRequest(call, context, expand, values); - const res = await dispatch(doAppSubmit(creq, intlShim)) as DoAppCallResult; + const res = await dispatch(doAppSubmit(creq, intl)) as DoAppCallResult; if (res.error) { const errorResponse = res.error; diff --git a/webapp/channels/src/actions/notification_actions.tsx b/webapp/channels/src/actions/notification_actions.tsx index 9dd7d1a78a5..f883152c717 100644 --- a/webapp/channels/src/actions/notification_actions.tsx +++ b/webapp/channels/src/actions/notification_actions.tsx @@ -190,7 +190,7 @@ const getNotificationTitle = (channel: Pick, m } if (isCrtReply) { - title = Utils.localizeAndFormatMessage({id: 'notification.crt', defaultMessage: 'Reply in {title}'}, {title}); + title = Utils.localizeMessage({id: 'notification.crt', defaultMessage: 'Reply in {title}'}, {title}); } return title; diff --git a/webapp/channels/src/components/about_build_modal/about_build_modal.tsx b/webapp/channels/src/components/about_build_modal/about_build_modal.tsx index e5082e774e4..bcdf4440379 100644 --- a/webapp/channels/src/components/about_build_modal/about_build_modal.tsx +++ b/webapp/channels/src/components/about_build_modal/about_build_modal.tsx @@ -136,16 +136,20 @@ export default function AboutBuildModal(props: Props) { learnMore = (
+ {'mattermost.com'} + + ), + }} /> - - {'mattermost.com'} -
); licensee = ( @@ -162,14 +166,18 @@ export default function AboutBuildModal(props: Props) {
+ {'mattermost.com'} + + ), + }} /> - - {'mattermost.com'} -
); } diff --git a/webapp/channels/src/components/access_problem/index.tsx b/webapp/channels/src/components/access_problem/index.tsx index bcb6f1c8a3c..cdc6c078834 100644 --- a/webapp/channels/src/components/access_problem/index.tsx +++ b/webapp/channels/src/components/access_problem/index.tsx @@ -36,10 +36,10 @@ const AccessProblem = ({
- {formatMessage({id: 'login.contact_admin.title'})} + {formatMessage({id: 'login.contact_admin.title', defaultMessage: 'Contact your workspace admin'})}
- {formatMessage({id: 'login.contact_admin.detail'})} + {formatMessage({id: 'login.contact_admin.detail', defaultMessage: "To access your team's workspace, contact your workspace admin. If you've been invited already, check your email inbox for a Mattermost workspace invite."})}
); diff --git a/webapp/channels/src/components/actions_menu/actions_menu_tutorial_tip.tsx b/webapp/channels/src/components/actions_menu/actions_menu_tutorial_tip.tsx index c112024f1d8..47a6af7510b 100644 --- a/webapp/channels/src/components/actions_menu/actions_menu_tutorial_tip.tsx +++ b/webapp/channels/src/components/actions_menu/actions_menu_tutorial_tip.tsx @@ -24,7 +24,7 @@ const title = ( const screen = ( ); const nextBtn = ( diff --git a/webapp/channels/src/components/add_users_to_group_modal/add_users_to_group_modal.tsx b/webapp/channels/src/components/add_users_to_group_modal/add_users_to_group_modal.tsx index e3b1c34802a..bbf17ea818a 100644 --- a/webapp/channels/src/components/add_users_to_group_modal/add_users_to_group_modal.tsx +++ b/webapp/channels/src/components/add_users_to_group_modal/add_users_to_group_modal.tsx @@ -118,6 +118,7 @@ const AddUsersToGroupModal = (props: Props) => { > diff --git a/webapp/channels/src/components/add_users_to_team_modal/__snapshots__/add_users_to_team_modal.test.tsx.snap b/webapp/channels/src/components/add_users_to_team_modal/__snapshots__/add_users_to_team_modal.test.tsx.snap index f5102a89c97..3ce013d2b4c 100644 --- a/webapp/channels/src/components/add_users_to_team_modal/__snapshots__/add_users_to_team_modal.test.tsx.snap +++ b/webapp/channels/src/components/add_users_to_team_modal/__snapshots__/add_users_to_team_modal.test.tsx.snap @@ -221,7 +221,7 @@ exports[`components/admin_console/add_users_to_team_modal/AddUsersToTeamModal sh perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } @@ -463,7 +463,7 @@ exports[`components/admin_console/add_users_to_team_modal/AddUsersToTeamModal sh perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } diff --git a/webapp/channels/src/components/add_users_to_team_modal/add_users_to_team_modal.tsx b/webapp/channels/src/components/add_users_to_team_modal/add_users_to_team_modal.tsx index 52395437422..5152c12dc37 100644 --- a/webapp/channels/src/components/add_users_to_team_modal/add_users_to_team_modal.tsx +++ b/webapp/channels/src/components/add_users_to_team_modal/add_users_to_team_modal.tsx @@ -262,7 +262,7 @@ export class AddUsersToTeamModal extends React.PureComponent { buttonSubmitLoadingText={buttonSubmitLoadingText} saving={this.state.saving} loading={this.state.loading} - placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search and add members'})} + placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search for people'})} /> diff --git a/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap index a10fd55962c..39786163195 100644 --- a/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/__snapshots__/database_settings.test.tsx.snap @@ -11,7 +11,7 @@ exports[`components/DatabaseSettings should match snapshot 1`] = ` > diff --git a/webapp/channels/src/components/admin_console/__snapshots__/elasticsearch_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/__snapshots__/elasticsearch_settings.test.tsx.snap index 51a48a1e0a8..5e8b8c6a84a 100644 --- a/webapp/channels/src/components/admin_console/__snapshots__/elasticsearch_settings.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/__snapshots__/elasticsearch_settings.test.tsx.snap @@ -335,6 +335,7 @@ exports[`components/ElasticSearchSettings should match snapshot, disabled 1`] = helpText={ } @@ -827,6 +828,7 @@ exports[`components/ElasticSearchSettings should match snapshot, enabled 1`] = ` helpText={ } diff --git a/webapp/channels/src/components/admin_console/__snapshots__/message_export_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/__snapshots__/message_export_settings.test.tsx.snap index ba2d74dd9c7..8bc6cb6cd24 100644 --- a/webapp/channels/src/components/admin_console/__snapshots__/message_export_settings.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/__snapshots__/message_export_settings.test.tsx.snap @@ -108,7 +108,7 @@ exports[`components/MessageExportSettings should match snapshot, disabled, actia "value": "csv", }, Object { - "text": "GlobalRelay EML", + "text": "Global Relay EML", "value": "globalrelay", }, ] @@ -270,7 +270,7 @@ exports[`components/MessageExportSettings should match snapshot, disabled, globa "value": "csv", }, Object { - "text": "GlobalRelay EML", + "text": "Global Relay EML", "value": "globalrelay", }, ] @@ -546,7 +546,7 @@ exports[`components/MessageExportSettings should match snapshot, enabled, actian "value": "csv", }, Object { - "text": "GlobalRelay EML", + "text": "Global Relay EML", "value": "globalrelay", }, ] @@ -708,7 +708,7 @@ exports[`components/MessageExportSettings should match snapshot, enabled, global "value": "csv", }, Object { - "text": "GlobalRelay EML", + "text": "Global Relay EML", "value": "globalrelay", }, ] diff --git a/webapp/channels/src/components/admin_console/__snapshots__/push_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/__snapshots__/push_settings.test.tsx.snap index 2faf80fd9c9..edec14c2fe9 100644 --- a/webapp/channels/src/components/admin_console/__snapshots__/push_settings.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/__snapshots__/push_settings.test.tsx.snap @@ -148,14 +148,14 @@ exports[`components/PushSettings should match snapshot, licensed 1`] = ` } id="maxNotificationsPerChannel" label={ } @@ -279,14 +279,14 @@ exports[`components/PushSettings should match snapshot, unlicensed 1`] = ` } id="maxNotificationsPerChannel" label={ } diff --git a/webapp/channels/src/components/admin_console/access_control/modals/job_details/searchable_sync_job_channel_list.tsx b/webapp/channels/src/components/admin_console/access_control/modals/job_details/searchable_sync_job_channel_list.tsx index aea9ffaa976..3469382aecb 100644 --- a/webapp/channels/src/components/admin_console/access_control/modals/job_details/searchable_sync_job_channel_list.tsx +++ b/webapp/channels/src/components/admin_console/access_control/modals/job_details/searchable_sync_job_channel_list.tsx @@ -173,7 +173,7 @@ const SearchableSyncJobChannelList = (props: Props) => { ); @@ -254,7 +254,7 @@ const SearchableSyncJobChannelList = (props: Props) => { clearable={true} onClear={handleClear} value={channelSearchValue} - aria-label={props.intl.formatMessage({id: 'filtered_channels_list.search', defaultMessage: 'Search Channels'})} + aria-label={props.intl.formatMessage({id: 'filtered_channels_list.search', defaultMessage: 'Search channels'})} /> ); @@ -306,7 +306,7 @@ const messages = defineMessages({ }, noMore: { id: 'more_channels.noMore', - defaultMessage: 'No results for {text}', + defaultMessage: 'No results for "{text}"', }, }); diff --git a/webapp/channels/src/components/admin_console/admin_definition.tsx b/webapp/channels/src/components/admin_console/admin_definition.tsx index 15e554cb555..1690dc7c9ce 100644 --- a/webapp/channels/src/components/admin_console/admin_definition.tsx +++ b/webapp/channels/src/components/admin_console/admin_definition.tsx @@ -680,12 +680,12 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'AccessControlSettings.EnableAttributeBasedAccessControl', label: defineMessage({id: 'admin.accesscontrol.enableTitle', defaultMessage: 'Allow attribute based access controls on this server'}), - help_text: defineMessage({id: 'admin.accesscontrol.enableDesc', defaultMessage: 'Allow access restrictions based on user attributes using custom access policies. To effectively use this feature, you must define user attributes in the {userAttributes} section.'}), + help_text: defineMessage({id: 'admin.accesscontrol.enableDesc', defaultMessage: 'Allow access restrictions based on user attributes using custom access policies. To effectively use this feature, you must define user attributes in the {userAttributes} section.'}), // eslint-disable-line formatjs/enforce-placeholders -- userAttributes provided via help_text_values help_text_values: { userAttributes: ( @@ -736,7 +736,7 @@ const AdminDefinition: AdminDefinitionType = { ), schema: { id: 'AttributeBasedAccessControl', - name: defineMessage({id: 'admin.accesscontrol.title', defaultMessage: 'Attribute-Based Access (Beta)'}), + name: defineMessage({id: 'admin.accesscontrol.title', defaultMessage: 'Attribute-Based Access'}), settings: [ { type: 'custom', @@ -773,14 +773,14 @@ const AdminDefinition: AdminDefinitionType = { settings: [ { type: 'banner', - label: defineMessage({id: 'admin.rate.noteDescription', defaultMessage: 'Changing properties in this section will require a server restart before taking effect.'}), + label: defineMessage({id: 'admin.info_banner.restart_required.desc', defaultMessage: 'Changing properties in this section will require a server restart before taking effect.'}), banner_type: 'info', }, { type: 'text', key: 'ServiceSettings.SiteURL', label: defineMessage({id: 'admin.service.siteURL', defaultMessage: 'Site URL:'}), - help_text: defineMessage({id: 'admin.service.siteURLDescription', defaultMessage: 'The URL that users will use to access Mattermost. Standard ports, such as 80 and 443, can be omitted, but non-standard ports are required. For example: http://example.com:8065. This setting is required. Mattermost may be hosted at a subpath. For example: http://example.com:8065/company/mattermost. A restart is required before the server will work correctly.'}), + help_text: defineMessage({id: 'admin.service.siteURLDescription', defaultMessage: 'The URL that users will use to access Mattermost. Standard ports, such as 80 and 443, can be omitted, but non-standard ports are required. For example: http://example.com:8065. This setting is required.\n \nMattermost may be hosted at a subpath. For example: http://example.com:8065/company/mattermost. A restart is required before the server will work correctly.'}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, placeholder: defineMessage({id: 'admin.service.siteURLExample', defaultMessage: 'E.g.: "http://example.com:8065"'}), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.WEB_SERVER)), @@ -791,7 +791,7 @@ const AdminDefinition: AdminDefinitionType = { action: testSiteURL, label: defineMessage({id: 'admin.service.testSiteURL', defaultMessage: 'Test Live URL'}), loading: defineMessage({id: 'admin.service.testSiteURLTesting', defaultMessage: 'Testing...'}), - error_message: defineMessage({id: 'admin.service.testSiteURLFail', defaultMessage: 'Test unsuccessful: {error}'}), + error_message: defineMessage({id: 'admin.service.testSiteURLFail', defaultMessage: 'Test unsuccessful: {error}'}), // eslint-disable-line formatjs/enforce-placeholders -- error provided at runtime success_message: defineMessage({id: 'admin.service.testSiteURLSuccess', defaultMessage: 'Test successful. This is a valid URL.'}), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.WEB_SERVER)), }, @@ -808,7 +808,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'ServiceSettings.Forward80To443', label: defineMessage({id: 'admin.service.forward80To443', defaultMessage: 'Forward port 80 to 443:'}), help_text: defineMessage({id: 'admin.service.forward80To443Description', defaultMessage: 'Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server.'}), - disabled_help_text: defineMessage({id: 'admin.service.forward80To443Description.disabled', defaultMessage: 'Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server. This setting cannot be enabled until your server is [listening](#ServiceSettings.ListenAddress) on port 443.'}), + disabled_help_text: defineMessage({id: 'admin.service.forward80To443Description.disabled', defaultMessage: 'Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server.\n \nThis setting cannot be enabled until your server is [listening](#ServiceSettings.ListenAddress) on port 443.'}), // eslint-disable-line formatjs/no-multiple-whitespaces disabled_help_text_markdown: true, isDisabled: it.any( it.cloudLicensed, @@ -858,7 +858,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'ServiceSettings.UseLetsEncrypt', label: defineMessage({id: 'admin.service.useLetsEncrypt', defaultMessage: 'Use Let\'s Encrypt:'}), help_text: defineMessage({id: 'admin.service.useLetsEncryptDescription', defaultMessage: 'Enable the automatic retrieval of certificates from Let\'s Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.'}), - disabled_help_text: defineMessage({id: 'admin.service.useLetsEncryptDescription.disabled', defaultMessage: "Enable the automatic retrieval of certificates from Let's Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains. This setting cannot be enabled unless the [Forward port 80 to 443](#ServiceSettings.Forward80To443) setting is set to true."}), + disabled_help_text: defineMessage({id: 'admin.service.useLetsEncryptDescription.disabled', defaultMessage: "Enable the automatic retrieval of certificates from Let's Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.\n \nThis setting cannot be enabled unless the [Forward port 80 to 443](#ServiceSettings.Forward80To443) setting is set to true."}), // eslint-disable-line formatjs/no-multiple-whitespaces disabled_help_text_markdown: true, isDisabled: it.any( it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.WEB_SERVER)), @@ -928,7 +928,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'ServiceSettings.ManagedResourcePaths', label: defineMessage({id: 'admin.service.managedResourcePaths', defaultMessage: 'Managed Resource Paths:'}), - help_text: defineMessage({id: 'admin.service.managedResourcePathsDescription', defaultMessage: 'A comma-separated list of paths on the Mattermost server that are managed by another service. See here for more information.'}), + help_text: defineMessage({id: 'admin.service.managedResourcePathsDescription', defaultMessage: 'A comma-separated list of paths on the Mattermost server that are managed by another service. See here for more information.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -947,7 +947,7 @@ const AdminDefinition: AdminDefinitionType = { action: reloadConfig, key: 'ReloadConfigButton', label: defineMessage({id: 'admin.reload.button', defaultMessage: 'Reload Configuration From Disk'}), - help_text: defineMessage({id: 'admin.reload.reloadDescription', defaultMessage: 'Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating "config.json" to the new desired configuration and using the {featureName} feature to load the new settings while the server is running. The administrator should then use the {recycleDatabaseConnections} feature to recycle the database connections based on the new settings.'}), + help_text: defineMessage({id: 'admin.reload.reloadDescription', defaultMessage: 'Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating "config.json" to the new desired configuration and using the {featureName} feature to load the new settings while the server is running. The administrator should then use the {recycleDatabaseConnections} feature to recycle the database connections based on the new settings.'}), // eslint-disable-line formatjs/enforce-placeholders -- featureName, recycleDatabaseConnections provided via help_text_values help_text_values: { featureName: ( @@ -968,7 +968,7 @@ const AdminDefinition: AdminDefinitionType = { ), }, - error_message: defineMessage({id: 'admin.reload.reloadFail', defaultMessage: 'Reload unsuccessful: {error}'}), + error_message: defineMessage({id: 'admin.reload.reloadFail', defaultMessage: 'Reload unsuccessful: {error}'}), // eslint-disable-line formatjs/enforce-placeholders -- error provided at runtime isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.WEB_SERVER)), }, { @@ -977,7 +977,7 @@ const AdminDefinition: AdminDefinitionType = { action: invalidateAllCaches, label: defineMessage({id: 'admin.purge.button', defaultMessage: 'Purge All Caches'}), help_text: defineMessage({id: 'admin.purge.purgeDescription', defaultMessage: 'This will purge all the in-memory caches for things like sessions, accounts, channels, etc. Deployments using High Availability will attempt to purge all the servers in the cluster. Purging the caches may adversely impact performance.'}), - error_message: defineMessage({id: 'admin.purge.purgeFail', defaultMessage: 'Purging unsuccessful: {error}'}), + error_message: defineMessage({id: 'admin.purge.purgeFail', defaultMessage: 'Purging unsuccessful: {error}'}), // eslint-disable-line formatjs/enforce-placeholders -- error provided at runtime isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.WEB_SERVER)), }, ], @@ -1028,7 +1028,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'dropdown', key: 'FileSettings.DriverName', label: defineMessage({id: 'admin.image.storeTitle', defaultMessage: 'File Storage System:'}), - help_text: defineMessage({id: 'admin.image.storeDescription', defaultMessage: 'Storage system where files and image attachments are saved. Selecting "Amazon S3" enables fields to enter your Amazon credentials and bucket details. Selecting "Local File System" enables the field to specify a local file directory.'}), + help_text: defineMessage({id: 'admin.image.storeDescription', defaultMessage: 'Storage system where files and image attachments are saved.\n \nSelecting "Amazon S3" enables fields to enter your Amazon credentials and bucket details.\n \nSelecting "Local File System" enables the field to specify a local file directory.'}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, options: [ { @@ -1067,7 +1067,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'FileSettings.ExtractContent', label: defineMessage({id: 'admin.image.extractContentTitle', defaultMessage: 'Enable document search by content:'}), - help_text: defineMessage({id: 'admin.image.extractContentDescription', defaultMessage: 'When enabled, supported document types are searchable by their content. Search results for existing documents may be incomplete until a data migration is executed.'}), + help_text: defineMessage({id: 'admin.image.extractContentDescription', defaultMessage: 'When enabled, supported document types are searchable by their content. Search results for existing documents may be incomplete until a data migration is executed.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -1087,7 +1087,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'FileSettings.ArchiveRecursion', label: defineMessage({id: 'admin.image.archiveRecursionTitle', defaultMessage: 'Enable searching content of documents within ZIP files:'}), - help_text: defineMessage({id: 'admin.image.archiveRecursionDescription', defaultMessage: 'When enabled, content of documents within ZIP files will be returned in search results. This may have an impact on server performance for large files. '}), + help_text: defineMessage({id: 'admin.image.archiveRecursionDescription', defaultMessage: 'When enabled, content of documents within ZIP files will be returned in search results. This may have an impact on server performance for large files.'}), isDisabled: it.any( it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)), it.configIsFalse('FileSettings', 'ExtractContent'), @@ -1109,7 +1109,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'FileSettings.AmazonS3PathPrefix', label: defineMessage({id: 'admin.image.amazonS3PathPrefixTitle', defaultMessage: 'Amazon S3 Path Prefix:'}), help_text: defineMessage({id: 'admin.image.amazonS3PathPrefixDescription', defaultMessage: 'Prefix you selected for your S3 bucket in AWS.'}), - placeholder: defineMessage({id: 'admin.image.amazonS3PathPrefixExample', defaultMessage: 'E.g.: "subdir1/" or you can leave it .'}), + placeholder: defineMessage({id: 'admin.image.amazonS3PathPrefixExample', defaultMessage: 'E.g.: "subdir1" or you can leave it empty.'}), isDisabled: it.any( it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)), it.not(it.stateEquals('FileSettings.DriverName', FILE_STORAGE_DRIVER_S3)), @@ -1130,7 +1130,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'FileSettings.AmazonS3AccessKeyId', label: defineMessage({id: 'admin.image.amazonS3IdTitle', defaultMessage: 'Amazon S3 Access Key ID:'}), - help_text: defineMessage({id: 'admin.image.amazonS3IdDescription', defaultMessage: '(Optional) Only required if you do not want to authenticate to S3 using an IAM role. Enter the Access Key ID provided by your Amazon EC2 administrator.'}), + help_text: defineMessage({id: 'admin.image.amazonS3IdDescription', defaultMessage: '(Optional) Only required if you do not want to authenticate to S3 using an IAM role. Enter the Access Key ID provided by your Amazon EC2 administrator.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.image.amazonS3SSEDescription', defaultMessage: 'When true, encrypt files in Amazon S3 using server-side encryption with Amazon S3-managed keys. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values help_text_values: { link: (msg: string) => ( IAM role. Enter the Access Key ID provided by your Amazon EC2 administrator.'}), + help_text: defineMessage({id: 'admin.image.amazonS3IdDescription', defaultMessage: '(Optional) Only required if you do not want to authenticate to S3 using an IAM role. Enter the Access Key ID provided by your Amazon EC2 administrator.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.image.amazonS3SSEDescription', defaultMessage: 'When true, encrypt files in Amazon S3 using server-side encryption with Amazon S3-managed keys. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.image.proxyTypeDescription', defaultMessage: 'Configure an image proxy to load all Markdown images through a proxy. The image proxy prevents users from making insecure image requests, provides caching for increased performance, and automates image adjustments such as resizing. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( @@ -1925,7 +1925,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'LogSettings.EnableDiagnostics', label: defineMessage({id: 'admin.log.enableDiagnostics', defaultMessage: 'Enable Diagnostics and Error Reporting:'}), - help_text: defineMessage({id: 'admin.log.enableDiagnosticsDescription', defaultMessage: 'Enable this feature to improve the quality and performance of Mattermost by sending error reporting and diagnostic information to Mattermost, Inc. Read our privacy policy to learn more.'}), + help_text: defineMessage({id: 'admin.log.enableDiagnosticsDescription', defaultMessage: 'Enable this feature to improve the quality and performance of Mattermost by sending error reporting and diagnostic information to Mattermost, Inc. Read our privacy policy to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -1946,7 +1946,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'longtext', key: 'LogSettings.AdvancedLoggingJSON', label: defineMessage({id: 'admin.log.AdvancedLoggingJSONTitle', defaultMessage: 'Advanced Logging:'}), - help_text: defineMessage({id: 'admin.log.AdvancedLoggingJSONDescription', defaultMessage: 'The JSON configuration for Advanced Logging. Please see documentation to learn more about Advanced Logging and the JSON format it uses.'}), + help_text: defineMessage({id: 'admin.log.AdvancedLoggingJSONDescription', defaultMessage: 'The JSON configuration for Advanced Logging. Please see documentation to learn more about Advanced Logging and the JSON format it uses.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -2014,7 +2014,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'MetricsSettings.Enable', label: defineMessage({id: 'admin.metrics.enableTitle', defaultMessage: 'Enable Performance Monitoring:'}), - help_text: defineMessage({id: 'admin.metrics.enableDescription', defaultMessage: 'When true, Mattermost will enable performance monitoring collection and profiling. Please see documentation to learn more about configuring performance monitoring for Mattermost.'}), + help_text: defineMessage({id: 'admin.metrics.enableDescription', defaultMessage: 'When true, Mattermost will enable performance monitoring collection and profiling. Please see documentation to learn more about configuring performance monitoring for Mattermost.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -2032,7 +2032,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'MetricsSettings.EnableClientMetrics', label: defineMessage({id: 'admin.metrics.enableClientMetricsTitle', defaultMessage: 'Enable Client Performance Monitoring:'}), - help_text: defineMessage({id: 'admin.metrics.enableClientMetricsDescription', defaultMessage: 'When true, Mattermost will enable performance monitoring collection for web and desktop app users. Please see documentation to learn more about configuring performance monitoring for Mattermost.'}), + help_text: defineMessage({id: 'admin.metrics.enableClientMetricsDescription', defaultMessage: 'When true, Mattermost will enable performance monitoring collection for web and desktop app users. Please see documentation to learn more about configuring performance monitoring for Mattermost.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -2107,7 +2107,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'ServiceSettings.AllowedUntrustedInternalConnections', label: defineMessage({id: 'admin.service.internalConnectionsTitle', defaultMessage: 'Allow untrusted internal connections to: '}), placeholder: defineMessage({id: 'admin.service.internalConnectionsEx', defaultMessage: 'webhooks.internal.example.com 127.0.0.1 10.0.16.0/28'}), - help_text: defineMessage({id: 'admin.service.internalConnectionsDesc', defaultMessage: 'A whitelist of local network addresses that can be requested by the Mattermost server on behalf of a client. Care should be used when configuring this setting to prevent unintended access to your local network. See documentation to learn more. Changing this requires a server restart before taking effect.'}), + help_text: defineMessage({id: 'admin.service.internalConnectionsDesc', defaultMessage: 'A whitelist of local network addresses that can be requested by the Mattermost server on behalf of a client. Care should be used when configuring this setting to prevent unintended access to your local network. See documentation to learn more. Changing this requires a server restart before taking effect.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( @@ -2374,7 +2374,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'SupportSettings.TermsOfServiceLink', label: defineMessage({id: 'admin.support.termsTitle', defaultMessage: 'Terms of Use Link:'}), - help_text: defineMessage({id: 'admin.support.termsDesc', defaultMessage: 'Link to the terms under which users may use your online service. By default, this includes the "Mattermost Conditions of Use (End Users)" explaining the terms under which Mattermost software is provided to end users. If you change the default link to add your own terms for using the service you provide, your new terms must include a link to the default terms so end users are aware of the Mattermost Conditions of Use (End User) for Mattermost software.'}), + help_text: defineMessage({id: 'admin.support.termsDesc', defaultMessage: 'Link to the terms under which users may use your online service. By default, this includes the "Mattermost Acceptable Use Policy" explaining the terms under which Mattermost software is provided to end users. If you change the default link to add your own terms for using the service you provide, your new terms must include a link to the default terms so end users are aware of the Mattermost Acceptable Use Policy for Mattermost software.'}), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.CUSTOMIZATION)), isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'), }, @@ -2603,7 +2603,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'dropdown', key: 'TeamSettings.RestrictDirectMessage', label: defineMessage({id: 'admin.team.restrictDirectMessage', defaultMessage: 'Enable users to open Direct Message channels with:'}), - help_text: defineMessage({id: 'admin.team.restrictDirectMessageDesc', defaultMessage: '"Any user on the Mattermost server" enables users to open a Direct Message channel with any user on the server, even if they are not on any teams together. "Any member of the team" limits the ability in the Direct Messages "More" menu to only open Direct Message channels with users who are in the same team.'}), + help_text: defineMessage({id: 'admin.team.restrictDirectMessageDesc', defaultMessage: "'Any user on the Mattermost server' enables users to open a Direct Message channel with any user on the server, even if they are not on any teams together. 'Any member of the team' limits the ability in the Direct Messages 'More' menu to only open Direct Message channels with users who are in the same team."}), options: [ { value: 'any', @@ -2641,7 +2641,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'TeamSettings.LockTeammateNameDisplay', label: defineMessage({id: 'admin.lockTeammateNameDisplay', defaultMessage: 'Lock Teammate Name Display for all users: '}), - help_text: defineMessage({id: 'admin.lockTeammateNameDisplayHelpText', defaultMessage: 'When true, disables users\' ability to change settings under Account Menu > Account Settings > Display > Teammate Name Display.'}), + help_text: defineMessage({id: 'admin.lockTeammateNameDisplayHelpText', defaultMessage: "When true, disables users' ability to change settings under Settings > Display > Teammate Name Display."}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { strong: (msg: string) => {msg}, }, @@ -2756,7 +2756,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'dropdown', key: 'EmailSettings.EmailNotificationContentsType', label: defineMessage({id: 'admin.environment.notifications.contents.label', defaultMessage: 'Email Notification Contents:'}), - help_text: defineMessage({id: 'admin.environment.notifications.contents.help', defaultMessage: '**Send full message contents** - Sender name and channel are included in email notifications. **Send generic description with only sender name** - Only the name of the person who sent the message, with no information about channel name or message contents are included in email notifications. Typically used for compliance reasons if Mattermost contains confidential information and policy dictates it cannot be stored in email.'}), + help_text: defineMessage({id: 'admin.environment.notifications.contents.help', defaultMessage: '**Send full message contents** - Sender name and channel are included in email notifications.\n **Send generic description with only sender name** - Only the name of the person who sent the message, with no information about channel name or message contents are included in email notifications. Typically used for compliance reasons if Mattermost contains confidential information and policy dictates it cannot be stored in email.'}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, options: [ { @@ -2831,7 +2831,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'dropdown', key: 'EmailSettings.PushNotificationContents', label: defineMessage({id: 'admin.environment.notifications.pushContents.label', defaultMessage: 'Push Notification Contents:'}), - help_text: defineMessage({id: 'admin.environment.notifications.pushContents.help', defaultMessage: "**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents. **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents. **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple's Push Notification Service (APNS) or Google's Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an \"https\" protocol to encrypt the connection and protect confidential information sent in messages."}), + help_text: defineMessage({id: 'admin.environment.notifications.pushContents.help', defaultMessage: '**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents.\n **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents.\n **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple\'s Push Notification Service (APNS) or Google\'s Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an "https" protocol to encrypt the connection and protect confidential information sent in messages.'}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, options: [ { @@ -2854,7 +2854,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'dropdown', key: 'EmailSettings.PushNotificationContents', label: defineMessage({id: 'admin.environment.notifications.pushContents.label', defaultMessage: 'Push Notification Contents:'}), - help_text: defineMessage({id: 'admin.environment.notifications.pushContents.withIdLoaded.help', defaultMessage: "**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents. **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents. **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple's Push Notification Service (APNS) or Google's Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an \"https\" protocol to encrypt the connection and protect confidential information sent in messages. **Full message content fetched from the server on receipt** - The notification payload relayed through APNS or FCM contains no message content, instead it contains a unique message ID used to fetch message content from the server when a push notification is received by a device. If the server cannot be reached, a generic notification will be displayed."}), + help_text: defineMessage({id: 'admin.environment.notifications.pushContents.withIdLoaded.help', defaultMessage: "**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents.\n **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents.\n **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple's Push Notification Service (APNS) or Google's Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an \"https\" protocol to encrypt the connection and protect confidential information sent in messages.\n**Full message content fetched from the server on receipt** - The notification payload relayed through APNS or FCM contains no message content, instead it contains a unique message ID used to fetch message content from the server when a push notification is received by a device. If the server cannot be reached, a generic notification will be displayed."}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, options: [ { @@ -3022,7 +3022,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'dropdown', key: 'ServiceSettings.CollapsedThreads', label: defineMessage({id: 'admin.experimental.collapsedThreads.title', defaultMessage: 'Threaded Discussions'}), - help_text: defineMessage({id: 'admin.experimental.collapsedThreads.desc', defaultMessage: 'When enabled (default off), users must enable Threaded Discussions in Settings. When disabled, users cannot access Threaded Discussions. Please review our documentation for known issues and help provide feedback in our Community Channel.'}), + help_text: defineMessage({id: 'admin.experimental.collapsedThreads.desc', defaultMessage: 'When enabled (default off), users have the option to enable Threaded Discussions in Account Settings. When enabled (default on), users see Threaded Discussions by default and have the option to disable it in Account Settings. When always on, users are required to use Threaded Discussions and cannot disable it.'}), help_text_values: { linkKnownIssues: (msg: string) => ( documentation.'}), + help_text: defineMessage({id: 'admin.posts.postPriority.desc', defaultMessage: 'When enabled, users can configure a visual indicator to communicate messages that are important or urgent. Learn more about message priority in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation.'}), + help_text: defineMessage({id: 'admin.posts.persistentNotifications.desc', defaultMessage: 'When enabled, users can trigger repeating notifications for the recipients of urgent messages. Learn more about message priority and persistent notifications in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation.'}), + help_text: defineMessage({id: 'admin.posts.persistentNotificationsMaxRecipients.desc', defaultMessage: 'Configure the maximum number of recipients to which users may send persistent notifications. Learn more about message priority and persistent notifications in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation.'}), + help_text: defineMessage({id: 'admin.posts.persistentNotificationsInterval.desc', defaultMessage: 'Configure the number of minutes between repeated notifications for urgent messages send with persistent notifications. Learn more about message priority and persistent notifications in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation.'}), + help_text: defineMessage({id: 'admin.posts.persistentNotificationsMaxCount.desc', defaultMessage: 'Configure the maximum number of times users may receive persistent notifications. Learn more about message priority and persistent notifications in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation.'}), + help_text: defineMessage({id: 'admin.posts.persistentNotificationsGuests.desc', defaultMessage: 'Whether a guest is able to require persistent notifications. Learn more about message priority and persistent notifications in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation for details.'}), + help_text: defineMessage({id: 'admin.customization.enablePermalinkPreviewsDesc', defaultMessage: 'When enabled, links to Mattermost messages will generate a preview for any users that have access to the original message. Please review our documentation for details.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation for details about text formatting.'}), + help_text: defineMessage({id: 'admin.customization.enableInlineLatexDesc', defaultMessage: 'Enable rendering of inline Latex code. If false, Latex can only be rendered in a code block using syntax highlighting. Please review our documentation for details about text formatting.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Google Developers Tutorial for instructions on how to obtain a key and add YouTube Data API v3 as a service to your key.'}), + help_text: defineMessage({id: 'admin.service.googleDescription', defaultMessage: 'Set this key to enable the display of titles for embedded YouTube video previews. Without the key, YouTube previews will still be created based on hyperlinks appearing in messages or comments but they will not show the video title. View a Google Developers Tutorial for instructions on how to obtain a key and add YouTube Data API v3 as a service to your key.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Learn more about notices in our documentation.'}), + help_text: defineMessage({id: 'admin.notices.enableAdminNoticesDescription', defaultMessage: 'When enabled, System Admins will receive notices about available server upgrades and relevant system administration features. Learn more about notices in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Learn more about notices in our documentation.'}), + help_text: defineMessage({id: 'admin.notices.enableEndUserNoticesDescription', defaultMessage: 'When enabled, all users will receive notices about available client upgrades and relevant end user features to improve user experience. Learn more about notices in our documentation.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Multi-factor authentication is available for accounts with AD/LDAP or email login. If other login methods are used, MFA should be configured with the authentication provider.'}), + label: defineMessage({id: 'admin.mfa.bannerDesc', defaultMessage: 'Multi-factor authentication is available for accounts with AD/LDAP or email login. If other login methods are used, MFA should be configured with the authentication provider.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided label_values: { link: (msg: string) => ( multi-factor authentication is required for login. New users will be required to configure MFA on signup. Logged in users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.'}), + help_text: defineMessage({id: 'admin.service.enforceMfaDesc', defaultMessage: 'When true, multi-factor authentication is required for login. New users will be required to configure MFA on signup. Logged in users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -3943,7 +3931,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'SamlSettings.Enable', label: defineMessage({id: 'admin.saml.enableTitle', defaultMessage: 'Enable Login With SAML 2.0:'}), - help_text: defineMessage({id: 'admin.saml.enableDescription', defaultMessage: 'When true, Mattermost allows login using SAML 2.0. Please see documentation to learn more about configuring SAML for Mattermost.'}), + help_text: defineMessage({id: 'admin.saml.enableDescription', defaultMessage: 'When true, Mattermost allows login using SAML 2.0. Please see documentation to learn more about configuring SAML for Mattermost.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -3961,7 +3949,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'SamlSettings.EnableSyncWithLdap', label: defineMessage({id: 'admin.saml.enableSyncWithLdapTitle', defaultMessage: 'Enable Synchronizing SAML Accounts With AD/LDAP:'}), - help_text: defineMessage({id: 'admin.saml.enableSyncWithLdapDescription', defaultMessage: 'When true, Mattermost periodically synchronizes SAML user attributes, including user deactivation and removal, from AD/LDAP. Enable and configure synchronization settings at Authentication > AD/LDAP. When false, user attributes are updated from SAML during user login. See documentation to learn more.'}), + help_text: defineMessage({id: 'admin.saml.enableSyncWithLdapDescription', defaultMessage: 'When true, Mattermost periodically synchronizes SAML user attributes, including user deactivation and removal, from AD/LDAP. Enable and configure synchronization settings at Authentication > AD/LDAP. When false, user attributes are updated from SAML during user login. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Note: SAML IDs must match the LDAP IDs to prevent disabling of user accounts. Please review documentation for more information.'}), + help_text: defineMessage({id: 'admin.saml.enableSyncWithLdapIncludeAuthDescription', defaultMessage: 'When true, Mattermost will override the SAML ID attribute with the AD/LDAP ID attribute if configured or override the SAML Email attribute with the AD/LDAP Email attribute if SAML ID attribute is not present. This will allow you automatically migrate users from Email binding to ID binding to prevent creation of new users when an email address changes for a user. Moving from true to false, will remove the override from happening. Note: SAML IDs must match the LDAP IDs to prevent disabling of user accounts. Please review documentation for more information.'}), // eslint-disable-line formatjs/no-multiple-whitespaces, formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( your-mattermost-url"'}), + placeholder: defineMessage({id: 'admin.saml.assertionConsumerServiceURLEx', defaultMessage: 'E.g.: "your-mattermost-url"'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided placeholder_values: { urlChunk: (chunk: string) => `https://'<${chunk}>'/login/sso/saml`, }, @@ -4121,7 +4109,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'SamlSettings.ServiceProviderIdentifier', label: defineMessage({id: 'admin.saml.serviceProviderIdentifierTitle', defaultMessage: 'Service Provider Identifier:'}), help_text: defineMessage({id: 'admin.saml.serviceProviderIdentifierDesc', defaultMessage: 'The unique identifier for the Service Provider, usually the same as Service Provider Login URL. In ADFS, this MUST match the Relying Party Identifier.'}), - placeholder: defineMessage({id: 'admin.saml.serviceProviderIdentifierEx', defaultMessage: 'E.g.: "your-mattermost-url"'}), + placeholder: defineMessage({id: 'admin.saml.serviceProviderIdentifierEx', defaultMessage: 'E.g.: "your-mattermost-url"'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided placeholder_values: { urlChunk: (chunk: string) => `https://'<${chunk}>'/login/sso/saml`, }, @@ -4275,7 +4263,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'SamlSettings.GuestAttribute', label: defineMessage({id: 'admin.saml.guestAttrTitle', defaultMessage: 'Guest Attribute:'}), placeholder: defineMessage({id: 'admin.saml.guestAttrEx', defaultMessage: 'E.g.: "usertype=Guest" or "isGuest=true"'}), - help_text: defineMessage({id: 'admin.saml.guestAttrDesc', defaultMessage: '(Optional) Requires Guest Access to be enabled before being applied. The attribute in the SAML Assertion that will be used to apply a guest role to users in Mattermost. Guests are prevented from accessing teams or channels upon logging in until they are assigned a team and at least one channel. Note: If this attribute is removed/changed from your guest user in SAML and the user is still active, they will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console > User Management**. Existing members that are identified by this attribute as a guest will be demoted from a member to a guest when they are asked to login next. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to guests in **System Console > User Management ** to ensure access is restricted immediately.'}), + help_text: defineMessage({id: 'admin.saml.guestAttrDesc', defaultMessage: '(Optional) Requires Guest Access to be enabled before being applied. The attribute in the SAML Assertion that will be used to apply a guest role to users in Mattermost. Guests are prevented from accessing teams or channels upon logging in until they are assigned a team and at least one channel.\n \nNote: If this attribute is removed/changed from your guest user in SAML and the user is still active, they will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console > User Management**.\n \n \nExisting members that are identified by this attribute as a guest will be demoted from a member to a guest when they are asked to login next. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to guests in **System Console > User Management ** to ensure access is restricted immediately.'}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, isDisabled: it.any( it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.SAML)), @@ -4297,7 +4285,7 @@ const AdminDefinition: AdminDefinitionType = { key: 'SamlSettings.AdminAttribute', label: defineMessage({id: 'admin.saml.adminAttrTitle', defaultMessage: 'Admin Attribute:'}), placeholder: defineMessage({id: 'admin.saml.adminAttrEx', defaultMessage: 'E.g.: "usertype=Admin" or "isAdmin=true"'}), - help_text: defineMessage({id: 'admin.saml.adminAttrDesc', defaultMessage: '(Optional) The attribute in the SAML Assertion for designating System Admins. The users selected by the query will have access to your Mattermost server as System Admins. By default, System Admins have complete access to the Mattermost System Console. Existing members that are identified by this attribute will be promoted from member to System Admin upon next login. The next login is based upon Session lengths set in **System Console > Session Lengths.** It is highly recommend to manually demote users to members in **System Console > User Management** to ensure access is restricted immediately. Note: If this filter is removed/changed, System Admins that were promoted via this filter will be demoted to members and will not retain access to the System Console. When this filter is not in use, System Admins can be manually promoted/demoted in **System Console > User Management**.'}), + help_text: defineMessage({id: 'admin.saml.adminAttrDesc', defaultMessage: '(Optional) The attribute in the SAML Assertion for designating System Admins. The users selected by the query will have access to your Mattermost server as System Admins. By default, System Admins have complete access to the Mattermost System Console.\n \nExisting members that are identified by this attribute will be promoted from member to System Admin upon next login. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to members in **System Console > User Management** to ensure access is restricted immediately.\n \nNote: If this filter is removed/changed, System Admins that were promoted via this filter will be demoted to members and will not retain access to the System Console. When this filter is not in use, System Admins can be manually promoted/demoted in **System Console > User Management**.'}), // eslint-disable-line formatjs/no-multiple-whitespaces help_text_markdown: true, isDisabled: it.any( it.not(it.isSystemAdmin), @@ -4486,7 +4474,7 @@ const AdminDefinition: AdminDefinitionType = { { value: Constants.GITLAB_SERVICE, display_name: defineMessage({id: 'admin.oauth.gitlab', defaultMessage: 'GitLab'}), - help_text: defineMessage({id: 'admin.gitlab.EnableMarkdownDesc', defaultMessage: '1. Log in to your GitLab account and go to Profile Settings -> Applications.\n2. Enter Redirect URIs "your-mattermost-url" (example: http://localhost:8065/login/gitlab/complete) and "your-mattermost-url".\n3. Then use "Application Secret Key" and "Application ID" fields from GitLab to complete the options below.\n4. Complete the Endpoint URLs below.'}), + help_text: defineMessage({id: 'admin.gitlab.EnableMarkdownDesc', defaultMessage: '1. Log in to your GitLab account and go to Profile Settings -> Applications.\n2. Enter Redirect URIs "your-mattermost-url" (example: http://localhost:8065/login/gitlab/complete) and "your-mattermost-url".\n3. Then use "Application Secret Key" and "Application ID" fields from GitLab to complete the options below.\n4. Complete the Endpoint URLs below.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { loginUrlChunk: (chunk: string) => `<${chunk}>/login/gitlab/complete`, signupUrlChunk: (chunk: string) => `<${chunk}>/signup/gitlab/complete`, @@ -4497,7 +4485,7 @@ const AdminDefinition: AdminDefinitionType = { value: Constants.GOOGLE_SERVICE, display_name: defineMessage({id: 'admin.oauth.google', defaultMessage: 'Google Apps'}), isHidden: it.all(it.not(it.licensedForFeature('GoogleOAuth')), it.not(it.cloudLicensed)), - help_text: defineMessage({id: 'admin.google.EnableMarkdownDesc', defaultMessage: '1. Log in to your Google account.\n2. Go to https://console.developers.google.com, click Credentials in the left hand sidebar and enter "Mattermost - your-company-name" as the Project Name, then click Create.\n3. Click the OAuth consent screen header and enter "Mattermost" as the Product name shown to users, then click Save.\n4. Under the Credentials header, click Create credentials, choose OAuth client ID and select Web Application.\n5. Under Restrictions and Authorized redirect URIs enter "your-mattermost-url/signup/google/complete" (example: http://localhost:8065/signup/google/complete). Click Create.\n6. Paste the Client ID and Client Secret to the fields below, then click Save.\n7. Go to the Google People API and click Enable.'}), + help_text: defineMessage({id: 'admin.google.EnableMarkdownDesc', defaultMessage: '1. Log in to your Google account.\n2. Go to https://console.developers.google.com, click Credentials in the left hand side.\n 3. Under the Credentials header, click Create credentials, choose OAuth client ID and select Web Application.\n 4. Enter "Mattermost - your-company-name" as the Name.\n 5. Under Authorized redirect URIs enter "your-mattermost-url/signup/google/complete" (example: http://localhost:8065/signup/google/complete). Click Create.\n 6. Paste the Client ID and Client Secret to the fields below, then click Save.\n 7. Go to the Google People API and click Enable.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { linkLogin: (msg: string) => ( @@ -4531,7 +4519,7 @@ const AdminDefinition: AdminDefinitionType = { value: Constants.OFFICE365_SERVICE, display_name: defineMessage({id: 'admin.oauth.office365', defaultMessage: 'Entra ID'}), isHidden: it.all(it.not(it.licensedForFeature('Office365OAuth')), it.not(it.cloudLicensed)), - help_text: defineMessage({id: 'admin.office365.EnableMarkdownDesc', defaultMessage: '1. Log in to your Microsoft account. \n2. In Microsoft, go to Applications and App Registrations in the left pane.\n3. Select New registration, then enter "Mattermost - your-company-name" as the Application Name. \n4. Under Redirect URI, select Web, and enter "your-mattermost-url/signup/office365/complete" as the Redirect URI. Select Register.\n5. Copy the Microsoft Application (client) ID value, and paste it below as the Client ID value. \n6. Copy the Microsoft Directory (tenant) ID value, and paste it below as the Directory (tenant) ID value. \n7. In Microsoft, create a new client secret. Copy the resulting client secret value, and paste it below as the Client Secret value. Select Save.'}), + help_text: defineMessage({id: 'admin.office365.EnableMarkdownDesc', defaultMessage: '1. Log in to your Microsoft account. \n2. In Microsoft, go to Applications and App Registrations in the left pane.\n3. Select New registration, then enter "Mattermost - your-company-name" as the Application Name. \n4. Under Redirect URI, select Web, and enter "your-mattermost-url/signup/office365/complete" as the Redirect URI. Select Register.\n5. Copy the Microsoft Application (client) ID value, and paste it below as the Client ID value. \n6. Copy the Microsoft Directory (tenant) ID value, and paste it below as the Directory (tenant) ID value. \n7. In Microsoft, create a new client secret. Copy the resulting client secret value, and paste it below as the Client Secret value. Select Save.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { linkLogin: (msg: string) => ( @@ -4825,7 +4813,7 @@ const AdminDefinition: AdminDefinitionType = { { value: Constants.GITLAB_SERVICE, display_name: defineMessage({id: 'admin.openid.gitlab', defaultMessage: 'GitLab'}), - help_text: defineMessage({id: 'admin.gitlab.EnableMarkdownDesc', defaultMessage: '1. Log in to your GitLab account and go to Profile Settings -> Applications.\n2. Enter Redirect URIs "your-mattermost-url" (example: http://localhost:8065/login/gitlab/complete) and "your-mattermost-url".\n3. Then use "Application Secret Key" and "Application ID" fields from GitLab to complete the options below.\n4. Complete the Endpoint URLs below.'}), + help_text: defineMessage({id: 'admin.gitlab.EnableMarkdownDesc', defaultMessage: '1. Log in to your GitLab account and go to Profile Settings -> Applications.\n2. Enter Redirect URIs "your-mattermost-url" (example: http://localhost:8065/login/gitlab/complete) and "your-mattermost-url".\n3. Then use "Application Secret Key" and "Application ID" fields from GitLab to complete the options below.\n4. Complete the Endpoint URLs below.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { loginUrlChunk: (chunk: string) => `<${chunk}>/login/gitlab/complete`, signupUrlChunk: (chunk: string) => `<${chunk}>/signup/gitlab/complete`, @@ -4835,7 +4823,7 @@ const AdminDefinition: AdminDefinitionType = { { value: Constants.GOOGLE_SERVICE, display_name: defineMessage({id: 'admin.openid.google', defaultMessage: 'Google Apps'}), - help_text: defineMessage({id: 'admin.google.EnableMarkdownDesc', defaultMessage: '1. Log in to your Google account.\n2. Go to https://console.developers.google.com], click Credentials in the left hand side.\n 3. Under the Credentials header, click Create credentials, choose OAuth client ID and select Web Application.\n 4. Enter "Mattermost - your-company-name" as the Name.\n 5. Under Authorized redirect URIs enter "your-mattermost-url/signup/google/complete" (example: http://localhost:8065/signup/google/complete). Click Create.\n 6. Paste the Client ID and Client Secret to the fields below, then click Save.\n 7. Go to the Google People API and click Enable.'}), + help_text: defineMessage({id: 'admin.google.EnableMarkdownDesc', defaultMessage: '1. Log in to your Google account.\n2. Go to https://console.developers.google.com, click Credentials in the left hand side.\n 3. Under the Credentials header, click Create credentials, choose OAuth client ID and select Web Application.\n 4. Enter "Mattermost - your-company-name" as the Name.\n 5. Under Authorized redirect URIs enter "your-mattermost-url/signup/google/complete" (example: http://localhost:8065/signup/google/complete). Click Create.\n 6. Paste the Client ID and Client Secret to the fields below, then click Save.\n 7. Go to the Google People API and click Enable.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { linkLogin: (msg: string) => ( @@ -4868,7 +4856,7 @@ const AdminDefinition: AdminDefinitionType = { { value: Constants.OFFICE365_SERVICE, display_name: defineMessage({id: 'admin.openid.office365', defaultMessage: 'Entra ID'}), - help_text: defineMessage({id: 'admin.office365.EnableMarkdownDesc', defaultMessage: '1. Log in to your Microsoft account. \n2. In Microsoft, go to Applications and App Registrations in the left pane.\n3. Select New registration, then enter "Mattermost - your-company-name" as the Application Name. \n4. Under Redirect URI, select Web, and enter "your-mattermost-url/signup/office365/complete" as the Redirect URI. Select Register.\n5. Copy the Microsoft Application (client) ID value, and paste it below as the Client ID value. \n6. Copy the Microsoft Directory (tenant) ID value, and paste it below as the Directory (tenant) ID value. \n7. In Microsoft, create a new client secret. Copy the resulting client secret value, and paste it below as the Client Secret value. Select Save.'}), + help_text: defineMessage({id: 'admin.office365.EnableMarkdownDesc', defaultMessage: '1. Log in to your Microsoft account. \n2. In Microsoft, go to Applications and App Registrations in the left pane.\n3. Select New registration, then enter "Mattermost - your-company-name" as the Application Name. \n4. Under Redirect URI, select Web, and enter "your-mattermost-url/signup/office365/complete" as the Redirect URI. Select Register.\n5. Copy the Microsoft Application (client) ID value, and paste it below as the Client ID value. \n6. Copy the Microsoft Directory (tenant) ID value, and paste it below as the Directory (tenant) ID value. \n7. In Microsoft, create a new client secret. Copy the resulting client secret value, and paste it below as the Client Secret value. Select Save.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { linkLogin: (msg: string) => ( @@ -4935,7 +4923,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'GitLabSettings.Id', label: defineMessage({id: 'admin.openid.clientIdTitle', defaultMessage: 'Client ID:'}), - help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.gitlab.clientIdExample', defaultMessage: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'}), isHidden: it.not(it.stateEquals('openidType', Constants.GITLAB_SERVICE)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -4944,8 +4932,8 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'GitLabSettings.Secret', label: defineMessage({id: 'admin.openid.clientSecretTitle', defaultMessage: 'Client Secret:'}), - help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation'}), - placeholder: defineMessage({id: 'admin.gitlab.clientSecretExample', defaultMessage: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx442pnqMxQY"'}), + help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation.'}), + placeholder: defineMessage({id: 'admin.gitlab.clientSecretExample', defaultMessage: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'}), isHidden: it.not(it.stateEquals('openidType', Constants.GITLAB_SERVICE)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), }, @@ -4963,7 +4951,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'GoogleSettings.Id', label: defineMessage({id: 'admin.openid.clientIdTitle', defaultMessage: 'Client ID:'}), - help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.google.clientIdExample', defaultMessage: 'E.g.: "7602141235235-url0fhs1mayfasbmop5qlfns8dh4.apps.googleusercontent.com"'}), isHidden: it.not(it.stateEquals('openidType', Constants.GOOGLE_SERVICE)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -4972,7 +4960,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'GoogleSettings.Secret', label: defineMessage({id: 'admin.openid.clientSecretTitle', defaultMessage: 'Client Secret:'}), - help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.google.clientSecretExample', defaultMessage: 'E.g.: "H8sz0Az-dDs2p15-7QzD231"'}), isHidden: it.not(it.stateEquals('openidType', Constants.GOOGLE_SERVICE)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -5005,7 +4993,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'Office365Settings.Id', label: defineMessage({id: 'admin.openid.clientIdTitle', defaultMessage: 'Client ID:'}), - help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.office365.clientIdExample', defaultMessage: 'E.g.: "adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq"'}), isHidden: it.not(it.stateEquals('openidType', Constants.OFFICE365_SERVICE)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -5014,7 +5002,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'Office365Settings.Secret', label: defineMessage({id: 'admin.openid.clientSecretTitle', defaultMessage: 'Client Secret:'}), - help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.office365.clientSecretExample', defaultMessage: 'E.g.: "shAieM47sNBfgl20f8ci294"'}), isHidden: it.not(it.stateEquals('openidType', Constants.OFFICE365_SERVICE)), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -5052,7 +5040,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'OpenIdSettings.Id', label: defineMessage({id: 'admin.openid.clientIdTitle', defaultMessage: 'Client ID:'}), - help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientIdDescription', defaultMessage: 'Obtaining the Client ID differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.openid.clientIdExample', defaultMessage: 'E.g.: "adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq"'}), isHidden: it.any(it.not(it.stateEquals('openidType', Constants.OPENID_SERVICE)), it.licensedForCloudStarter), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -5061,7 +5049,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'text', key: 'OpenIdSettings.Secret', label: defineMessage({id: 'admin.openid.clientSecretTitle', defaultMessage: 'Client Secret:'}), - help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation'}), + help_text: defineMessage({id: 'admin.openid.clientSecretDescription', defaultMessage: 'Obtaining the Client Secret differs across providers. Please check you provider\'s documentation.'}), placeholder: defineMessage({id: 'admin.openid.clientSecretExample', defaultMessage: 'E.g.: "H8sz0Az-dDs2p15-7QzD231"'}), isHidden: it.any(it.not(it.stateEquals('openidType', Constants.OPENID_SERVICE)), it.licensedForCloudStarter), isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.OPENID)), @@ -5179,7 +5167,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'GuestAccountsSettings.EnforceMultifactorAuthentication', label: defineMessage({id: 'admin.guest_access.mfaTitle', defaultMessage: 'Enforce Multi-factor Authentication: '}), - help_text: defineMessage({id: 'admin.guest_access.mfaDescription', defaultMessage: 'When true, multi-factor authentication for guests is required for login. New guest users will be required to configure MFA on signup. Logged in guest users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has guest users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.'}), + help_text: defineMessage({id: 'admin.guest_access.mfaDescription', defaultMessage: 'When true, multi-factor authentication for guests is required for login. New guest users will be required to configure MFA on signup. Logged in guest users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has guest users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.service.webhooksDescription', defaultMessage: 'When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.service.outWebhooksDesc', defaultMessage: 'When true, outgoing webhooks will be allowed. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.service.outgoingOAuthConnectionsDesc', defaultMessage: 'When true, outgoing webhooks and slash commands will use set up oauth connections to authenticate with third party services. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (text: string) => ( {text} @@ -5335,7 +5323,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'ServiceSettings.EnableCommands', label: defineMessage({id: 'admin.service.cmdsTitle', defaultMessage: 'Enable Custom Slash Commands: '}), - help_text: defineMessage({id: 'admin.service.cmdsDesc', defaultMessage: 'When true, custom slash commands will be allowed. See documentation to learn more.'}), + help_text: defineMessage({id: 'admin.service.cmdsDesc', defaultMessage: 'When true, custom slash commands will be allowed. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation to learn more.'}), + help_text: defineMessage({id: 'admin.oauth.providerDescription', defaultMessage: 'When true, Mattermost can act as an OAuth 2.0 service provider allowing Mattermost to authorize API requests from external applications. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Slash Commands, Outgoing Webhooks, Interactive Messages and Interactive Dialogs.'}), + help_text: defineMessage({id: 'admin.service.integrationRequestDesc', defaultMessage: 'The number of seconds to wait for Integration requests. That includes Slash Commands, Outgoing Webhooks, Interactive Messages and Interactive Dialogs.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { slashCommands: (msg: string) => ( user access tokens for integrations in Account Menu > Account Settings > Security. They can be used to authenticate against the API and give full access to the account.\n\n To manage who can create personal access tokens or to search users by token ID, go to the User Management > Users page.'}), + label: defineMessage({id: 'admin.service.userAccessTokensTitle', defaultMessage: 'Enable Personal Access Tokens:'}), + help_text: defineMessage({id: 'admin.service.userAccessTokensDescription', defaultMessage: 'When true, users can create personal access tokens for integrations in Profile > Security. They can be used to authenticate against the API and give full access to the account.\n\n To manage who can create personal access tokens or to search users by token ID, go to System Console > User Management > Users.'}), // eslint-disable-line formatjs/no-multiple-whitespaces, formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( Integrations > Bot Accounts. Bot accounts are similar to user accounts except they cannot be used to log in. See documentation to learn more.'}), + help_text: defineMessage({id: 'admin.service.enableBotAccountCreation', defaultMessage: 'When true, System Admins can create bot accounts for integrations in Integrations > Bot Accounts. Bot accounts are similar to user accounts except they cannot be used to log in. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { siteURL: getSiteURL(), @@ -5499,7 +5487,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'ServiceSettings.DisableBotsWhenOwnerIsDeactivated', label: defineMessage({id: 'admin.service.disableBotOwnerDeactivatedTitle', defaultMessage: 'Disable bot accounts when owner is deactivated:'}), - help_text: defineMessage({id: 'admin.service.disableBotWhenOwnerIsDeactivated', defaultMessage: 'When a user is deactivated, disables all bot accounts managed by the user. To re-enable bot accounts, go to [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots).'}), + help_text: defineMessage({id: 'admin.service.disableBotWhenOwnerIsDeactivated', defaultMessage: 'When a user is deactivated, disables all bot accounts managed by the user. To re-enable bot accounts, go to [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots).'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: true, help_text_values: {siteURL: getSiteURL()}, isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.INTEGRATIONS.BOT_ACCOUNTS)), @@ -5732,7 +5720,7 @@ const AdminDefinition: AdminDefinitionType = { settings: [ { type: 'banner', - label: defineMessage({id: 'admin.compliance.newComplianceExportBanner', defaultMessage: 'This feature is replaced by a new Compliance Export feature, and will be removed in a future release. We recommend migrating to the new system.'}), + label: defineMessage({id: 'admin.compliance.newComplianceExportBanner', defaultMessage: 'This feature is replaced by a new Compliance Export feature, and will be removed in a future release. We recommend migrating to the new system.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided label_values: { link: (msg: string) => ( @@ -5747,7 +5735,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'ComplianceSettings.Enable', label: defineMessage({id: 'admin.compliance.enableTitle', defaultMessage: 'Enable Compliance Reporting:'}), - help_text: defineMessage({id: 'admin.compliance.enableDesc', defaultMessage: 'When true, Mattermost allows compliance reporting from the Compliance and Auditing tab. See documentation to learn more.'}), + help_text: defineMessage({id: 'admin.compliance.enableDesc', defaultMessage: 'When true, Mattermost allows compliance reporting from the Compliance and Auditing tab. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( documentation to learn more about Advanced Logging and the JSON format it uses.'}), + help_text: defineMessage({id: 'admin.log.AdvancedAuditLoggingJSONDescription', defaultMessage: 'The JSON configuration for Advanced Audit Logging. Please see documentation to learn more about Advanced Logging and the JSON format it uses.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_markdown: false, help_text_values: { link: (msg: string) => ( @@ -6020,7 +6008,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'ServiceSettings.ExperimentalEnableAuthenticationTransfer', label: defineMessage({id: 'admin.experimental.experimentalEnableAuthenticationTransfer.title', defaultMessage: 'Allow Authentication Transfer:'}), - help_text: defineMessage({id: 'admin.experimental.experimentalEnableAuthenticationTransfer.desc', defaultMessage: 'When true, users can change their sign-in method to any that is enabled on the server, any via Account Settings or the APIs. When false, Users cannot change their sign-in method, regardless of which authentication options are enabled.'}), + help_text: defineMessage({id: 'admin.experimental.experimentalEnableAuthenticationTransfer.desc', defaultMessage: 'When true, users can change their sign-in method to any that is enabled on the server, either via their Profile or the APIs. When false, Users cannot change their sign-in method, regardless of which authentication options are enabled.'}), help_text_markdown: false, isHidden: it.any( // documented as E20 and higher, but only E10 in the code it.not(it.licensed), @@ -6115,7 +6103,7 @@ const AdminDefinition: AdminDefinitionType = { type: 'bool', key: 'ServiceSettings.ExperimentalEnableHardenedMode', label: defineMessage({id: 'admin.experimental.experimentalEnableHardenedMode.title', defaultMessage: 'Enable Hardened Mode:'}), - help_text: defineMessage({id: 'admin.experimental.experimentalEnableHardenedMode.desc', defaultMessage: 'Enables a hardened mode for Mattermost that makes user experience trade-offs in the interest of security. See documentation to learn more.'}), + help_text: defineMessage({id: 'admin.experimental.experimentalEnableHardenedMode.desc', defaultMessage: 'Enables a hardened mode for Mattermost that makes user experience trade-offs in the interest of security. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- placeholders provided help_text_values: { link: (msg: string) => ( diff --git a/webapp/channels/src/components/admin_console/admin_definition_helpers.tsx b/webapp/channels/src/components/admin_console/admin_definition_helpers.tsx index 826a1cee38a..9617bcbc180 100644 --- a/webapp/channels/src/components/admin_console/admin_definition_helpers.tsx +++ b/webapp/channels/src/components/admin_console/admin_definition_helpers.tsx @@ -113,6 +113,7 @@ export const getRestrictedIndicator = (displayBlocked = false, minimumPlanRequir minimumPlanRequiredForFeature={minimumPlanRequiredForFeature} tooltipMessageBlocked={defineMessage({ id: 'admin.sidebar.restricted_indicator.tooltip.message.blocked', + // eslint-disable-next-line formatjs/enforce-placeholders -- Placeholders provided in RestrictedIndicator defaultMessage: 'This is {article} {minimumPlanRequiredForFeature} feature, available with an upgrade or free {trialLength}-day trial', })} /> diff --git a/webapp/channels/src/components/admin_console/admin_definition_ldap_wizard.tsx b/webapp/channels/src/components/admin_console/admin_definition_ldap_wizard.tsx index 42e70400331..dab19ceefdd 100644 --- a/webapp/channels/src/components/admin_console/admin_definition_ldap_wizard.tsx +++ b/webapp/channels/src/components/admin_console/admin_definition_ldap_wizard.tsx @@ -1,6 +1,8 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +/* eslint-disable formatjs/enforce-placeholders -- Admin wizard uses help_text_values for placeholders, which ESLint cannot statically analyze */ + import React from 'react'; import {FormattedMessage, defineMessage} from 'react-intl'; diff --git a/webapp/channels/src/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx b/webapp/channels/src/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx index 70a2bd2c96f..1ef70d840cc 100644 --- a/webapp/channels/src/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx +++ b/webapp/channels/src/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx @@ -107,7 +107,7 @@ class AdminNavbarDropdown extends React.PureComponent { } @@ -2187,7 +2187,7 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr name="experimental/feature_flags" title={ } @@ -3261,7 +3261,7 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr name="experimental/feature_flags" title={ } @@ -4246,7 +4246,7 @@ exports[`components/AdminSidebar should match snapshot with license with profess name="experimental/feature_flags" title={ } @@ -5220,7 +5220,7 @@ exports[`components/AdminSidebar should match snapshot with workspace optimizati name="experimental/feature_flags" title={ } @@ -6233,7 +6233,7 @@ exports[`components/AdminSidebar should match snapshot, not prevent the console name="experimental/feature_flags" title={ } @@ -7207,7 +7207,7 @@ exports[`components/AdminSidebar should match snapshot, render plugins without a name="experimental/feature_flags" title={ } @@ -8082,7 +8082,7 @@ exports[`components/AdminSidebar should match snapshot, with license (with all f name="experimental/feature_flags" title={ } @@ -9067,7 +9067,7 @@ exports[`components/AdminSidebar should match snapshot, with license (without an name="experimental/feature_flags" title={ } diff --git a/webapp/channels/src/components/admin_console/billing/billing_history_modal.tsx b/webapp/channels/src/components/admin_console/billing/billing_history_modal.tsx index c43870afa05..8559e219637 100644 --- a/webapp/channels/src/components/admin_console/billing/billing_history_modal.tsx +++ b/webapp/channels/src/components/admin_console/billing/billing_history_modal.tsx @@ -61,7 +61,7 @@ export default function BillingHistoryModal(props: BillingHistoryModalProps) { dialogClassName='a11y__modal' > - {formatMessage({id: 'cloud_billing_history_modal.title', defaultMessage: 'Unpaid Invoice(s)'})} + {formatMessage({id: 'cloud_billing_history_modal.title', defaultMessage: 'Invoice(s)'})} diff --git a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/cloud_trial_banner.tsx b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/cloud_trial_banner.tsx index adce1b1f7cb..fa2614eb55d 100644 --- a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/cloud_trial_banner.tsx +++ b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/cloud_trial_banner.tsx @@ -70,7 +70,7 @@ const CloudTrialBanner = ({trialEndDate}: Props): JSX.Element | null => { title={( )} message={( diff --git a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.test.tsx b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.test.tsx index cd1c7f4ca8d..b6775d0ec78 100644 --- a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.test.tsx +++ b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.test.tsx @@ -105,7 +105,7 @@ describe('Limits', () => { const state = setupState(defaultOptions); renderWithContext(, state); - screen.getByText('Message History'); + screen.getByText('Message history'); screen.getByText(/of 10K/); }); @@ -113,7 +113,7 @@ describe('Limits', () => { const state = setupState(defaultOptions); renderWithContext(, state); - screen.getByText('File Storage'); + screen.getByText('File storage'); screen.getByText(/of 1GB/); }); diff --git a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.tsx b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.tsx index c8b1a0852fa..5c87b841a12 100644 --- a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.tsx +++ b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/limits.tsx @@ -68,7 +68,7 @@ const Limits = (): JSX.Element | null => { name={( )} status={( @@ -92,13 +92,13 @@ const Limits = (): JSX.Element | null => { name={ } status={ { > {intl.formatMessage({ id: 'admin.license.trialCard.contactSales', - defaultMessage: 'Contact sales', + defaultMessage: 'Contact Sales', })} diff --git a/webapp/channels/src/components/admin_console/billing/billing_summary/billing_summary.tsx b/webapp/channels/src/components/admin_console/billing/billing_summary/billing_summary.tsx index 21c5e5a863d..8cf19eb289d 100644 --- a/webapp/channels/src/components/admin_console/billing/billing_summary/billing_summary.tsx +++ b/webapp/channels/src/components/admin_console/billing/billing_summary/billing_summary.tsx @@ -82,7 +82,7 @@ export const FreeTrial = ({daysLeftOnTrial}: FreeTrialProps) => { {daysLeftOnTrial > TrialPeriodDays.TRIAL_1_DAY && } {(daysLeftOnTrial === TrialPeriodDays.TRIAL_1_DAY || daysLeftOnTrial === TrialPeriodDays.TRIAL_0_DAYS) && @@ -96,21 +96,21 @@ export const FreeTrial = ({daysLeftOnTrial}: FreeTrialProps) => { {daysLeftOnTrial > TrialPeriodDays.TRIAL_WARNING_THRESHOLD && } {(daysLeftOnTrial > TrialPeriodDays.TRIAL_1_DAY && daysLeftOnTrial <= TrialPeriodDays.TRIAL_WARNING_THRESHOLD) && } {(daysLeftOnTrial === TrialPeriodDays.TRIAL_1_DAY || daysLeftOnTrial === TrialPeriodDays.TRIAL_0_DAYS) && } diff --git a/webapp/channels/src/components/admin_console/billing/plan_details/feature_list.tsx b/webapp/channels/src/components/admin_console/billing/plan_details/feature_list.tsx index 19ad8becd8a..3d15558f198 100644 --- a/webapp/channels/src/components/admin_console/billing/plan_details/feature_list.tsx +++ b/webapp/channels/src/components/admin_console/billing/plan_details/feature_list.tsx @@ -32,7 +32,7 @@ const FeatureList = (props: FeatureListProps) => { intl.formatMessage( { id: 'admin.billing.subscription.planDetails.features.limitedFileStorage', - defaultMessage: 'Limited to {limit} File Storage', + defaultMessage: 'Limited to {limit} file storage', }, { diff --git a/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx b/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx index 5622dc1118a..d3d1f08632a 100644 --- a/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx +++ b/webapp/channels/src/components/admin_console/custom_profile_attributes/custom_profile_attributes.tsx @@ -27,7 +27,7 @@ const AttributeHelpText = memo(({attributeKey, attributeName, attributeType}: At
{attributeKey === 'ldap' && ( {msg}, - }} />
)} @@ -132,7 +128,7 @@ const CustomProfileAttributes: React.FC = (props: Props): JSX.Element | n subtitle={ ( Site Configuration > Customization'}, }); diff --git a/webapp/channels/src/components/admin_console/database_settings.tsx b/webapp/channels/src/components/admin_console/database_settings.tsx index d7b1067951f..d4cb5eef43b 100644 --- a/webapp/channels/src/components/admin_console/database_settings.tsx +++ b/webapp/channels/src/components/admin_console/database_settings.tsx @@ -44,7 +44,7 @@ interface State extends BaseState { } const messages = defineMessages({ - title: {id: 'admin.database.title', defaultMessage: 'Database Settings'}, + title: {id: 'admin.database.title', defaultMessage: 'Database'}, recycleDescription: {id: 'admin.recycle.recycleDescription', defaultMessage: 'Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating "config.json" to the new desired configuration and using the {reloadConfiguration} feature to load the new settings while the server is running. The administrator should then use {featureName} feature to recycle the database connections based on the new settings.'}, featureName: {id: 'admin.recycle.recycleDescription.featureName', defaultMessage: 'Recycle Database Connections'}, reloadConfiguration: {id: 'admin.recycle.recycleDescription.reloadConfiguration', defaultMessage: 'Environment > Web Server > Reload Configuration from Disk'}, @@ -187,6 +187,7 @@ export default class DatabaseSettings extends OLDAdminSettings { showSuccessMessage={false} errorMessage={defineMessage({ id: 'admin.recycle.reloadFail', + // eslint-disable-next-line formatjs/enforce-placeholders -- error provided by RequestButton defaultMessage: 'Recycling unsuccessful: {error}', })} includeDetailedError={true} diff --git a/webapp/channels/src/components/admin_console/elasticsearch_settings.tsx b/webapp/channels/src/components/admin_console/elasticsearch_settings.tsx index 1bf248d975c..4df1cbb96c0 100644 --- a/webapp/channels/src/components/admin_console/elasticsearch_settings.tsx +++ b/webapp/channels/src/components/admin_console/elasticsearch_settings.tsx @@ -65,18 +65,18 @@ export const messages = defineMessages({ bulkIndexingTitle: {id: 'admin.elasticsearch.bulkIndexingTitle', defaultMessage: 'Bulk Indexing:'}, help: {id: 'admin.elasticsearch.createJob.help', defaultMessage: 'All users, channels and posts in the database will be indexed from oldest to newest. Elasticsearch is available during indexing but search results may be incomplete until the indexing job is complete.'}, rebuildChannelsIndexTitle: {id: 'admin.elasticsearch.rebuildChannelsIndexTitle', defaultMessage: 'Rebuild Channels Index'}, - rebuildChannelIndexHelpText: {id: 'admin.elasticsearch.rebuildChannelsIndex.helpText', defaultMessage: 'This purges the channels index and re-indexes all channels in the database, from oldest to newest. Channel autocomplete is available during indexing but search results may be incomplete until the indexing job is complete.\nNote- Please ensure no other indexing job is in progress in the table above.'}, + rebuildChannelIndexHelpText: {id: 'admin.elasticsearch.rebuildChannelsIndex.helpText', defaultMessage: 'This purges the channels index and re-indexes all channels in the database, from oldest to newest. Channel autocomplete is available during indexing but search results may be incomplete until the indexing job is complete.\n\nNote- Please ensure no other indexing job is in progress in the table above.'}, // eslint-disable-line formatjs/no-multiple-whitespaces rebuildChannelsIndexButtonText: {id: 'admin.elasticsearch.rebuildChannelsIndex.title', defaultMessage: 'Rebuild Channels Index'}, purgeIndexesHelpText: {id: 'admin.elasticsearch.purgeIndexesHelpText', defaultMessage: 'Purging will entirely remove the indexes on the Elasticsearch server. Search results may be incomplete until a bulk index of the existing database is rebuilt.'}, - purgeIndexesButton: {id: 'admin.elasticsearch.purgeIndexesButton', defaultMessage: 'Purge Index'}, + purgeIndexesButton: {id: 'admin.elasticsearch.purgeIndexesButton', defaultMessage: 'Purge Indexes'}, label: {id: 'admin.elasticsearch.purgeIndexesButton.label', defaultMessage: 'Purge Indexes:'}, enableSearchingTitle: {id: 'admin.elasticsearch.enableSearchingTitle', defaultMessage: 'Enable Elasticsearch for search queries:'}, enableSearchingDescription: {id: 'admin.elasticsearch.enableSearchingDescription', defaultMessage: 'Requires a successful connection to the Elasticsearch server. When true, Elasticsearch will be used for all search queries using the latest index. Search results may be incomplete until a bulk index of the existing post database is finished. When false, database search is used.'}, }); export const searchableStrings: Array = [ - [messages.connectionUrlDescription, {documentationLink: ''}], - [messages.enableIndexingDescription, {documentationLink: ''}], + [messages.connectionUrlDescription, {link: (msg: string) => msg}], + [messages.enableIndexingDescription, {link: (msg: string) => msg}], messages.title, messages.enableIndexingTitle, messages.connectionUrlTitle, @@ -456,6 +456,7 @@ export default class ElasticsearchSettings extends OLDAdminSettings { expect(screen.getByRole('button', {name: 'Start trial'})).toBeInTheDocument(); await userEvent.click(screen.getByRole('button', {name: 'Start trial'})); - await userEvent.click(screen.getByText('Mattermost Software and Services License Agreement')); + await userEvent.click(screen.getByText('Mattermost Software Evaluation Agreement')); //cloud option expect(screen.queryByRole('button', {name: 'Try free for 30 days'})).not.toBeInTheDocument(); @@ -68,7 +68,7 @@ describe('components/feature_discovery', () => { expect(featureLink).toBeInTheDocument(); expect(featureLink).toHaveAttribute('href', 'https://test.mattermost.com/secondary/?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid=&edition=team&server_version='); expect(featureLink).toHaveTextContent('Learn more'); - expect(screen.getByText('Mattermost Software and Services License Agreement')).toHaveAttribute('href', 'https://mattermost.com/pl/software-and-services-license-agreement?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid=&edition=team&server_version='); + expect(screen.getByText('Mattermost Software Evaluation Agreement')).toHaveAttribute('href', 'https://mattermost.com/pl/software-and-services-license-agreement?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid=&edition=team&server_version='); expect(screen.getByText('Privacy Policy')).toHaveAttribute('href', AboutLinks.PRIVACY_POLICY + '?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid=&edition=team&server_version='); expect(getPrevTrialLicense).toHaveBeenCalled(); diff --git a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx index 6a62855f2e3..d5b78984bdb 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx @@ -167,7 +167,7 @@ export default class FeatureDiscovery extends React.PureComponent ( {msg} diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/auto_translation.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/auto_translation.tsx index 01ce27c2add..ee52e3fb052 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/auto_translation.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/auto_translation.tsx @@ -31,6 +31,7 @@ const AutoTranslationFeatureDiscovery: React.FC = () => { })} copy={defineMessage({ id: 'admin.auto_translation_feature_discovery.copy', + // eslint-disable-next-line formatjs/enforce-placeholders -- values spread onto FormattedMessage in FeatureDiscovery defaultMessage: 'Effortlessly collaborate across languages with auto-translation. Messages in shared channels are instantly translated based on each user’s language preference—no extra steps required.{br}Only available in Enterprise Advanced.', values: {strong: (msg: string) => {msg}, br:
}, })} diff --git a/webapp/channels/src/components/admin_console/feature_flags.tsx b/webapp/channels/src/components/admin_console/feature_flags.tsx index 7563c19a559..6e30c61c12b 100644 --- a/webapp/channels/src/components/admin_console/feature_flags.tsx +++ b/webapp/channels/src/components/admin_console/feature_flags.tsx @@ -13,7 +13,7 @@ type Props = { }; export const messages = defineMessages({ - title: {id: 'admin.feature_flags.title', defaultMessage: 'Features Flags'}, + title: {id: 'admin.feature_flags.title', defaultMessage: 'Feature Flags'}, }); const FeatureFlags: React.FC = (props: Props) => { @@ -40,7 +40,7 @@ const FeatureFlags: React.FC = (props: Props) => {
diff --git a/webapp/channels/src/components/admin_console/group_settings/group_details/group_details.tsx b/webapp/channels/src/components/admin_console/group_settings/group_details/group_details.tsx index d4803835543..e79ba559f38 100644 --- a/webapp/channels/src/components/admin_console/group_settings/group_details/group_details.tsx +++ b/webapp/channels/src/components/admin_console/group_settings/group_details/group_details.tsx @@ -479,7 +479,7 @@ class GroupDetails extends React.PureComponent { serverError = ( ); } else if ( diff --git a/webapp/channels/src/components/admin_console/group_settings/group_details/group_profile_and_settings.tsx b/webapp/channels/src/components/admin_console/group_settings/group_details/group_profile_and_settings.tsx index 3dbe8a1db0f..7c2c301ca8b 100644 --- a/webapp/channels/src/components/admin_console/group_settings/group_details/group_profile_and_settings.tsx +++ b/webapp/channels/src/components/admin_console/group_settings/group_details/group_profile_and_settings.tsx @@ -36,7 +36,7 @@ const GroupSettingsToggle = ({ title={ } subTitle={ diff --git a/webapp/channels/src/components/admin_console/group_settings/group_settings.tsx b/webapp/channels/src/components/admin_console/group_settings/group_settings.tsx index cd5cc1230c7..b360ee58a74 100644 --- a/webapp/channels/src/components/admin_console/group_settings/group_settings.tsx +++ b/webapp/channels/src/components/admin_console/group_settings/group_settings.tsx @@ -51,6 +51,7 @@ const GroupSettings = ({isDisabled}: Props) => { AD/LDAP configuration page.'})} subtitleValues={{ link: (msg: React.ReactNode) => ( diff --git a/webapp/channels/src/components/admin_console/ip_filtering/edit_section/edit_section_no_filters_panel.tsx b/webapp/channels/src/components/admin_console/ip_filtering/edit_section/edit_section_no_filters_panel.tsx index 40e3f0b651c..c65cc890ca5 100644 --- a/webapp/channels/src/components/admin_console/ip_filtering/edit_section/edit_section_no_filters_panel.tsx +++ b/webapp/channels/src/components/admin_console/ip_filtering/edit_section/edit_section_no_filters_panel.tsx @@ -27,7 +27,7 @@ const NoFiltersPanel = ({setShowAddModal}: NoFiltersPanelProps) => (
(
{msg}, linkEvaluation: (msg: React.ReactNode) => ( diff --git a/webapp/channels/src/components/admin_console/localization/auto_translation.tsx b/webapp/channels/src/components/admin_console/localization/auto_translation.tsx index 6f5e798572e..1b01ce8123a 100644 --- a/webapp/channels/src/components/admin_console/localization/auto_translation.tsx +++ b/webapp/channels/src/components/admin_console/localization/auto_translation.tsx @@ -112,6 +112,7 @@ export default function AutoTranslation(props: SystemConsoleCustomSettingsCompon helpText={ diff --git a/webapp/channels/src/components/admin_console/message_export_settings.tsx b/webapp/channels/src/components/admin_console/message_export_settings.tsx index cdf47519356..3ed095dd43f 100644 --- a/webapp/channels/src/components/admin_console/message_export_settings.tsx +++ b/webapp/channels/src/components/admin_console/message_export_settings.tsx @@ -193,7 +193,7 @@ export class MessageExportSettings extends OLDAdminSettingsSystem Scheme", + "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme.", "id": "admin.permissions.teamOverrideSchemesBannerText", } } @@ -203,7 +203,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_schemes } subtitle={ Object { - "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme", + "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme.", "id": "admin.permissions.teamOverrideSchemesBannerText", } } @@ -309,7 +309,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_schemes } subtitle={ Object { - "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme", + "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme.", "id": "admin.permissions.teamOverrideSchemesBannerText", } } @@ -454,7 +454,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_schemes } subtitle={ Object { - "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme", + "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme.", "id": "admin.permissions.teamOverrideSchemesBannerText", } } @@ -598,7 +598,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_schemes } subtitle={ Object { - "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme", + "defaultMessage": "Use when specific teams need permission exceptions to the System Scheme.", "id": "admin.permissions.teamOverrideSchemesBannerText", } } diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_row.tsx b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_row.tsx index cc6791be3bd..ecfbc90f4ea 100644 --- a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_row.tsx +++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_row.tsx @@ -46,7 +46,7 @@ const PermissionRow = ({ if (permissionRolesStrings[id]) { description = ( ); diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_schemes_settings.tsx b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_schemes_settings.tsx index 11d7229d693..4aae57563b9 100644 --- a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_schemes_settings.tsx +++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_schemes_settings.tsx @@ -1,6 +1,8 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +/* eslint-disable formatjs/enforce-placeholders -- link placeholders provided by admin panel components */ + import React from 'react'; import {type MessageDescriptor} from 'react-intl'; import {FormattedMessage, defineMessage, defineMessages} from 'react-intl'; @@ -53,7 +55,7 @@ const messages = defineMessages({ systemSchemeBannerText: {id: 'admin.permissions.systemSchemeBannerText', defaultMessage: 'Set the default permissions inherited by all teams unless a Team Override Scheme is applied.'}, systemSchemeBannerButton: {id: 'admin.permissions.systemSchemeBannerButton', defaultMessage: 'Edit Scheme'}, teamOverrideSchemesTitle: {id: 'admin.permissions.teamOverrideSchemesTitle', defaultMessage: 'Team Override Schemes'}, - teamOverrideSchemesBannerText: {id: 'admin.permissions.teamOverrideSchemesBannerText', defaultMessage: 'Use when specific teams need permission exceptions to the System Scheme'}, + teamOverrideSchemesBannerText: {id: 'admin.permissions.teamOverrideSchemesBannerText', defaultMessage: 'Use when specific teams need permission exceptions to the System Scheme.'}, teamOverrideSchemesNewButton: {id: 'admin.permissions.teamOverrideSchemesNewButton', defaultMessage: 'New Team Override Scheme'}, }); diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_system_scheme_settings/__snapshots__/permission_system_scheme_settings.test.tsx.snap b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_system_scheme_settings/__snapshots__/permission_system_scheme_settings.test.tsx.snap index 8800cf284aa..c8ca4098ee3 100644 --- a/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_system_scheme_settings/__snapshots__/permission_system_scheme_settings.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/permission_system_scheme_settings/__snapshots__/permission_system_scheme_settings.test.tsx.snap @@ -175,7 +175,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_system_ > { ( @@ -270,7 +270,7 @@ exports[`components/PluginManagement should match snapshot when \`Enable Marketp > @@ -529,7 +529,7 @@ exports[`components/PluginManagement should match snapshot when \`Enable Plugins > @@ -605,7 +605,7 @@ exports[`components/PluginManagement should match snapshot when \`Enable Remote > @@ -864,7 +864,7 @@ exports[`components/PluginManagement should match snapshot when \`Require Signat > @@ -1125,7 +1125,7 @@ exports[`components/PluginManagement should match snapshot, No installed plugins > @@ -1388,7 +1388,7 @@ exports[`components/PluginManagement should match snapshot, allow insecure URL e > @@ -1647,7 +1647,7 @@ exports[`components/PluginManagement should match snapshot, disabled 1`] = ` > @@ -1730,11 +1730,12 @@ exports[`components/PluginManagement should match snapshot, disabled 1`] = ` @@ -1890,7 +1891,7 @@ exports[`components/PluginManagement should match snapshot, text entered into th > @@ -2149,7 +2150,7 @@ exports[`components/PluginManagement should match snapshot, upload disabled 1`] > @@ -2415,7 +2416,7 @@ exports[`components/PluginManagement should match snapshot, with installed plugi > @@ -2737,7 +2738,7 @@ exports[`components/PluginManagement should match snapshot, with installed plugi > @@ -3027,7 +3028,7 @@ exports[`components/PluginManagement should match snapshot, with installed plugi > @@ -3317,7 +3318,7 @@ exports[`components/PluginManagement should match snapshot, with installed plugi > @@ -3607,7 +3608,7 @@ exports[`components/PluginManagement should match snapshot, with installed plugi > diff --git a/webapp/channels/src/components/admin_console/plugin_management/plugin_management.tsx b/webapp/channels/src/components/admin_console/plugin_management/plugin_management.tsx index 34ffe0fdf17..bc5ce96146b 100644 --- a/webapp/channels/src/components/admin_console/plugin_management/plugin_management.tsx +++ b/webapp/channels/src/components/admin_console/plugin_management/plugin_management.tsx @@ -189,7 +189,7 @@ type PluginItemProps = { }; const messages = defineMessages({ - title: {id: 'admin.plugin.management.title', defaultMessage: 'Management'}, + title: {id: 'admin.plugin.management.title', defaultMessage: 'Plugin Management'}, enable: {id: 'admin.plugins.settings.enable', defaultMessage: 'Enable Plugins: '}, enableDesc: {id: 'admin.plugins.settings.enableDesc', defaultMessage: 'When true, enables plugins on your Mattermost server. Use plugins to integrate with third-party systems, extend functionality, or customize the user interface of your Mattermost server. See documentation to learn more.'}, uploadTitle: {id: 'admin.plugin.uploadTitle', defaultMessage: 'Upload Plugin: '}, @@ -1073,7 +1073,7 @@ class PluginManagement extends OLDAdminSettings { uploadHelpText = ( ( { {msg} ), + strong: (msg: React.ReactNode) => {msg}, }} /> ); diff --git a/webapp/channels/src/components/admin_console/push_settings.tsx b/webapp/channels/src/components/admin_console/push_settings.tsx index 078070e424f..a2aee49217d 100644 --- a/webapp/channels/src/components/admin_console/push_settings.tsx +++ b/webapp/channels/src/components/admin_console/push_settings.tsx @@ -389,14 +389,14 @@ class PushSettings extends OLDAdminSettings { label={ } placeholder={defineMessage({id: 'admin.team.maxNotificationsPerChannelExample', defaultMessage: 'E.g.: "1000"'})} helpText={ } value={this.state.maxNotificationsPerChannel} diff --git a/webapp/channels/src/components/admin_console/request_button/request_button.tsx b/webapp/channels/src/components/admin_console/request_button/request_button.tsx index d1ecc37efef..80ec0df22e8 100644 --- a/webapp/channels/src/components/admin_console/request_button/request_button.tsx +++ b/webapp/channels/src/components/admin_console/request_button/request_button.tsx @@ -1,6 +1,8 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +/* eslint-disable formatjs/enforce-placeholders -- Admin request button uses runtime injection for error placeholder */ + import React from 'react'; import type {MessageDescriptor} from 'react-intl'; import {FormattedMessage, defineMessage} from 'react-intl'; diff --git a/webapp/channels/src/components/admin_console/session_length_settings.tsx b/webapp/channels/src/components/admin_console/session_length_settings.tsx index dd27c2c509b..d5184694afd 100644 --- a/webapp/channels/src/components/admin_console/session_length_settings.tsx +++ b/webapp/channels/src/components/admin_console/session_length_settings.tsx @@ -39,14 +39,14 @@ const messages = defineMessages({ extendSessionLengthActivity_label: {id: 'admin.service.extendSessionLengthActivity.label', defaultMessage: 'Extend session length with activity: '}, extendSessionLengthActivity_helpText: {id: 'admin.service.extendSessionLengthActivity.helpText', defaultMessage: 'When true, sessions will be automatically extended when the user is active in their Mattermost client. Users sessions will only expire if they are not active in their Mattermost client for the entire duration of the session lengths defined in the fields below. When false, sessions will not extend with activity in Mattermost. User sessions will immediately expire at the end of the session length or idle timeouts defined below. '}, terminateSessionsOnPasswordChange_label: {id: 'admin.service.terminateSessionsOnPasswordChange.label', defaultMessage: 'Terminate Sessions on Password Change: '}, - terminateSessionsOnPasswordChange_helpText: {id: 'admin.service.terminateSessionsOnPasswordChange.helpText', defaultMessage: 'When true, all sessions of a user will expire if their password is changed by themselves or an administrator.'}, + terminateSessionsOnPasswordChange_helpText: {id: 'admin.service.terminateSessionsOnPasswordChange.helpText', defaultMessage: 'When true, all sessions of a user will expire if their password is changed by themselves or an administrator. If password change is initiated by user, their current session is not terminated.'}, webSessionHours: {id: 'admin.service.webSessionHours', defaultMessage: 'Session Length AD/LDAP and Email (hours):'}, mobileSessionHours: {id: 'admin.service.mobileSessionHours', defaultMessage: 'Session Length Mobile (hours):'}, ssoSessionHours: {id: 'admin.service.ssoSessionHours', defaultMessage: 'Session Length SSO (hours):'}, sessionCache: {id: 'admin.service.sessionCache', defaultMessage: 'Session Cache (minutes):'}, sessionCacheDesc: {id: 'admin.service.sessionCacheDesc', defaultMessage: 'The number of minutes to cache a session in memory:'}, sessionHoursEx: {id: 'admin.service.sessionHoursEx', defaultMessage: 'E.g.: "720"'}, - sessionIdleTimeoutDesc: {id: 'admin.service.sessionIdleTimeoutDesc', defaultMessage: "The number of minutes from the last time a user was active on the system to the expiry of the user's session. Once expired, the user will need to log in to continue. Minimum is 5 minutes, and 0 is unlimited. Applies to the desktop app and browsers. For mobile apps, use an EMM provider to lock the app when not in use. In High Availability mode, enable IP hash load balancing for reliable timeout measurement."}, + sessionIdleTimeoutDesc: {id: 'admin.service.sessionIdleTimeoutDesc', defaultMessage: "The number of minutes from the last time a user was active on the system to the expiry of the user's session. Once expired, the user will need to log in to continue. Minimum is 5 minutes, and 0 is unlimited.\n \nApplies to the desktop app and browsers. For mobile apps, use an EMM provider to lock the app when not in use. In High Availability mode, enable IP hash load balancing for reliable timeout measurement."}, // eslint-disable-line formatjs/no-multiple-whitespaces }); export const searchableStrings = [ diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap index 0260f7827f8..a8546e3677f 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap @@ -180,7 +180,7 @@ exports[`admin_console/add_users_to_role_modal search should not include bot use perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } @@ -332,7 +332,7 @@ exports[`admin_console/add_users_to_role_modal should exclude user 1`] = ` perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } @@ -528,7 +528,7 @@ exports[`admin_console/add_users_to_role_modal should have single passed value 1 perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } @@ -765,7 +765,7 @@ exports[`admin_console/add_users_to_role_modal should include additional user 1` perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } @@ -1002,7 +1002,7 @@ exports[`admin_console/add_users_to_role_modal should include additional user 2` perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } @@ -1198,7 +1198,7 @@ exports[`admin_console/add_users_to_role_modal should not include bot user 1`] = perPage={50} placeholderText={ Object { - "defaultMessage": "Search and add members", + "defaultMessage": "Search for people", "id": "multiselect.placeholder", } } diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx index c8d47a6aa27..a28edf8170a 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx @@ -271,7 +271,7 @@ export class AddUsersToRoleModal extends React.PureComponent { buttonSubmitLoadingText={buttonSubmitLoadingText} saving={this.state.saving} loading={this.state.loading} - placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search and add members'})} + placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search for people'})} /> diff --git a/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx b/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx index c01ffc45a46..01995ae78d4 100644 --- a/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx +++ b/webapp/channels/src/components/admin_console/system_user_detail/system_user_detail.tsx @@ -868,7 +868,7 @@ export class SystemUserDetail extends PureComponent { { message={
{ return ( ); } @@ -38,14 +38,14 @@ export default class TeamRow extends React.PureComponent { return ( ); } return ( ); }; diff --git a/webapp/channels/src/components/admin_console/system_users/system_users_list_actions/deactivate_member_modal.tsx b/webapp/channels/src/components/admin_console/system_users/system_users_list_actions/deactivate_member_modal.tsx index 64d4059bc74..4907f9e6726 100644 --- a/webapp/channels/src/components/admin_console/system_users/system_users_list_actions/deactivate_member_modal.tsx +++ b/webapp/channels/src/components/admin_console/system_users/system_users_list_actions/deactivate_member_modal.tsx @@ -52,7 +52,7 @@ export default function DeactivateMemberModal({user, onExited, onSuccess, onErro const defaultMessage = ( ( } onClick={handleRemoveSessionsClick} diff --git a/webapp/channels/src/components/admin_console/system_users/utils/index.tsx b/webapp/channels/src/components/admin_console/system_users/utils/index.tsx index 829c754c669..0ed1215f53e 100644 --- a/webapp/channels/src/components/admin_console/system_users/utils/index.tsx +++ b/webapp/channels/src/components/admin_console/system_users/utils/index.tsx @@ -164,7 +164,7 @@ export function getDefaultSelectedTeam(teamId: Team['id'] | string, label?: stri label: ( ), }; @@ -174,7 +174,7 @@ export function getDefaultSelectedTeam(teamId: Team['id'] | string, label?: stri label: ( ), }; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_access_control_policy.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_access_control_policy.tsx index 6bfbeebdd8e..0c477d644d6 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_access_control_policy.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/details/channel_access_control_policy.tsx @@ -135,7 +135,7 @@ export const ChannelAccessControl: React.FC = (props: Props): JSX.Element return ( { diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/errors.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/errors.tsx index 8782554621d..a37da23ddc0 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/errors.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/errors.tsx @@ -65,7 +65,7 @@ export const UsersWillBeRemovedError = ({users, total, scope, scopeId}: UsersWil let error = ( ); diff --git a/webapp/channels/src/components/advanced_create_post/prewritten_chips.tsx b/webapp/channels/src/components/advanced_create_post/prewritten_chips.tsx index 2cbfdb9823e..d2f6e932d05 100644 --- a/webapp/channels/src/components/advanced_create_post/prewritten_chips.tsx +++ b/webapp/channels/src/components/advanced_create_post/prewritten_chips.tsx @@ -132,6 +132,7 @@ const PrewrittenChips = ({channelId, currentUserId, prefillMessage}: Props) => { event: 'prefilled_message_selected_dm_hey', message: defineMessage({ id: 'create_post.prewritten.tip.dm_hey_message', + // eslint-disable-next-line formatjs/enforce-placeholders -- username provided when message is formatted defaultMessage: ':wave: Hey @{username}', }), display: defineMessage({ diff --git a/webapp/channels/src/components/advanced_text_editor/priority_labels/index.tsx b/webapp/channels/src/components/advanced_text_editor/priority_labels/index.tsx index e8d9f5df4f6..1e3ec2d3dbb 100644 --- a/webapp/channels/src/components/advanced_text_editor/priority_labels/index.tsx +++ b/webapp/channels/src/components/advanced_text_editor/priority_labels/index.tsx @@ -79,7 +79,7 @@ function PriorityLabels({
diff --git a/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.test.tsx b/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.test.tsx index 0b6cd021d24..0672f56d27c 100644 --- a/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.test.tsx +++ b/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.test.tsx @@ -155,7 +155,7 @@ describe('ChannelSettingsArchiveTab', () => { // Use the within function to scope the query to just the modal content const modalBody = screen.getByTestId('archiveChannelConfirmModal').querySelector('#confirmModalBody'); expect(modalBody).toBeInTheDocument(); - expect(modalBody).toHaveTextContent(/Archiving a channel removes it from the user interface/); + expect(modalBody).toHaveTextContent(/This will archive the channel from the team/); }); it('should call deleteChannel which handles channel ID validation', async () => { diff --git a/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.tsx b/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.tsx index 7c4d5ebcda3..47eea23c2c1 100644 --- a/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.tsx +++ b/webapp/channels/src/components/channel_settings_modal/channel_settings_archive_tab.tsx @@ -66,7 +66,7 @@ function ChannelSettingsArchiveTab({

diff --git a/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx b/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx index 4635b3c49ce..32aa9078c5e 100644 --- a/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx +++ b/webapp/channels/src/components/channel_settings_modal/channel_settings_info_tab.tsx @@ -394,7 +394,7 @@ function ChannelSettingsInfoTab({ onChange={handlePurposeChange} createMessage={formatMessage({ id: 'channel_settings_modal.purpose.placeholder', - defaultMessage: 'Enter a purpose for this channel', + defaultMessage: 'Enter a purpose for this channel (optional)', })} maxLength={Constants.MAX_CHANNELPURPOSE_LENGTH} preview={shouldShowPreviewPurpose} @@ -408,7 +408,7 @@ function ChannelSettingsInfoTab({ hasError={channelPurpose.length > Constants.MAX_CHANNELPURPOSE_LENGTH} errorMessage={channelPurpose.length > Constants.MAX_CHANNELPURPOSE_LENGTH ? formatMessage({ id: 'channel_settings.error_purpose_length', - defaultMessage: 'The channel purpose exceeds the maximum character limit of {maxLength} characters.', + defaultMessage: 'The text entered exceeds the character limit. The channel purpose is limited to {maxLength} characters.', }, { maxLength: Constants.MAX_CHANNELPURPOSE_LENGTH, }) : undefined @@ -426,7 +426,7 @@ function ChannelSettingsInfoTab({ onChange={handleHeaderChange} createMessage={formatMessage({ id: 'channel_settings_modal.header.placeholder', - defaultMessage: 'Enter a header description or important links', + defaultMessage: 'Enter a header for this channel', })} maxLength={HEADER_MAX_LENGTH} preview={shouldShowPreviewHeader} @@ -440,7 +440,7 @@ function ChannelSettingsInfoTab({ hasError={channelHeader.length > HEADER_MAX_LENGTH} errorMessage={channelHeader.length > HEADER_MAX_LENGTH ? formatMessage({ id: 'edit_channel_header_modal.error', - defaultMessage: 'The channel header exceeds the maximum character limit of {maxLength} characters.', + defaultMessage: 'The text entered exceeds the character limit. The channel header is limited to {maxLength} characters.', }, { maxLength: HEADER_MAX_LENGTH, }) : undefined diff --git a/webapp/channels/src/components/channel_view/channel_view.tsx b/webapp/channels/src/components/channel_view/channel_view.tsx index 1fb7e3134fa..ee32ccd4d5e 100644 --- a/webapp/channels/src/components/channel_view/channel_view.tsx +++ b/webapp/channels/src/components/channel_view/channel_view.tsx @@ -179,9 +179,6 @@ export default class ChannelView extends React.PureComponent { {chunks}, - }} />

@@ -244,7 +244,7 @@ exports[`components/emoji/components/AddEmoji should select a file and match sna className="form__help" >
@@ -376,7 +376,7 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match className="form__help" > @@ -421,7 +421,7 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match className="form__help" > diff --git a/webapp/channels/src/components/emoji/add_emoji/add_emoji.tsx b/webapp/channels/src/components/emoji/add_emoji/add_emoji.tsx index 788a72cd34b..ec5450b72ab 100644 --- a/webapp/channels/src/components/emoji/add_emoji/add_emoji.tsx +++ b/webapp/channels/src/components/emoji/add_emoji/add_emoji.tsx @@ -173,7 +173,7 @@ export default class AddEmoji extends React.PureComponent ), }); @@ -326,7 +326,7 @@ export default class AddEmoji extends React.PureComponent @@ -362,7 +362,7 @@ export default class AddEmoji extends React.PureComponent diff --git a/webapp/channels/src/components/emoji_picker/components/emoji_picker_category_row.tsx b/webapp/channels/src/components/emoji_picker/components/emoji_picker_category_row.tsx index fc758faeb58..9565b00dd16 100644 --- a/webapp/channels/src/components/emoji_picker/components/emoji_picker_category_row.tsx +++ b/webapp/channels/src/components/emoji_picker/components/emoji_picker_category_row.tsx @@ -7,7 +7,7 @@ import {FormattedMessage} from 'react-intl'; import type {EmojiCategory} from '@mattermost/types/emojis'; -import {emojiCategories} from '../constants'; +import {EMOJI_CATEGORIES} from '../constants'; interface Props { categoryName: EmojiCategory; @@ -15,7 +15,7 @@ interface Props { } function EmojiPickerCategoryRow({categoryName, style}: Props) { - const category = emojiCategories[categoryName]; + const category = EMOJI_CATEGORIES[categoryName]; return (
; +} as const; -export const RECENT_EMOJI_CATEGORY: Pick = {recent: emojiCategories.recent}; -export const SEARCH_EMOJI_CATEGORY: Pick = {searchResults: emojiCategories.searchResults}; +const {recent, searchResults, ...standardCategories} = EMOJI_CATEGORIES; -export const CATEGORIES: Categories = Emoji.CategoryNames. - filter((category) => !(category === 'recent' || category === 'searchResults')). - reduce((previousCategory, currentCategory) => { - return { - ...previousCategory, - [currentCategory]: emojiCategories[currentCategory as EmojiCategory], - }; - }, {} as Categories); +export const RECENT_EMOJI_CATEGORY: Pick = {recent}; +export const SEARCH_EMOJI_CATEGORY: Pick = {searchResults}; + +// TODO CATEGORIES doesn't contain 'recent' or 'searchResults' as it's type claims +export const CATEGORIES = standardCategories as Categories; export const EMOJI_PER_ROW = 9; // needs to match variable `$emoji-per-row` in _variables.scss export const ITEM_HEIGHT = 36; //as per .emoji-picker__item height in _emoticons.scss diff --git a/webapp/channels/src/components/emoji_picker/emoji_picker.test.tsx b/webapp/channels/src/components/emoji_picker/emoji_picker.test.tsx index eb3c6fcc9c3..86fe9a42972 100644 --- a/webapp/channels/src/components/emoji_picker/emoji_picker.test.tsx +++ b/webapp/channels/src/components/emoji_picker/emoji_picker.test.tsx @@ -64,7 +64,7 @@ describe('components/emoji_picker/EmojiPicker', () => { , ); - expect(screen.queryByLabelText('Recent')).not.toBeNull(); + expect(screen.queryByLabelText('Recently Used')).not.toBeNull(); }); test('First emoji should be selected on search', () => { diff --git a/webapp/channels/src/components/emoji_picker/types/index.ts b/webapp/channels/src/components/emoji_picker/types/index.ts index 6be32984c80..bfe120e4690 100644 --- a/webapp/channels/src/components/emoji_picker/types/index.ts +++ b/webapp/channels/src/components/emoji_picker/types/index.ts @@ -18,6 +18,7 @@ export type Category = { }; export type Categories = Record; +export type ListedCategories = Omit & Partial>; export type CategoryOrEmojiRow = CategoryHeaderRow | EmojiRow; diff --git a/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.tsx b/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.tsx index b2c0ae4f3c2..19f2e4938cf 100644 --- a/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.tsx +++ b/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.tsx @@ -71,7 +71,7 @@ const FeatureRestrictedModal = ({ const [notifyAdminBtnText, notifyAdmin, notifyRequestStatus] = useNotifyAdmin({ ctaText: formatMessage({ id: 'feature_restricted_modal.button.notify', - defaultMessage: 'Notify Admin', + defaultMessage: 'Notify admin', }), }, { required_feature: feature || '', @@ -152,7 +152,7 @@ const FeatureRestrictedModal = ({

( diff --git a/webapp/channels/src/components/flag_message_modal/flag_post_modal.test.tsx b/webapp/channels/src/components/flag_message_modal/flag_post_modal.test.tsx index a35e1568612..d5a576b280d 100644 --- a/webapp/channels/src/components/flag_message_modal/flag_post_modal.test.tsx +++ b/webapp/channels/src/components/flag_message_modal/flag_post_modal.test.tsx @@ -56,7 +56,7 @@ describe('components/FlagPostModal', () => { baseState, ); - await userEvent.click(screen.getByText('Select a reason for flagging')); + await userEvent.click(screen.getByText('Select a reason')); expect(screen.getByText('Reason 1')).toBeVisible(); expect(screen.getByText('Reason 2')).toBeVisible(); @@ -107,7 +107,7 @@ describe('components/FlagPostModal', () => { ); // Select a reason - await userEvent.click(screen.getByText('Select a reason for flagging')); + await userEvent.click(screen.getByText('Select a reason')); await userEvent.click(screen.getByText('Reason 1')); // Add a comment diff --git a/webapp/channels/src/components/flag_message_modal/flag_post_modal.tsx b/webapp/channels/src/components/flag_message_modal/flag_post_modal.tsx index c64ca3c343b..7e59dd57219 100644 --- a/webapp/channels/src/components/flag_message_modal/flag_post_modal.tsx +++ b/webapp/channels/src/components/flag_message_modal/flag_post_modal.tsx @@ -54,11 +54,11 @@ export default function FlagPostModal({postId, onExited}: Props) { const [showCommentPreview, setShowCommentPreview] = React.useState(false); const label = formatMessage({id: 'flag_message_modal.heading', defaultMessage: 'Flag message'}); - const subHeading = formatMessage({id: 'flag_message_modal.subheading', defaultMessage: 'Flagged messages will be sent to Content Reviewers for review'}); + const subHeading = formatMessage({id: 'flag_message_modal.subheading', defaultMessage: 'Flagged messages will be sent to Content Reviewers for review.'}); const submitButtonText = formatMessage({id: 'generic.submit', defaultMessage: 'Submit'}); const requiredCommentSectionTitle = formatMessage({id: 'flag_message_modal.required_comment.title', defaultMessage: 'Comment (required)'}); const optionalCommentSectionTitle = formatMessage({id: 'flag_message_modal.optional_comment.title', defaultMessage: 'Comment (optional)'}); - const reasonSelectPlaceholder = formatMessage({id: 'flag_message_modal.reason_select.placeholder', defaultMessage: 'Select a reason for flagging'}); + const reasonSelectPlaceholder = formatMessage({id: 'flag_message_modal.reason_select.placeholder', defaultMessage: 'Select a reason'}); const commentPlaceholder = formatMessage({id: 'flag_message_modal.comment.placeholder', defaultMessage: 'Describe your concern...'}); const post = useSelector((state: GlobalState) => getPost(state, postId)); diff --git a/webapp/channels/src/components/forward_post_modal/index.tsx b/webapp/channels/src/components/forward_post_modal/index.tsx index b0fc926e1f4..d2102c0207d 100644 --- a/webapp/channels/src/components/forward_post_modal/index.tsx +++ b/webapp/channels/src/components/forward_post_modal/index.tsx @@ -162,7 +162,6 @@ const ForwardPostModal = ({onExited, post}: Props) => { defaultMessage='This message is from a private conversation and can only be shared with {participants}' values={{ participants: , - strong: (x: React.ReactNode) => {x}, }} /> ); diff --git a/webapp/channels/src/components/integrations/__snapshots__/abstract_command.test.tsx.snap b/webapp/channels/src/components/integrations/__snapshots__/abstract_command.test.tsx.snap index d70e6f18bde..01878c0385a 100644 --- a/webapp/channels/src/components/integrations/__snapshots__/abstract_command.test.tsx.snap +++ b/webapp/channels/src/components/integrations/__snapshots__/abstract_command.test.tsx.snap @@ -282,7 +282,7 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = ` className="form__help" >

@@ -765,7 +765,7 @@ exports[`components/integrations/AbstractCommand should match snapshot when head className="form__help" > @@ -1243,7 +1243,7 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays className="form__help" > diff --git a/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap b/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap index 4adfbfe6b3e..09935c5917a 100644 --- a/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap +++ b/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap @@ -181,7 +181,7 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func className="form__help" > @@ -446,7 +446,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot 1 className="form__help" > @@ -711,7 +711,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot w className="form__help" > @@ -976,7 +976,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot, className="form__help" > @@ -1244,7 +1244,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot, className="form__help" > @@ -1708,7 +1708,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot, className="form__help" > diff --git a/webapp/channels/src/components/integrations/__snapshots__/abstract_oauth_app.test.tsx.snap b/webapp/channels/src/components/integrations/__snapshots__/abstract_oauth_app.test.tsx.snap index 0d17d874fc2..5960d3829cd 100644 --- a/webapp/channels/src/components/integrations/__snapshots__/abstract_oauth_app.test.tsx.snap +++ b/webapp/channels/src/components/integrations/__snapshots__/abstract_oauth_app.test.tsx.snap @@ -9,7 +9,7 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot 1`] = ` to="/test/integrations/oauth2-apps" > @@ -375,7 +375,7 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot, display to="/test/integrations/oauth2-apps" > diff --git a/webapp/channels/src/components/integrations/abstract_command.tsx b/webapp/channels/src/components/integrations/abstract_command.tsx index 1bb42993917..aea2ddf2a9f 100644 --- a/webapp/channels/src/components/integrations/abstract_command.tsx +++ b/webapp/channels/src/components/integrations/abstract_command.tsx @@ -609,7 +609,7 @@ export default class AbstractCommand extends React.PureComponent {
diff --git a/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx b/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx index e0f60aebba5..91f07009caf 100644 --- a/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx +++ b/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx @@ -335,7 +335,7 @@ export default class AbstractIncomingWebhook extends PureComponent
diff --git a/webapp/channels/src/components/integrations/abstract_oauth_app.tsx b/webapp/channels/src/components/integrations/abstract_oauth_app.tsx index 19c89ceda0d..7dffb62f745 100644 --- a/webapp/channels/src/components/integrations/abstract_oauth_app.tsx +++ b/webapp/channels/src/components/integrations/abstract_oauth_app.tsx @@ -375,7 +375,7 @@ export default class AbstractOAuthApp extends React.PureComponent diff --git a/webapp/channels/src/components/integrations/add_command/add_command.tsx b/webapp/channels/src/components/integrations/add_command/add_command.tsx index c268b4c695e..756dd970779 100644 --- a/webapp/channels/src/components/integrations/add_command/add_command.tsx +++ b/webapp/channels/src/components/integrations/add_command/add_command.tsx @@ -3,7 +3,6 @@ import React, {useState} from 'react'; import {useIntl} from 'react-intl'; -import type {MessageDescriptor} from 'react-intl'; import {useHistory} from 'react-router-dom'; import type {Command} from '@mattermost/types/integrations'; @@ -32,9 +31,9 @@ export type Props = { const AddCommand = ({team, actions}: Props) => { const history = useHistory(); const {formatMessage} = useIntl(); - const headerMessage = formatMessage({id: ('integrations.add'), defaultMessage: 'Add'}) as MessageDescriptor; - const footerMessage = formatMessage({id: ('add_command.save'), defaultMessage: 'Save'}) as MessageDescriptor; - const loadingMessage = formatMessage({id: ('add_command.saving'), defaultMessage: 'Saving...'}) as MessageDescriptor; + const headerMessage = formatMessage({id: 'integrations.add', defaultMessage: 'Add'}); + const footerMessage = formatMessage({id: 'add_command.save', defaultMessage: 'Save'}); + const loadingMessage = formatMessage({id: 'add_command.saving', defaultMessage: 'Saving...'}); const [serverError, setServerError] = useState(''); const addCommand = async (command: Command) => { diff --git a/webapp/channels/src/components/integrations/bots/bots.tsx b/webapp/channels/src/components/integrations/bots/bots.tsx index 340bed7305b..298e518d0e6 100644 --- a/webapp/channels/src/components/integrations/bots/bots.tsx +++ b/webapp/channels/src/components/integrations/bots/bots.tsx @@ -237,6 +237,7 @@ export default class Bots extends React.PureComponent { emptyTextSearch={ {chunks}, diff --git a/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap b/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap index aa8c2e94236..8ba93d23cd9 100644 --- a/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap +++ b/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap @@ -206,7 +206,7 @@ exports[`components/integrations/ConfirmIntegration should match snapshot, oauth key="add_oauth_app.doneHelp" > @@ -450,12 +450,11 @@ exports[`components/integrations/ConfirmIntegration should match snapshot, outgo />
diff --git a/webapp/channels/src/components/integrations/confirm_integration/confirm_integration.tsx b/webapp/channels/src/components/integrations/confirm_integration/confirm_integration.tsx index c16dc464c5b..50b62119903 100644 --- a/webapp/channels/src/components/integrations/confirm_integration/confirm_integration.tsx +++ b/webapp/channels/src/components/integrations/confirm_integration/confirm_integration.tsx @@ -208,7 +208,7 @@ const ConfirmIntegration = ({team, location, commands, oauthApps, incomingHooks,

( ( ); @@ -343,9 +342,8 @@ const ConfirmIntegration = ({team, location, commands, oauthApps, incomingHooks,
{chunks}, }} /> @@ -417,10 +415,10 @@ const ConfirmIntegration = ({team, location, commands, oauthApps, incomingHooks,

{msg}, + strong: (msg) => {msg}, link: (msg) => ( { header={ } addText={ @@ -102,12 +102,13 @@ export default class InstalledCommands extends React.PureComponent { emptyText={ } emptyTextSearch={ {chunks}, diff --git a/webapp/channels/src/components/integrations/installed_incoming_webhooks/installed_incoming_webhooks.tsx b/webapp/channels/src/components/integrations/installed_incoming_webhooks/installed_incoming_webhooks.tsx index e4b329835b3..137c3cb57e5 100644 --- a/webapp/channels/src/components/integrations/installed_incoming_webhooks/installed_incoming_webhooks.tsx +++ b/webapp/channels/src/components/integrations/installed_incoming_webhooks/installed_incoming_webhooks.tsx @@ -124,7 +124,7 @@ export default class InstalledIncomingWebhooks extends React.PureComponent } addText={ @@ -144,7 +144,11 @@ export default class InstalledIncomingWebhooks extends React.PureComponent {chunks}, + }} /> } helpText={ diff --git a/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap b/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap index c4c70f1f908..9254d5ae4ca 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap +++ b/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap @@ -13,8 +13,13 @@ exports[`components/integrations/InstalledOAuthApps should match snapshot 1`] = } emptyTextSearch={ } header={ diff --git a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx index 37c117e25ee..137229490dc 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx +++ b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx @@ -184,7 +184,13 @@ export default class InstalledOAuthApps extends React.PureComponent {chunks}, + }} /> } searchPlaceholder={localizeMessage({id: 'installed_oauth_apps.search', defaultMessage: 'Search OAuth 2.0 Applications'})} diff --git a/webapp/channels/src/components/integrations/installed_outgoing_webhooks/__snapshots__/installed_outgoing_webhooks.test.tsx.snap b/webapp/channels/src/components/integrations/installed_outgoing_webhooks/__snapshots__/installed_outgoing_webhooks.test.tsx.snap index b44d149ed3d..be857981ef4 100644 --- a/webapp/channels/src/components/integrations/installed_outgoing_webhooks/__snapshots__/installed_outgoing_webhooks.test.tsx.snap +++ b/webapp/channels/src/components/integrations/installed_outgoing_webhooks/__snapshots__/installed_outgoing_webhooks.test.tsx.snap @@ -252,7 +252,7 @@ exports[`components/integrations/InstalledOutgoingWebhooks should match snapshot } header={ } diff --git a/webapp/channels/src/components/integrations/installed_outgoing_webhooks/installed_outgoing_webhooks.tsx b/webapp/channels/src/components/integrations/installed_outgoing_webhooks/installed_outgoing_webhooks.tsx index 38fee6525ae..0da6ca38461 100644 --- a/webapp/channels/src/components/integrations/installed_outgoing_webhooks/installed_outgoing_webhooks.tsx +++ b/webapp/channels/src/components/integrations/installed_outgoing_webhooks/installed_outgoing_webhooks.tsx @@ -162,7 +162,7 @@ export default class InstalledOutgoingWebhooks extends React.PureComponent } addText={ @@ -186,6 +186,9 @@ export default class InstalledOutgoingWebhooks extends React.PureComponent {chunks}, diff --git a/webapp/channels/src/components/integrations/integrations.tsx b/webapp/channels/src/components/integrations/integrations.tsx index e9e6ee6876f..910feff65ed 100644 --- a/webapp/channels/src/components/integrations/integrations.tsx +++ b/webapp/channels/src/components/integrations/integrations.tsx @@ -120,7 +120,7 @@ export default class Integrations extends React.PureComponent { description={ } link={'/' + this.props.team.name + '/integrations/commands'} @@ -147,7 +147,7 @@ export default class Integrations extends React.PureComponent { description={ } link={'/' + this.props.team.name + '/integrations/oauth2-apps'} diff --git a/webapp/channels/src/components/integrations/outgoing_oauth_connections/installed_outgoing_oauth_connections.tsx b/webapp/channels/src/components/integrations/outgoing_oauth_connections/installed_outgoing_oauth_connections.tsx index 6f6781446ab..86eaa6486e3 100644 --- a/webapp/channels/src/components/integrations/outgoing_oauth_connections/installed_outgoing_oauth_connections.tsx +++ b/webapp/channels/src/components/integrations/outgoing_oauth_connections/installed_outgoing_oauth_connections.tsx @@ -131,6 +131,7 @@ const InstalledOutgoingOAuthConnections = (props: Props) => { emptyTextSearch={ } diff --git a/webapp/channels/src/components/interactive_dialog/interactive_dialog.tsx b/webapp/channels/src/components/interactive_dialog/interactive_dialog.tsx index 3b294d0de4e..b63c7bffbcf 100644 --- a/webapp/channels/src/components/interactive_dialog/interactive_dialog.tsx +++ b/webapp/channels/src/components/interactive_dialog/interactive_dialog.tsx @@ -74,8 +74,7 @@ export default class InteractiveDialog extends React.PureComponent if (error) { errors[elem.name] = ( ); diff --git a/webapp/channels/src/components/intl_provider/intl_provider.tsx b/webapp/channels/src/components/intl_provider/intl_provider.tsx index 9f8ec2b3c29..0d040a981a2 100644 --- a/webapp/channels/src/components/intl_provider/intl_provider.tsx +++ b/webapp/channels/src/components/intl_provider/intl_provider.tsx @@ -1,15 +1,16 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react'; +import React, {useEffect} from 'react'; import type {ReactNode} from 'react'; -import {IntlProvider as BaseIntlProvider} from 'react-intl'; +import {IntlProvider as BaseIntlProvider, useIntl} from 'react-intl'; import type {IntlConfig} from 'react-intl'; import {Client4} from 'mattermost-redux/client'; import {setLocalizeFunction} from 'mattermost-redux/utils/i18n_utils'; import * as I18n from 'i18n/i18n'; +import {setIntl} from 'utils/i18n'; import {localizeMessage} from 'utils/utils'; type Props = { @@ -21,6 +22,20 @@ type Props = { }; }; +/** + * Captures the intl instance from BaseIntlProvider and stores it + * so that getIntl() can return the same instance. + */ +function IntlCapture() { + const intl = useIntl(); + + useEffect(() => { + setIntl(intl); + }, [intl]); + + return null; +} + export default class IntlProvider extends React.PureComponent { componentDidMount() { // Pass localization function back to mattermost-redux @@ -68,6 +83,7 @@ export default class IntlProvider extends React.PureComponent { textComponent='span' wrapRichTextChunksInFragment={false} > + {this.props.children} ); diff --git a/webapp/channels/src/components/keyboard_shortcuts/keyboard_shortcuts_sequence/keyboard_shortcuts.ts b/webapp/channels/src/components/keyboard_shortcuts/keyboard_shortcuts_sequence/keyboard_shortcuts.ts index 65f4d0c4108..d093716cf0f 100644 --- a/webapp/channels/src/components/keyboard_shortcuts/keyboard_shortcuts_sequence/keyboard_shortcuts.ts +++ b/webapp/channels/src/components/keyboard_shortcuts/keyboard_shortcuts_sequence/keyboard_shortcuts.ts @@ -316,21 +316,21 @@ export const KEYBOARD_SHORTCUTS = { msgMarkdownCode: defineMessages({ default: { id: 'shortcuts.msgs.markdown.code', - defaultMessage: 'Code', + defaultMessage: 'Code:\tCtrl|Alt|C', }, mac: { id: 'shortcuts.msgs.markdown.code.mac', - defaultMessage: 'Code', + defaultMessage: 'Code:\t⌘|⌥|C', }, }), msgMarkdownStrike: defineMessages({ default: { id: 'shortcuts.msgs.markdown.strike', - defaultMessage: 'Strikethrough:\tCtrl|Shift|X', + defaultMessage: 'Strikethrough:\tShift|Alt|X', }, mac: { id: 'shortcuts.msgs.markdown.strike.mac', - defaultMessage: 'Strikethrough:\t⌘|Shift|X', + defaultMessage: 'Strikethrough:\tShift|⌥|X', }, }), msgMarkdownH3: defineMessages({ @@ -346,31 +346,31 @@ export const KEYBOARD_SHORTCUTS = { msgMarkdownQuote: defineMessages({ default: { id: 'shortcuts.msgs.markdown.quote', - defaultMessage: 'Quote', + defaultMessage: 'Quote:\tShift|Alt|9', }, mac: { id: 'shortcuts.msgs.markdown.quote.mac', - defaultMessage: 'Quote', + defaultMessage: 'Quote:\tShift|⌥|9', }, }), msgMarkdownOl: defineMessages({ default: { id: 'shortcuts.msgs.markdown.ordered', - defaultMessage: 'Numbered List', + defaultMessage: 'Numbered List:\tShift|Alt|7', }, mac: { id: 'shortcuts.msgs.markdown.ordered.mac', - defaultMessage: 'Numbered List', + defaultMessage: 'Numbered List:\tShift|⌥|7', }, }), msgMarkdownUl: defineMessages({ default: { id: 'shortcuts.msgs.markdown.unordered', - defaultMessage: 'Bulleted List', + defaultMessage: 'Bulleted List\tShift|Alt|8', }, mac: { id: 'shortcuts.msgs.markdown.unordered.mac', - defaultMessage: 'Bulleted List', + defaultMessage: 'Bulleted List:\tShift|⌥|8', }, }), msgShowFormatting: defineMessages({ @@ -396,11 +396,11 @@ export const KEYBOARD_SHORTCUTS = { msgShowEmojiPicker: defineMessages({ default: { id: 'shortcuts.msgs.markdown.emoji', - defaultMessage: 'Emoji / Gif picker:\tCtrl|Shift|E', + defaultMessage: 'Emoji / Gif picker:\tCtrl|Alt|E', }, mac: { id: 'shortcuts.msgs.markdown.emoji.mac', - defaultMessage: 'Emoji / Gif picker:\t⌘|Shift|E', + defaultMessage: 'Emoji / Gif picker:\t⌘|⌥|E', }, }), msgMarkdownPreview: defineMessages({ @@ -410,7 +410,7 @@ export const KEYBOARD_SHORTCUTS = { }, mac: { id: 'shortcuts.msgs.markdown.preview.mac', - defaultMessage: 'Show/Hide Preview:\t⌘|Shift|P', + defaultMessage: 'Show/Hide Preview:\t⌘|⌥|P', }, }), msgMarkdownItalic: defineMessages({ diff --git a/webapp/channels/src/components/latex_block/latex_block.tsx b/webapp/channels/src/components/latex_block/latex_block.tsx index 836f70ee74e..f1cd8fd5025 100644 --- a/webapp/channels/src/components/latex_block/latex_block.tsx +++ b/webapp/channels/src/components/latex_block/latex_block.tsx @@ -62,7 +62,7 @@ const LatexBlock = ({ > ); diff --git a/webapp/channels/src/components/latex_inline/latex_inline.tsx b/webapp/channels/src/components/latex_inline/latex_inline.tsx index 7ed814a49bb..305aa8d742e 100644 --- a/webapp/channels/src/components/latex_inline/latex_inline.tsx +++ b/webapp/channels/src/components/latex_inline/latex_inline.tsx @@ -58,7 +58,7 @@ const LatexInline = ({content, enableInlineLatex}: Props) => { > ); diff --git a/webapp/channels/src/components/leave_team_modal/leave_team_modal.tsx b/webapp/channels/src/components/leave_team_modal/leave_team_modal.tsx index ebacb84f66a..50f4dd8cfb3 100644 --- a/webapp/channels/src/components/leave_team_modal/leave_team_modal.tsx +++ b/webapp/channels/src/components/leave_team_modal/leave_team_modal.tsx @@ -83,7 +83,7 @@ export default class LeaveTeamModal extends React.PureComponent { modalMessage = ( { modalMessage = ( {chunks}, @@ -106,7 +106,7 @@ export default class LeaveTeamModal extends React.PureComponent { modalMessage = ( {chunks}, @@ -118,7 +118,7 @@ export default class LeaveTeamModal extends React.PureComponent { modalMessage = ( { modalMessage = ( {chunks}, diff --git a/webapp/channels/src/components/login/__snapshots__/login_mfa.test.tsx.snap b/webapp/channels/src/components/login/__snapshots__/login_mfa.test.tsx.snap index e24bd985b0c..0ba11e87079 100644 --- a/webapp/channels/src/components/login/__snapshots__/login_mfa.test.tsx.snap +++ b/webapp/channels/src/components/login/__snapshots__/login_mfa.test.tsx.snap @@ -14,7 +14,7 @@ exports[`components/login/LoginMfa should match snapshot 1`] = ` inputSize="large" name="token" onChange={[Function]} - placeholder="Enter MFA Token" + placeholder="MFA Token" type="text" value="" /> diff --git a/webapp/channels/src/components/login/login.tsx b/webapp/channels/src/components/login/login.tsx index 54477b96c89..f44c9185e01 100644 --- a/webapp/channels/src/components/login/login.tsx +++ b/webapp/channels/src/components/login/login.tsx @@ -48,7 +48,6 @@ import PasswordInput from 'components/widgets/inputs/password_input/password_inp import Constants from 'utils/constants'; import DesktopApp from 'utils/desktop_api'; import {isEmbedded} from 'utils/embed'; -import {t} from 'utils/i18n'; import {DesktopNotificationSounds} from 'utils/notification_sounds'; import {showNotification} from 'utils/notifications'; import {isDesktopApp} from 'utils/user_agent'; @@ -372,7 +371,7 @@ const Login = ({onCustomizeHeader}: LoginProps) => { mode = 'danger'; title = formatMessage({ id: 'login.get_terms_error', - defaultMessage: 'Unable to load terms of service. If this issue persists, contact your System Administrator.', + defaultMessage: 'Unable to load terms of use. If this issue persists, contact your System Administrator.', }); break; @@ -610,33 +609,42 @@ const Login = ({onCustomizeHeader}: LoginProps) => { currentLoginId = currentLoginId.trim().toLowerCase(); if (!currentLoginId) { - t('login.noEmail'); - t('login.noEmailLdapUsername'); - t('login.noEmailUsername'); - t('login.noEmailUsernameLdapUsername'); - t('login.noLdapUsername'); - t('login.noUsername'); - t('login.noUsernameLdapUsername'); + const ldapUsername = LdapLoginFieldName || formatMessage({id: 'login.ldapUsernameLower', defaultMessage: 'AD/LDAP username'}); - // it's slightly weird to be constructing the message ID, but it's a bit nicer than triply nested if statements - let msgId = 'login.no'; - if (enableSignInWithEmail) { - msgId += 'Email'; - } - if (enableSignInWithUsername) { - msgId += 'Username'; - } - if (ldapEnabled) { - msgId += 'LdapUsername'; + let title; + + // 3 methods, 2 methods, 1 method - Keep in mind order of cases. + switch (true) { + // three login methods enabled + case enableSignInWithEmail && enableSignInWithUsername && ldapEnabled: + title = formatMessage({id: 'login.noEmailUsernameLdapUsername', defaultMessage: 'Please enter your email, username or {ldapUsername}'}, {ldapUsername}); + break; + + // two login methods enabled + case enableSignInWithEmail && enableSignInWithUsername: + title = formatMessage({id: 'login.noEmailUsername', defaultMessage: 'Please enter your email or username'}); + break; + case enableSignInWithEmail && ldapEnabled: + title = formatMessage({id: 'login.noEmailLdapUsername', defaultMessage: 'Please enter your email or {ldapUsername}'}, {ldapUsername}); + break; + case enableSignInWithUsername && ldapEnabled: + title = formatMessage({id: 'login.noUsernameLdapUsername', defaultMessage: 'Please enter your username or {ldapUsername}'}, {ldapUsername}); + break; + + // one login method enabled + case enableSignInWithEmail: + title = formatMessage({id: 'login.noEmail', defaultMessage: 'Please enter your email'}); + break; + case ldapEnabled: + title = formatMessage({id: 'login.noLdapUsername', defaultMessage: 'Please enter your {ldapUsername}'}, {ldapUsername}); + break; + case enableSignInWithUsername: + default: + title = formatMessage({id: 'login.noUsername', defaultMessage: 'Please enter your username'}); + break; } - setAlertBanner({ - mode: 'danger', - title: formatMessage( - {id: msgId}, - {ldapUsername: LdapLoginFieldName || formatMessage({id: 'login.ldapUsernameLower', defaultMessage: 'AD/LDAP username'})}, - ), - }); + setAlertBanner({mode: 'danger', title}); setHasError(true); setIsWaiting(false); diff --git a/webapp/channels/src/components/login/login_mfa.tsx b/webapp/channels/src/components/login/login_mfa.tsx index bd2a4906ea9..81a2b14a55e 100644 --- a/webapp/channels/src/components/login/login_mfa.tsx +++ b/webapp/channels/src/components/login/login_mfa.tsx @@ -60,7 +60,7 @@ const LoginMfa = ({loginId, password, title, subtitle, onSubmit}: LoginMfaProps) inputSize={SIZE.LARGE} value={token} onChange={handleInputOnChange} - placeholder={formatMessage({id: 'login_mfa.token', defaultMessage: 'Enter MFA Token'})} + placeholder={formatMessage({id: 'login_mfa.token', defaultMessage: 'MFA Token'})} autoFocus={true} disabled={saving} /> diff --git a/webapp/channels/src/components/mfa/setup/__snapshots__/setup.test.tsx.snap b/webapp/channels/src/components/mfa/setup/__snapshots__/setup.test.tsx.snap index 756f88f38cc..3955bca306b 100644 --- a/webapp/channels/src/components/mfa/setup/__snapshots__/setup.test.tsx.snap +++ b/webapp/channels/src/components/mfa/setup/__snapshots__/setup.test.tsx.snap @@ -57,11 +57,6 @@ exports[`components/mfa/setup should match snapshot without required text 1`] =

diff --git a/webapp/channels/src/components/mfa/setup/setup.tsx b/webapp/channels/src/components/mfa/setup/setup.tsx index 8055263a3af..827aa82d4ee 100644 --- a/webapp/channels/src/components/mfa/setup/setup.tsx +++ b/webapp/channels/src/components/mfa/setup/setup.tsx @@ -211,9 +211,6 @@ export default class Setup extends React.PureComponent { {chunks}, - }} />

diff --git a/webapp/channels/src/components/more_direct_channels/list/list.tsx b/webapp/channels/src/components/more_direct_channels/list/list.tsx index 53772e34dfc..26a16b77ea3 100644 --- a/webapp/channels/src/components/more_direct_channels/list/list.tsx +++ b/webapp/channels/src/components/more_direct_channels/list/list.tsx @@ -166,7 +166,7 @@ const List = React.forwardRef((props: Props, ref?: React.Ref ); }); diff --git a/webapp/channels/src/components/onboarding_tasklist/__snapshots__/onboarding_tasklist_completed.test.tsx.snap b/webapp/channels/src/components/onboarding_tasklist/__snapshots__/onboarding_tasklist_completed.test.tsx.snap index 9d41e532632..4c3b701f237 100644 --- a/webapp/channels/src/components/onboarding_tasklist/__snapshots__/onboarding_tasklist_completed.test.tsx.snap +++ b/webapp/channels/src/components/onboarding_tasklist/__snapshots__/onboarding_tasklist_completed.test.tsx.snap @@ -57,7 +57,7 @@ exports[`components/onboarding_tasklist/onboarding_tasklist_completed.tsx should > { > diff --git a/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_completed.tsx b/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_completed.tsx index 52ab0937663..7d3c9c37365 100644 --- a/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_completed.tsx +++ b/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist_completed.tsx @@ -216,7 +216,7 @@ const Completed = (props: Props): JSX.Element => { ( { ( ,

,

@@ -151,7 +151,7 @@ export const UpdateConfirmationModal = ({show, name, version, installedVersion,

, diff --git a/webapp/channels/src/components/post_markdown/system_message_helpers.tsx b/webapp/channels/src/components/post_markdown/system_message_helpers.tsx index fa19601c7c9..80d6540972d 100644 --- a/webapp/channels/src/components/post_markdown/system_message_helpers.tsx +++ b/webapp/channels/src/components/post_markdown/system_message_helpers.tsx @@ -78,7 +78,7 @@ function renderLeaveChannelMessage(post: Post): ReactNode { return ( ); @@ -164,7 +164,7 @@ function renderAddToTeamMessage(post: Post): ReactNode { return ( ); @@ -360,7 +360,7 @@ function renderChannelUnarchivedMessage(post: Post): ReactNode { return ( ); diff --git a/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx b/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx index 9bf6d8f102b..399ab07c39a 100644 --- a/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx +++ b/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx @@ -125,7 +125,7 @@ describe('components/post_view/ChannelIntroMessages', () => { expect(screen.queryByText('Any member can join and read this channel.')).not.toBeInTheDocument(); // there are no profiles in the dom, channel type is GM_CHANNEL, teammate text should be displayed - expect(screen.getByText('This is the start of your group message history with these teammates. ', {exact: false})).toBeInTheDocument(); + expect(screen.getByText('This is the start of your group message history with these teammates.', {exact: false})).toBeInTheDocument(); expect(screen.getByText('This is the start of your', {exact: false})).toHaveClass('channel-intro__text'); }); diff --git a/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.tsx b/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.tsx index 7ef9c7e737f..14a0e6dc862 100644 --- a/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.tsx +++ b/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.tsx @@ -228,7 +228,7 @@ function createGMIntroMessage(

@@ -530,7 +530,6 @@ function createStandardIntroMessage( locale: string, creatorName: string, ) { - const uiName = channel.display_name; let memberMessage; let teamInviteLink = null; const channelIsArchived = channel.delete_at !== 0; @@ -577,7 +576,7 @@ function createStandardIntroMessage( ); } else if (channel.type === Constants.OPEN_CHANNEL) { @@ -585,7 +584,7 @@ function createStandardIntroMessage( ); } @@ -596,7 +595,6 @@ function createStandardIntroMessage( id='intro_messages.creatorPrivate' defaultMessage='Private channel created by {creator} on {date}.' values={{ - name: (uiName), creator: (creatorName), date, }} @@ -610,7 +608,6 @@ function createStandardIntroMessage( id='intro_messages.creator' defaultMessage='Public channel created by {creator} on {date}.' values={{ - name: (uiName), creator: (creatorName), date, }} @@ -755,7 +752,7 @@ function createNotificationPreferencesButton(channel: Channel, currentUser: User diff --git a/webapp/channels/src/components/post_view/post_list_row/post_list_row.tsx b/webapp/channels/src/components/post_view/post_list_row/post_list_row.tsx index ef01466ed05..47b032b040d 100644 --- a/webapp/channels/src/components/post_view/post_list_row/post_list_row.tsx +++ b/webapp/channels/src/components/post_view/post_list_row/post_list_row.tsx @@ -138,7 +138,7 @@ export default class PostListRow extends React.PureComponent { > ); diff --git a/webapp/channels/src/components/preparing_workspace/plugins.tsx b/webapp/channels/src/components/preparing_workspace/plugins.tsx index 51e12f764f7..6eb6ce279a7 100644 --- a/webapp/channels/src/components/preparing_workspace/plugins.tsx +++ b/webapp/channels/src/components/preparing_workspace/plugins.tsx @@ -105,7 +105,7 @@ const Plugins = (props: Props) => { checked: props.options.gitlab, tooltip: formatMessage({ id: 'onboarding_wizard.plugins.gitlab.tooltip', - defaultMessage: 'GitLab tooltip', + defaultMessage: 'Subscribe to repositories, stay up-to-date with reviews, assignments and more', }), }, { @@ -119,7 +119,7 @@ const Plugins = (props: Props) => { checked: props.options.jira, tooltip: formatMessage({ id: 'onboarding_wizard.plugins.jira.tooltip', - defaultMessage: 'Jira tooltip', + defaultMessage: 'Create Jira tickets from messages in Mattermost, get notified of important updates in Jira', }), }, { @@ -133,7 +133,7 @@ const Plugins = (props: Props) => { checked: props.options.zoom, tooltip: formatMessage({ id: 'onboarding_wizard.plugins.zoom.tooltip', - defaultMessage: 'Zoom tooltip', + defaultMessage: 'Start Zoom audio and video conferencing calls in Mattermost with a single click', }), }, { @@ -147,7 +147,7 @@ const Plugins = (props: Props) => { checked: props.options.servicenow, tooltip: formatMessage({ id: 'onboarding_wizard.plugins.servicenow.tooltip', - defaultMessage: 'ServiceNow tooltip', + defaultMessage: 'This plugin serves as an integration between Mattermost and ServiceNow.', }), }, ]} diff --git a/webapp/channels/src/components/profile_popover/profile_popover_call_button_wrapper/index.tsx b/webapp/channels/src/components/profile_popover/profile_popover_call_button_wrapper/index.tsx index dc88c02d5db..8221aaeb23e 100644 --- a/webapp/channels/src/components/profile_popover/profile_popover_call_button_wrapper/index.tsx +++ b/webapp/channels/src/components/profile_popover/profile_popover_call_button_wrapper/index.tsx @@ -102,7 +102,7 @@ const CallButton = ({ defaultMessage: 'Call with {user} is ongoing', }, {user: fullname || username}, ) : formatMessage({ - id: 'webapp.mattermost.feature.start_call', + id: 'user_profile.call.start', defaultMessage: 'Start Call', }); const callButton = ( diff --git a/webapp/channels/src/components/remove_flagged_message_confirmation_modal/remove_flagged_message_confirmation_modal.tsx b/webapp/channels/src/components/remove_flagged_message_confirmation_modal/remove_flagged_message_confirmation_modal.tsx index 0720d5901b0..566bdf662e5 100644 --- a/webapp/channels/src/components/remove_flagged_message_confirmation_modal/remove_flagged_message_confirmation_modal.tsx +++ b/webapp/channels/src/components/remove_flagged_message_confirmation_modal/remove_flagged_message_confirmation_modal.tsx @@ -63,7 +63,6 @@ export default function KeepRemoveFlaggedMessageConfirmationModal({action, onExi id: 'keep_remove_flag_content_modal.action_remove.body', defaultMessage: 'You are about to remove a message authored by {flaggedPostAuthor} posed in the {flaggedPostChannel} channel and flagged for review by {reportingUser}.', }, { - br:
, flaggedPostChannel: flaggedPostChannel?.display_name, reportingUser: , flaggedPostAuthor: , @@ -72,7 +71,6 @@ export default function KeepRemoveFlaggedMessageConfirmationModal({action, onExi id: 'keep_remove_flag_content_modal.action_keep.body', defaultMessage: 'You are about to keep a flagged message authored by {flaggedPostAuthor} posed in the {flaggedPostChannel} channel and flagged for review by {reportingUser}.', }, { - br:
, flaggedPostChannel: flaggedPostChannel?.display_name, reportingUser: , flaggedPostAuthor: , diff --git a/webapp/channels/src/components/rhs_card_header/rhs_card_header.tsx b/webapp/channels/src/components/rhs_card_header/rhs_card_header.tsx index 5f943bf9fce..825de19000a 100644 --- a/webapp/channels/src/components/rhs_card_header/rhs_card_header.tsx +++ b/webapp/channels/src/components/rhs_card_header/rhs_card_header.tsx @@ -142,7 +142,7 @@ class RhsCardHeader extends React.PureComponent { {back}
diff --git a/webapp/channels/src/components/rhs_plugin_popout/rhs_plugin_popout.tsx b/webapp/channels/src/components/rhs_plugin_popout/rhs_plugin_popout.tsx index 8db88d88126..f7d4716c0e3 100644 --- a/webapp/channels/src/components/rhs_plugin_popout/rhs_plugin_popout.tsx +++ b/webapp/channels/src/components/rhs_plugin_popout/rhs_plugin_popout.tsx @@ -16,6 +16,7 @@ import type {GlobalState} from 'types/store'; export const RHS_PLUGIN_TITLE = defineMessage({ id: 'rhs_plugin_popout.title', + // eslint-disable-next-line formatjs/enforce-placeholders -- provided later defaultMessage: '{pluginDisplayName} - {serverName}', }); diff --git a/webapp/channels/src/components/search_results/search_results.tsx b/webapp/channels/src/components/search_results/search_results.tsx index 4e6ad44e6a8..be7544de08e 100644 --- a/webapp/channels/src/components/search_results/search_results.tsx +++ b/webapp/channels/src/components/search_results/search_results.tsx @@ -201,7 +201,7 @@ const SearchResults: React.FC = (props: Props): JSX.Element => { } else if (isCard) { titleDescriptor = defineMessage({ id: 'search_header.title5', - defaultMessage: 'Extra information', + defaultMessage: 'Extra Information', }); } else if (!searchTerms && noResults && noFileResults) { titleDescriptor = defineMessage({ @@ -236,7 +236,7 @@ const SearchResults: React.FC = (props: Props): JSX.Element => { contentItems = (
- +
); diff --git a/webapp/channels/src/components/searchable_channel_list.tsx b/webapp/channels/src/components/searchable_channel_list.tsx index 2f028795603..e348af02114 100644 --- a/webapp/channels/src/components/searchable_channel_list.tsx +++ b/webapp/channels/src/components/searchable_channel_list.tsx @@ -289,7 +289,7 @@ export class SearchableChannelList extends React.PureComponent { ); @@ -439,7 +439,7 @@ export class SearchableChannelList extends React.PureComponent { clearable={true} onClear={this.handleClear} value={this.state.channelSearchValue} - aria-label={this.props.intl.formatMessage({id: 'filtered_channels_list.search', defaultMessage: 'Search Channels'})} + aria-label={this.props.intl.formatMessage({id: 'filtered_channels_list.search.label', defaultMessage: 'Search Channels'})} />
); @@ -646,7 +646,7 @@ const messages = defineMessages({ }, noMore: { id: 'more_channels.noMore', - defaultMessage: 'No results for {text}', + defaultMessage: 'No results for "{text}"', }, }); diff --git a/webapp/channels/src/components/select_team/components/__snapshots__/select_team_item.test.tsx.snap b/webapp/channels/src/components/select_team/components/__snapshots__/select_team_item.test.tsx.snap index 32023fe783f..bbc97ee1d1a 100644 --- a/webapp/channels/src/components/select_team/components/__snapshots__/select_team_item.test.tsx.snap +++ b/webapp/channels/src/components/select_team/components/__snapshots__/select_team_item.test.tsx.snap @@ -40,7 +40,7 @@ exports[`components/select_team/components/SelectTeamItem should match snapshot,
diff --git a/webapp/channels/src/components/select_team/components/select_team_item.tsx b/webapp/channels/src/components/select_team/components/select_team_item.tsx index e4ccd101c3f..3b6553ccd49 100644 --- a/webapp/channels/src/components/select_team/components/select_team_item.tsx +++ b/webapp/channels/src/components/select_team/components/select_team_item.tsx @@ -79,7 +79,7 @@ const SelectTeamItem = ({ {!team.allow_open_invite && } {canJoin && icon} diff --git a/webapp/channels/src/components/sidebar/__snapshots__/invite_members_button.test.tsx.snap b/webapp/channels/src/components/sidebar/__snapshots__/invite_members_button.test.tsx.snap index f0653e0522b..85b9ca8566f 100644 --- a/webapp/channels/src/components/sidebar/__snapshots__/invite_members_button.test.tsx.snap +++ b/webapp/channels/src/components/sidebar/__snapshots__/invite_members_button.test.tsx.snap @@ -53,7 +53,7 @@ exports[`components/sidebar/invite_members_button should match snapshot 1`] = ` onClick={[Function]} >
{
diff --git a/webapp/channels/src/components/user_list_row_with_error/user_list_row_with_error.tsx b/webapp/channels/src/components/user_list_row_with_error/user_list_row_with_error.tsx index 9720405224d..0dbb0e945c7 100644 --- a/webapp/channels/src/components/user_list_row_with_error/user_list_row_with_error.tsx +++ b/webapp/channels/src/components/user_list_row_with_error/user_list_row_with_error.tsx @@ -90,9 +90,9 @@ export default class UserListRowWithError extends React.PureComponent {values}, + strong: (values: React.ReactNode) => {values}, email: this.props.user.email, }} /> diff --git a/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap b/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap index 7a5dc8a2ce1..034a6b9d35e 100644 --- a/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap +++ b/webapp/channels/src/components/user_settings/display/__snapshots__/user_settings_display.test.tsx.snap @@ -99,7 +99,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -493,7 +493,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -957,7 +957,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -1281,7 +1281,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -1675,7 +1675,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -1999,7 +1999,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -2305,7 +2305,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -2699,7 +2699,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -3111,7 +3111,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -3435,7 +3435,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -3759,7 +3759,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -4095,7 +4095,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -4419,7 +4419,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should match snaps section="availabilityStatus" title={ } @@ -4743,7 +4743,7 @@ exports[`components/user_settings/display/UserSettingsDisplay should not show la section="availabilityStatus" title={ } diff --git a/webapp/channels/src/components/user_settings/display/manage_timezones/manage_timezones.tsx b/webapp/channels/src/components/user_settings/display/manage_timezones/manage_timezones.tsx index f3f50af9faa..abb7e91fa93 100644 --- a/webapp/channels/src/components/user_settings/display/manage_timezones/manage_timezones.tsx +++ b/webapp/channels/src/components/user_settings/display/manage_timezones/manage_timezones.tsx @@ -259,7 +259,7 @@ export default class ManageTimezones extends React.PureComponent {
, ); diff --git a/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/__snapshots__/render_emoticons_as_emoji.test.tsx.snap b/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/__snapshots__/render_emoticons_as_emoji.test.tsx.snap index 5e0ff676e54..02d2728e544 100644 --- a/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/__snapshots__/render_emoticons_as_emoji.test.tsx.snap +++ b/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/__snapshots__/render_emoticons_as_emoji.test.tsx.snap @@ -60,7 +60,7 @@ exports[`components/user_settings/display/render_emoticons_as_emoji/render_emoti
- When enabled, text emoticons in messages will be rendered as emojis (For example :D as 😄) + When enabled, text emoticons in messages will automatically be rendered as emojis (For example :D as 😄)
diff --git a/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx b/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx index d27e42dfa9b..c848f79dc63 100644 --- a/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx +++ b/webapp/channels/src/components/user_settings/display/render_emoticons_as_emoji/render_emoticons_as_emoji.tsx @@ -107,7 +107,7 @@ const RenderEmoticonsAsEmoji: React.FC = ({user, renderEmoticonsAsEmoji,
diff --git a/webapp/channels/src/components/user_settings/display/user_settings_display.tsx b/webapp/channels/src/components/user_settings/display/user_settings_display.tsx index 6a4959ebf74..64ac5a472a1 100644 --- a/webapp/channels/src/components/user_settings/display/user_settings_display.tsx +++ b/webapp/channels/src/components/user_settings/display/user_settings_display.tsx @@ -827,7 +827,7 @@ export default class UserSettingsDisplay extends React.PureComponent diff --git a/webapp/channels/src/components/user_settings/display/user_settings_theme/custom_theme_chooser/custom_theme_chooser.tsx b/webapp/channels/src/components/user_settings/display/user_settings_theme/custom_theme_chooser/custom_theme_chooser.tsx index 09ee355d542..415b56f050d 100644 --- a/webapp/channels/src/components/user_settings/display/user_settings_theme/custom_theme_chooser/custom_theme_chooser.tsx +++ b/webapp/channels/src/components/user_settings/display/user_settings_theme/custom_theme_chooser/custom_theme_chooser.tsx @@ -419,7 +419,7 @@ export class CustomThemeChooser extends React.PureComponent { >