From cce0167e442776f4624ecf8eedcbbe1351e367c2 Mon Sep 17 00:00:00 2001 From: Dan Purdy Date: Fri, 30 Apr 2021 19:54:37 +0100 Subject: [PATCH 01/10] fix: support shallow route changes * Memoize the i18n client and do not re-create it unless the route or locale has changed (fix #1059). * Let Next's router locale take precedence over initialLocale (fix #1023). * Bump the minimum version of react-i18next. --- examples/simple/yarn.lock | 46 +++++++++++----------- src/appWithTranslation.client.test.tsx | 54 +++++++++++++++++++++++--- src/appWithTranslation.server.test.tsx | 4 ++ src/appWithTranslation.tsx | 31 ++++++++------- 4 files changed, 92 insertions(+), 43 deletions(-) diff --git a/examples/simple/yarn.lock b/examples/simple/yarn.lock index 1dbad6ec..34436b5d 100644 --- a/examples/simple/yarn.lock +++ b/examples/simple/yarn.lock @@ -74,17 +74,24 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/runtime@7.12.5", "@babel/runtime@^7.12.0": +"@babel/runtime@7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.13.6": - version "7.13.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a" - integrity sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA== +"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.6": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" + integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.13.17": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" + integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== dependencies: regenerator-runtime "^0.13.4" @@ -1054,9 +1061,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^3: - version "3.7.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f" - integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA== + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.1.tgz#cec8de593db8eb2a85ffb0dbdeb312cb6e5460ae" + integrity sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg== core-util-is@~1.0.0: version "1.0.2" @@ -1870,14 +1877,14 @@ https-proxy-agent@5.0.0: debug "4" i18next-fs-backend@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-1.0.7.tgz#00ca4587e306f8948740408389dda73461a5d07f" - integrity sha512-aAZ3rvshe1Zbl6JSCWrWWqbZS5JpmVNG+84YqLcgdYcm9uAxzw4xWxnA/a3044Nm2PKXE62CT+pIZjk7OEYtTw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-1.1.0.tgz#3baa63bfb6fd00a331b91d186776cd886b46d2f6" + integrity sha512-QfzfrEYEsLsDC5sZsdSQl5fVYg8I5KrJynnWN7xgSU5yfClbBJ009mtNxUszR0uABQZ8PRr2gj3bN9+RNORBlg== i18next@^19.7.0: - version "19.9.1" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.9.1.tgz#7a072b75daf677aa51fd4ce55214f21702af3ffd" - integrity sha512-9Azzyb3DvMJUMd7sPhwVEs6PQcogvdHmLQTjMQ+P+h3XwW4O66/8lgZTmYShgkjPOCqTw4Fwl5LOp/VhZgPo5A== + version "19.9.2" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.9.2.tgz#ea5a124416e3c5ab85fddca2c8e3c3669a8da397" + integrity sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg== dependencies: "@babel/runtime" "^7.12.0" @@ -2485,15 +2492,8 @@ neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== "next-i18next@link:../..": - version "8.1.3" - dependencies: - "@types/hoist-non-react-statics" "^3.3.1" - "@types/i18next-fs-backend" "^1.0.0" - core-js "^3" - hoist-non-react-statics "^3.2.0" - i18next "^20.1.0" - i18next-fs-backend "^1.0.7" - react-i18next "^11.8.8" + version "0.0.0" + uid "" next-tick@~1.0.0: version "1.0.0" diff --git a/src/appWithTranslation.client.test.tsx b/src/appWithTranslation.client.test.tsx index 33e6ad70..c809b877 100644 --- a/src/appWithTranslation.client.test.tsx +++ b/src/appWithTranslation.client.test.tsx @@ -2,8 +2,10 @@ import React from 'react' import fs from 'fs' import { screen, render } from '@testing-library/react' import { I18nextProvider } from 'react-i18next' +import createClient from './createClient' import { appWithTranslation } from './appWithTranslation' +import { NextRouter } from 'next/router' jest.mock('fs', () => ({ existsSync: jest.fn(), @@ -19,15 +21,16 @@ jest.mock('react-i18next', () => ({ __esmodule: true, })) +jest.mock('./createClient', () => jest.fn()) const DummyApp = appWithTranslation(() => (
Hello world
)) -const props = { +const createProps = (locale = 'en', router: Partial = {}) => ({ pageProps: { _nextI18Next: { - initialLocale: 'en', + initialLocale: locale, userConfig: { i18n: { defaultLocale: 'en', @@ -36,9 +39,15 @@ const props = { }, }, } as any, -} as any - -const renderComponent = () => + router: { + locale: locale, + route: '/', + ...router, + }, +} as any) + +const defaultRenderProps = createProps() +const renderComponent = (props = defaultRenderProps) => render( { (fs.existsSync as jest.Mock).mockReturnValue(true); (fs.readdirSync as jest.Mock).mockReturnValue([]); (I18nextProvider as jest.Mock).mockImplementation(DummyI18nextProvider) + const actualCreateClient = jest.requireActual('./createClient'); + (createClient as jest.Mock).mockImplementation(actualCreateClient) }) afterEach(jest.resetAllMocks) @@ -69,6 +80,7 @@ describe('appWithTranslation', () => { }, } as any) const customProps = { + ...createProps(), pageProps: { _nextI18Next: { initialLocale: 'en', @@ -91,6 +103,7 @@ describe('appWithTranslation', () => {
Hello world
)) const customProps = { + ...createProps(), pageProps: { _nextI18Next: { initialLocale: 'en', @@ -124,4 +137,35 @@ describe('appWithTranslation', () => { expect(fs.readdirSync).toHaveBeenCalledTimes(0) }) + it('should use locale from router', () => { + renderComponent(createProps('de')) + const [args] = (I18nextProvider as jest.Mock).mock.calls + expect(args[0].i18n.language).toEqual('de') + }) + + it('does not re-call createClient on re-renders unless locale or props have changed', () => { + const { rerender } = renderComponent() + expect(createClient).toHaveBeenCalledTimes(1) + rerender( + + ) + expect(createClient).toHaveBeenCalledTimes(1) + const newProps = createProps() + rerender( + + ) + expect(createClient).toHaveBeenCalledTimes(2) + newProps.router.locale = 'de' + rerender( + + ) + expect(createClient).toHaveBeenCalledTimes(3) + }) + }) diff --git a/src/appWithTranslation.server.test.tsx b/src/appWithTranslation.server.test.tsx index 2f4d8b79..883738d2 100644 --- a/src/appWithTranslation.server.test.tsx +++ b/src/appWithTranslation.server.test.tsx @@ -40,6 +40,10 @@ const props = { }, }, } as any, + router: { + locale: 'en', + route: '/', + }, } as any const renderComponent = () => diff --git a/src/appWithTranslation.tsx b/src/appWithTranslation.tsx index 0e70fb89..5a0c20e5 100644 --- a/src/appWithTranslation.tsx +++ b/src/appWithTranslation.tsx @@ -22,12 +22,17 @@ export const appWithTranslation = ( configOverride: UserConfig | null = null, ) => { const AppWithTranslation = (props: AppProps) => { - let i18n: I18NextClient | null = null - let locale = null + const { _nextI18Next } = props.pageProps + const { locale } = props.router - if (props?.pageProps?._nextI18Next) { - let { userConfig } = props.pageProps._nextI18Next - const { initialI18nStore, initialLocale } = props.pageProps._nextI18Next + // Memoize the instance and only re-initialize when either: + // 1. The route changes (non-shallowly) + // 2. Router locale changes + const i18n: I18NextClient | null = useMemo(() => { + if (!locale || !_nextI18Next) return null + + let { userConfig } = _nextI18Next + const { initialI18nStore } = _nextI18Next if (userConfig === null && configOverride === null) { throw new Error('appWithTranslation was called without a next-i18next config') @@ -41,21 +46,17 @@ export const appWithTranslation = ( throw new Error('appWithTranslation was called without config.i18n') } - locale = initialLocale; - - ({ i18n } = createClient({ + return createClient({ ...createConfig({ ...userConfig, - lng: initialLocale, + lng: locale, }), - lng: initialLocale, + lng: locale, resources: initialI18nStore, - })) + }).i18n + }, [_nextI18Next, locale]) - useMemo(() => { - globalI18n = i18n - }, [i18n]) - } + globalI18n = i18n return i18n !== null ? ( Date: Fri, 30 Apr 2021 19:54:56 +0100 Subject: [PATCH 02/10] chore(deps): bump i18next from 19.9.2 to 20.1.0 (#1106) Bumps [i18next](https://github.com/i18next/i18next) from 19.9.2 to 20.1.0. - [Release notes](https://github.com/i18next/i18next/releases) - [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md) - [Commits](https://github.com/i18next/i18next/compare/v19.9.2...v20.1.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f409c3d3..a63994db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4687,9 +4687,9 @@ i18next@^19.7.0: "@babel/runtime" "^7.12.0" i18next@^20.1.0: - version "20.2.1" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.2.1.tgz#8aedfdc596f7d54b9d3f6d87bcb89214467cb785" - integrity sha512-JLruWDEQ3T6tKT6P7u+DsNtToMHUwUcQIYOMRcnNBdUhSfKkoIDUKdVDKgGtmqr//LrirxjADUdr3d5Gwbow6g== + version "20.1.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.1.0.tgz#397dce9ad230ea822f487dc62d6128df5b678456" + integrity sha512-sV+ZwTM4Ik4d6wKdwNS/ocKmvXi6DFA/YHMgdQX3i4L5993jnbo1/j1pK/c4+zBOjexer4dt+c5JHsFj4CUoXQ== dependencies: "@babel/runtime" "^7.12.0" From ab5764b37616d841100acc8c35f82275b138662d Mon Sep 17 00:00:00 2001 From: Dan Purdy Date: Fri, 30 Apr 2021 19:55:22 +0100 Subject: [PATCH 03/10] Fix CVE-2021-23346 vulnerability (#1144) * fix: update react-i18next to resolve CVE-2021-23346 * Update examples/simple/yarn.lock Co-authored-by: Isaac Hinman --- examples/simple/yarn.lock | 432 +++++++++++++++++++------------------- 1 file changed, 213 insertions(+), 219 deletions(-) diff --git a/examples/simple/yarn.lock b/examples/simple/yarn.lock index 34436b5d..80d45bd4 100644 --- a/examples/simple/yarn.lock +++ b/examples/simple/yarn.lock @@ -60,17 +60,17 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" + integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== "@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf" + integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.14.0" chalk "^2.0.0" js-tokens "^4.0.0" @@ -81,14 +81,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.6": - version "7.13.10" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" - integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.13.17": +"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.17", "@babel/runtime@^7.13.6": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== @@ -113,16 +106,16 @@ "@hapi/hoek" "9.x.x" "@hapi/boom@9.x.x": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.0.tgz#0d9517657a56ff1e0b42d0aca9da1b37706fec56" - integrity sha512-4nZmpp4tXbm162LaZT45P7F7sgiem8dwAh2vHWT6XX24dozNjGMg6BvKCRvtCUcmcXqeMIUqWN8Rc5X8yKuROQ== + version "9.1.2" + resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.2.tgz#48bd41d67437164a2d636e3b5bc954f8c8dc5e38" + integrity sha512-uJEJtiNHzKw80JpngDGBCGAmWjBtzxDCz17A9NO2zCi8LLBlb5Frpq4pXwyN+2JQMod4pKz5BALwyneCgDg89Q== dependencies: "@hapi/hoek" "9.x.x" "@hapi/hoek@9.x.x": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6" - integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw== + version "9.2.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131" + integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug== "@next/env@10.0.5": version "10.0.5" @@ -183,12 +176,7 @@ dependencies: i18next "^19.7.0" -"@types/json-schema@^7.0.5": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" - integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== - -"@types/json-schema@^7.0.6": +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== @@ -199,9 +187,9 @@ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== "@types/react@*": - version "17.0.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79" - integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg== + version "17.0.4" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.4.tgz#a67c6f7a460d2660e950d9ccc1c2f18525c28220" + integrity sha512-onz2BqScSFMoTRdJUZUDD/7xrusM8hBA2Fktk2qgaTYPCgPvWnDEgkrOs8hhPUf2jfcIXkJ5yK6VfYormJS3Jw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -457,9 +445,9 @@ anymatch@^2.0.0: normalize-path "^2.1.1" anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -564,14 +552,14 @@ babel-plugin-transform-react-remove-prop-types@0.4.24: integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-js@^1.0.2, base64-js@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: version "0.11.2" @@ -597,9 +585,9 @@ binary-extensions@^1.0.0: integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" - integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bindings@^1.5.0: version "1.5.0" @@ -609,9 +597,9 @@ bindings@^1.5.0: file-uri-to-path "1.0.0" bl@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" - integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" inherits "^2.0.4" @@ -627,10 +615,10 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" - integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== brace-expansion@^1.1.7: version "1.1.11" @@ -700,11 +688,11 @@ browserify-des@^1.0.0: safe-buffer "^5.1.2" browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: - bn.js "^4.1.0" + bn.js "^5.0.0" randombytes "^2.0.1" browserify-sign@^4.0.0: @@ -831,9 +819,9 @@ camelcase@^6.0.0: integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001113, caniuse-lite@^1.0.30001154: - version "1.0.30001156" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001156.tgz#75c20937b6012fe2b02ab58b30d475bf0718de97" - integrity sha512-z7qztybA2eFZTB6Z3yvaQBIoJpQtsewRD74adw2UbRWwsRq3jIPvgrQGawBMbfafekQaD21FWuXNcywtTDGGCw== + version "1.0.30001219" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001219.tgz#5bfa5d0519f41f993618bd318f606a4c4c16156b" + integrity sha512-c0yixVG4v9KBc/tQ2rlbB3A/bgBFRvl8h8M4IeUbqCca4gsiCfvtaheUssbnux/Mb66Vjz7x8yYjDgYcNQOhyQ== chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" @@ -852,7 +840,7 @@ chalk@4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chokidar@3.4.3, chokidar@^3.4.1: +chokidar@3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== @@ -886,17 +874,30 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.4.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -959,9 +960,9 @@ color-name@^1.0.0, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" - integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== + version "1.5.5" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014" + integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -975,9 +976,9 @@ color@^3.1.3: color-string "^1.5.4" colorette@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" - integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== commander@^2.20.0: version "2.20.3" @@ -1061,9 +1062,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^3: - version "3.9.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.1.tgz#cec8de593db8eb2a85ffb0dbdeb312cb6e5460ae" - integrity sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg== + version "3.11.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.11.1.tgz#f920392bf8ed63a0ec8e4e729857bfa3d121c525" + integrity sha512-k93Isqg7e4txZWMGNYwevZL9MiogLk8pd1PtwrmFmi8IBq4GXqUaVW/a33Llt6amSI36uSjd0GWwc9pTT9ALlQ== core-util-is@~1.0.0: version "1.0.2" @@ -1180,9 +1181,9 @@ cssnano-simple@1.2.1: postcss "^7.0.32" csstype@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" - integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g== + version "3.0.8" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340" + integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw== cyclist@^1.0.1: version "1.0.1" @@ -1203,9 +1204,9 @@ data-uri-to-buffer@3.0.1: integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== debug@4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" @@ -1294,7 +1295,7 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dom-serializer@1.1.0, dom-serializer@^1.0.1: +dom-serializer@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58" integrity sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ== @@ -1303,20 +1304,24 @@ dom-serializer@1.1.0, dom-serializer@^1.0.1: domhandler "^3.0.0" entities "^2.0.0" +dom-serializer@^1.0.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.1.tgz#d845a1565d7c041a95e5dab62184ab41e3a519be" + integrity sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + entities "^2.0.0" + domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" - integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== - -domelementtype@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" - integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== domhandler@3.3.0, domhandler@^3.0.0, domhandler@^3.3.0: version "3.3.0" @@ -1325,12 +1330,12 @@ domhandler@3.3.0, domhandler@^3.0.0, domhandler@^3.3.0: dependencies: domelementtype "^2.0.1" -domhandler@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e" - integrity sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA== +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" + integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== dependencies: - domelementtype "^2.1.0" + domelementtype "^2.2.0" domutils@2.4.2: version "2.4.2" @@ -1342,13 +1347,13 @@ domutils@2.4.2: domhandler "^3.3.0" domutils@^2.4.2: - version "2.4.4" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3" - integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA== + version "2.6.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7" + integrity sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA== dependencies: dom-serializer "^1.0.1" - domelementtype "^2.0.1" - domhandler "^4.0.0" + domelementtype "^2.2.0" + domhandler "^4.2.0" duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -1361,9 +1366,9 @@ duplexify@^3.4.2, duplexify@^3.6.0: stream-shift "^1.0.0" electron-to-chromium@^1.3.585: - version "1.3.591" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.591.tgz#a18892bf1acb93f7b6e4da402705d564bc235017" - integrity sha512-ol/0WzjL4NS4Kqy9VD6xXQON91xIihDT36sYCew/G/bnd1v0/4D+kahp26JauQhgFUjrdva3kRSo7URcUmQ+qw== + version "1.3.723" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.723.tgz#52769a75635342a4db29af5f1e40bd3dad02c877" + integrity sha512-L+WXyXI7c7+G1V8ANzRsPI5giiimLAUDC6Zs1ojHHPhYXb3k/iTABFmWjivEtsWrRQymjnO66/rO2ZTABGdmWg== elliptic@^6.5.3: version "6.5.4" @@ -1396,23 +1401,23 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: once "^1.4.0" enhanced-resolve@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" - integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" tapable "^1.0.0" entities@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" - integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" @@ -1493,9 +1498,9 @@ event-target-shim@^5.0.0: integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== events@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" - integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -1690,6 +1695,11 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1723,9 +1733,9 @@ glob-parent@^3.1.0: path-dirname "^1.0.0" glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -1747,9 +1757,9 @@ glob@^7.1.3, glob@^7.1.4: path-is-absolute "^1.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== has-flag@^3.0.0: version "3.0.0" @@ -1835,10 +1845,10 @@ hoist-non-react-statics@^3.2.0, hoist-non-react-statics@^3.3.0: dependencies: react-is "^16.7.0" -html-parse-stringify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.0.tgz#28f10753e190af211d2c3c9a1191a4502e112c96" - integrity sha512-TrTKp/U0tACrpqalte/VhxepqMLii2mOfC8iuOt4+VA7Zdi6BUKKqNJvEsO17Cr3T3E7PpqLe3NdLII6bcYJgg== +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== dependencies: void-elements "3.1.0" @@ -1877,9 +1887,9 @@ https-proxy-agent@5.0.0: debug "4" i18next-fs-backend@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-1.1.0.tgz#3baa63bfb6fd00a331b91d186776cd886b46d2f6" - integrity sha512-QfzfrEYEsLsDC5sZsdSQl5fVYg8I5KrJynnWN7xgSU5yfClbBJ009mtNxUszR0uABQZ8PRr2gj3bN9+RNORBlg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-1.1.1.tgz#1d8028926803f63784ffa0f2b1478fb369f92735" + integrity sha512-RFkfy10hNxJqc7MVAp5iAZq0Tum6msBCNebEe3OelOBvrROvzHUPaR8Qe10RQrOGokTm0W4vJGEJzruFkEt+hQ== i18next@^19.7.0: version "19.9.2" @@ -1889,9 +1899,9 @@ i18next@^19.7.0: "@babel/runtime" "^7.12.0" i18next@^20.1.0: - version "20.1.0" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.1.0.tgz#397dce9ad230ea822f487dc62d6128df5b678456" - integrity sha512-sV+ZwTM4Ik4d6wKdwNS/ocKmvXi6DFA/YHMgdQX3i4L5993jnbo1/j1pK/c4+zBOjexer4dt+c5JHsFj4CUoXQ== + version "20.2.2" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.2.2.tgz#175644829dcf35546ba8c174583acfe449e4ef1a" + integrity sha512-uWCv9LzKpe+OwvnKKrb8CbJwgAhasQofD58cB0PQ6bTPXEl5PlItl5C4esmY8HtriLu9nrjc2Hi0IfYv3Fy8BQ== dependencies: "@babel/runtime" "^7.12.0" @@ -1924,11 +1934,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - infer-owner@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -2152,9 +2157,9 @@ json5@^1.0.1: minimist "^1.2.0" json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" @@ -2248,9 +2253,9 @@ lodash.sortby@^4.7.0: integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= lodash@^4.17.11, lodash@^4.17.13: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loose-envify@^1.4.0: version "1.4.0" @@ -2259,7 +2264,7 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@6.0.0: +lru-cache@6.0.0, lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== @@ -2453,9 +2458,9 @@ nan@^2.12.1: integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== nanoid@^3.1.16: - version "3.1.20" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" - integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== + version "3.1.22" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" + integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== nanomatch@^1.2.9: version "1.2.13" @@ -2554,17 +2559,17 @@ next@10.0.5: optionalDependencies: sharp "0.26.3" -node-abi@^2.7.0: - version "2.19.1" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.1.tgz#6aa32561d0a5e2fdb6810d8c25641b657a8cea85" - integrity sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A== +node-abi@^2.21.0: + version "2.26.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.26.0.tgz#355d5d4bc603e856f74197adbf3f5117a396ba40" + integrity sha512-ag/Vos/mXXpWLLAYWsAoQdgS+gW7IwvgMLOgqopm/DbzAjazLltzgzpVMsFlgmo9TzG5hGXeaBZx2AI731RIsQ== dependencies: semver "^5.4.1" node-addon-api@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz#04bc7b83fd845ba785bb6eae25bc857e1ef75681" - integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239" + integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw== node-fetch@2.6.1: version "2.6.1" @@ -2608,9 +2613,9 @@ node-libs-browser@^2.2.1: vm-browserify "^1.0.1" node-releases@^1.1.65: - version "1.1.66" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.66.tgz#609bd0dc069381015cd982300bae51ab4f1b1814" - integrity sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg== + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== noop-logger@^0.1.1: version "0.1.1" @@ -2783,9 +2788,9 @@ path-is-absolute@^1.0.0: integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= pbkdf2@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" - integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -2794,9 +2799,9 @@ pbkdf2@^3.0.3: sha.js "^2.4.8" picomatch@^2.0.4, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + version "2.2.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d" + integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg== pify@^4.0.1: version "4.0.1" @@ -2875,13 +2880,11 @@ postcss-safe-parser@4.0.2: postcss "^7.0.26" postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" - integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== + version "6.0.5" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.5.tgz#042d74e137db83e6f294712096cb413f5aa612c4" + integrity sha512-aFYPoYmXbZ1V6HZaSvat08M97A8HqO6Pjz+PiNpw/DhuRrC72XWAdp3hL6wusDCN31sSmcZyMGa2hZEuX+Xfhg== dependencies: cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" util-deprecate "^1.0.2" postcss-value-parser@^4.1.0: @@ -2927,9 +2930,9 @@ postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0. supports-color "^6.1.0" prebuild-install@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.0.1.tgz#5902172f7a40eb67305b96c2a695db32636ee26d" - integrity sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ== + version "6.1.2" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.2.tgz#6ce5fc5978feba5d3cbffedca0682b136a0b5bff" + integrity sha512-PzYWIKZeP+967WuKYXlTOhYBgGOvTRSfaKI89XnfJ0ansRAH7hDU45X+K+FZeI1Wb/7p/NnuctPH3g0IqKUuSQ== dependencies: detect-libc "^1.0.3" expand-template "^2.0.3" @@ -2937,7 +2940,7 @@ prebuild-install@^6.0.0: minimist "^1.2.3" mkdirp-classic "^0.5.3" napi-build-utils "^1.0.1" - node-abi "^2.7.0" + node-abi "^2.21.0" noop-logger "^0.1.1" npmlog "^4.0.1" pump "^3.0.0" @@ -2945,7 +2948,6 @@ prebuild-install@^6.0.0: simple-get "^3.0.3" tar-fs "^2.0.0" tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" process-nextick-args@~2.0.0: version "2.0.1" @@ -3033,11 +3035,16 @@ querystring-es3@^0.2.0: resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= -querystring@0.2.0, querystring@^0.2.0: +querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +querystring@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" + integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -3074,12 +3081,12 @@ rc@^1.2.7: strip-json-comments "~2.0.1" react-i18next@^11.8.13: - version "11.8.13" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.13.tgz#9560376f8655b9aaa04f685da8eca0b032034ff9" - integrity sha512-KTNuLYnEwI9y54nSEal4yBxXBnfCCfh7t/0p/UHfhlGNcIMu+V4x/y5zGKzbOEK4noQrUzZ+J47RPYH7rMs2ZQ== + version "11.8.15" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.15.tgz#89450d585298f18d4a8eb1628b0868863f3a4767" + integrity sha512-ZbKcbYYKukgDL0MiUWKJTEsEftjSTNVZv67/V+SjPqTRwuF/aL4NbUtuEcb4WjHk0HyZ1M+2wGd07Fp0RUNHKA== dependencies: "@babel/runtime" "^7.13.6" - html-parse-stringify "^3.0.0" + html-parse-stringify "^3.0.1" react-is@16.13.1, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" @@ -3153,9 +3160,9 @@ remove-trailing-separator@^1.0.1: integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== repeat-string@^1.6.1: version "1.6.1" @@ -3294,9 +3301,11 @@ semver@^6.0.0: integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" serialize-javascript@^4.0.0: version "4.0.0" @@ -3449,9 +3458,9 @@ source-map-support@~0.5.12, source-map-support@~0.5.19: source-map "^0.6.0" source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" @@ -3680,9 +3689,9 @@ tar-fs@^2.0.0, tar-fs@^2.1.1: tar-stream "^2.1.4" tar-stream@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.4.tgz#c4fb1a11eb0da29b893a5b25476397ba2d053bfa" - integrity sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== dependencies: bl "^4.0.3" end-of-stream "^1.4.1" @@ -3802,11 +3811,6 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tslib@^1.9.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -3830,9 +3834,9 @@ type@^1.0.1: integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f" - integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== typedarray@^0.0.6: version "0.0.6" @@ -3849,11 +3853,6 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -3887,9 +3886,9 @@ upath@^1.1.1: integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" @@ -3947,10 +3946,10 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= -watchpack-chokidar2@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" - integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" @@ -3963,15 +3962,15 @@ watchpack@2.0.0-beta.13: graceful-fs "^4.1.2" watchpack@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" - integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" optionalDependencies: chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.0" + watchpack-chokidar2 "^2.0.1" webidl-conversions@^4.0.2: version "4.0.2" @@ -4024,11 +4023,6 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= - wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -4054,9 +4048,9 @@ xtend@^4.0.0, xtend@~4.0.1: integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" - integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== yallist@^3.0.2: version "3.1.1" From a13c01b66717a8a27f661a973401050d0fb23776 Mon Sep 17 00:00:00 2001 From: Dan Purdy Date: Fri, 30 Apr 2021 19:55:44 +0100 Subject: [PATCH 04/10] Update serverSideTranslations tests --- examples/simple/pages/_app.js | 3 +- examples/simple/pages/index.js | 4 +- examples/simple/pages/second-page.js | 2 +- examples/simple/yarn.lock | 9 +- jest.config.js | 1 + mocks/next-i18next.config.js | 7 ++ src/appWithTranslation.tsx | 53 ++++++----- src/serverSideTranslations.test.ts | 130 ++++++++++++++++++--------- src/serverSideTranslations.ts | 12 +-- 9 files changed, 147 insertions(+), 74 deletions(-) create mode 100644 mocks/next-i18next.config.js diff --git a/examples/simple/pages/_app.js b/examples/simple/pages/_app.js index 2b639436..08f43f2b 100644 --- a/examples/simple/pages/_app.js +++ b/examples/simple/pages/_app.js @@ -1,5 +1,6 @@ import { appWithTranslation } from 'next-i18next' +import nextI18nConfig from '../next-i18next.config' const MyApp = ({ Component, pageProps }) => -export default appWithTranslation(MyApp) +export default appWithTranslation(MyApp, nextI18nConfig) diff --git a/examples/simple/pages/index.js b/examples/simple/pages/index.js index 9a6e6741..d55912df 100644 --- a/examples/simple/pages/index.js +++ b/examples/simple/pages/index.js @@ -39,7 +39,9 @@ const Homepage = () => { ) } -export const getStaticProps = async ({ locale }) => ({ +export const getStaticProps = async ({ + locale, +}) => ({ props: { ...await serverSideTranslations(locale, ['common', 'footer']), }, diff --git a/examples/simple/pages/second-page.js b/examples/simple/pages/second-page.js index 8a7a251f..bd88b8ec 100644 --- a/examples/simple/pages/second-page.js +++ b/examples/simple/pages/second-page.js @@ -27,7 +27,7 @@ const SecondPage = () => { ) } -export const getStaticProps = async ({ locale }) => ({ +export const getStaticProps = async ({locale}) => ({ props: { ...await serverSideTranslations(locale, ['second-page', 'footer']), }, diff --git a/examples/simple/yarn.lock b/examples/simple/yarn.lock index 80d45bd4..c86c6b91 100644 --- a/examples/simple/yarn.lock +++ b/examples/simple/yarn.lock @@ -81,13 +81,20 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.17", "@babel/runtime@^7.13.6": +"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.17": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.13.6": + version "7.13.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a" + integrity sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/types@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" diff --git a/jest.config.js b/jest.config.js index b2fa970d..f326244b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,6 +8,7 @@ module.exports = { moduleDirectories: [ 'node_modules', 'src', + 'mocks', ], moduleNameMapper: { createClient: '/src/createClient/browser.ts', diff --git a/mocks/next-i18next.config.js b/mocks/next-i18next.config.js new file mode 100644 index 00000000..30b432e0 --- /dev/null +++ b/mocks/next-i18next.config.js @@ -0,0 +1,7 @@ +module.exports = { + i18n: { + defaultLocale: 'en', + locales: ['en', 'de'], + }, +} + diff --git a/src/appWithTranslation.tsx b/src/appWithTranslation.tsx index 5a0c20e5..348ed1d1 100644 --- a/src/appWithTranslation.tsx +++ b/src/appWithTranslation.tsx @@ -6,7 +6,7 @@ import type { AppProps as NextJsAppProps } from 'next/app' import { createConfig } from './config/createConfig' import createClient from './createClient' -import { SSRConfig, UserConfig } from './types' +import { InternalConfig, SSRConfig, UserConfig } from './types' import { i18n as I18NextClient } from 'i18next' export { Trans, useTranslation, withTranslation } from 'react-i18next' @@ -15,26 +15,26 @@ type AppProps = NextJsAppProps & { pageProps: SSRConfig } -export let globalI18n: I18NextClient | null = null +export let globalI18n: I18NextClient +export let globalConfig: InternalConfig export const appWithTranslation = ( WrappedComponent: React.ComponentType | React.ElementType, configOverride: UserConfig | null = null, ) => { const AppWithTranslation = (props: AppProps) => { - const { _nextI18Next } = props.pageProps - const { locale } = props.router + const { _nextI18Next = {} } = props.pageProps + let { locale } = props.router // Memoize the instance and only re-initialize when either: // 1. The route changes (non-shallowly) // 2. Router locale changes - const i18n: I18NextClient | null = useMemo(() => { - if (!locale || !_nextI18Next) return null - + // 3. UserConfig override changes + const {config, i18n} = useMemo(() => { let { userConfig } = _nextI18Next const { initialI18nStore } = _nextI18Next - if (userConfig === null && configOverride === null) { + if (!userConfig && configOverride === null) { throw new Error('appWithTranslation was called without a next-i18next config') } @@ -46,32 +46,39 @@ export const appWithTranslation = ( throw new Error('appWithTranslation was called without config.i18n') } - return createClient({ - ...createConfig({ - ...userConfig, - lng: locale, - }), + if (!userConfig?.i18n?.defaultLocale) { + throw new Error('config.i18n does not include a defaultLocale property') + } + + if (!locale) { + locale = userConfig.i18n.defaultLocale + } + + const config = createConfig({ + ...userConfig, lng: locale, - resources: initialI18nStore, - }).i18n - }, [_nextI18Next, locale]) + }) + + return { + config, + i18n: createClient({ + ...config, + lng: locale, + resources: initialI18nStore, + }).i18n} + }, [_nextI18Next, locale, configOverride]) + globalConfig = config globalI18n = i18n - return i18n !== null ? ( + return ( - ) : ( - ) } diff --git a/src/serverSideTranslations.test.ts b/src/serverSideTranslations.test.ts index 7c10b80f..a36f2723 100644 --- a/src/serverSideTranslations.test.ts +++ b/src/serverSideTranslations.test.ts @@ -1,61 +1,107 @@ import fs from 'fs' +import path from 'path' import { UserConfig } from './types' -import { serverSideTranslations } from './serverSideTranslations' +import { DEFAULT_CONFIG_PATH, serverSideTranslations } from './serverSideTranslations' jest.mock('fs', () => ({ existsSync: jest.fn(), readdirSync: jest.fn(), })) +jest.mock('path', () => ({ + resolve: jest.fn(), +})) + + describe('serverSideTranslations', () => { - beforeEach(() => { - (fs.existsSync as jest.Mock).mockReturnValueOnce(false); - (fs.existsSync as jest.Mock).mockReturnValueOnce(true); - (fs.readdirSync as jest.Mock).mockReturnValue([]) - }) - afterEach(jest.resetAllMocks) + describe('external config', () => { + beforeEach(() => { + (fs.readdirSync as jest.Mock).mockReturnValue([]) + }) + afterEach(jest.resetAllMocks) - it('throws if initialLocale is not passed', async () => { - await expect(serverSideTranslations(undefined as any)) - .rejects - .toThrow('Initial locale argument was not passed into serverSideTranslations') - }) + it('should try to import the default user config file if no override is passed', async () => { + const config = { + i18n: { + defaultLocale: 'en-US', + locales: ['en-US', 'fr-CA'], + }, + }; + (fs.existsSync as jest.Mock).mockReturnValue(true) + const pathMock = (path.resolve as jest.Mock).mockReturnValue('next-i18next.config.js') + + jest.mock('next-i18next.config.js', () => (config)) + const props = await serverSideTranslations('en-US', undefined, undefined) + + expect(pathMock).toHaveBeenCalledWith(DEFAULT_CONFIG_PATH) + expect(props._nextI18Next.initialLocale).toEqual('en-US') + expect(props._nextI18Next?.userConfig?.i18n).toEqual(config?.i18n) + }) + + it('should throw when no config is present', async () => { + (fs.existsSync as jest.Mock).mockReturnValue(false) - it('returns all namespaces if namespacesRequired is not provided', async () => { - (fs.readdirSync as jest.Mock).mockReturnValue(['one', 'two', 'three']) - const props = await serverSideTranslations('en-US', undefined, { - i18n: { - defaultLocale: 'en-US', - locales: ['en-US', 'fr-CA'], - }, - } as UserConfig) - expect(fs.readdirSync).toHaveBeenCalledTimes(1) - expect(fs.readdirSync).toHaveBeenCalledWith(expect.stringMatching('/public/locales/en-US')) - expect(Object.values(props._nextI18Next.initialI18nStore)) - .toEqual([{ one: {}, three: {}, two: {} }]) + await expect(serverSideTranslations('en-US', undefined as any)) + .rejects + .toThrow('next-i18next was unable to find a user config or one was not passed to serverSideTranslations') + }) }) - it('returns props', async () => { - const props = await serverSideTranslations('en-US', [], { - i18n: { - defaultLocale: 'en-US', - locales: ['en-US', 'fr-CA'], - }, - } as UserConfig) - - expect(props).toEqual({ - _nextI18Next: { - initialI18nStore: { - 'en-US': {}, + describe('default', () => { + beforeEach(() => { + (fs.existsSync as jest.Mock).mockReturnValueOnce(false); + (fs.existsSync as jest.Mock).mockReturnValueOnce(true); + (fs.readdirSync as jest.Mock).mockReturnValue([]) + }) + afterEach(jest.resetAllMocks) + + it('throws if initialLocale is not passed', async () => { + await expect(serverSideTranslations(undefined as any)) + .rejects + .toThrow('Initial locale argument was not passed into serverSideTranslations') + }) + + it('returns all namespaces if namespacesRequired is not provided', async () => { + (fs.readdirSync as jest.Mock).mockReturnValue(['one', 'two', 'three']); + (path.resolve as jest.Mock).mockReturnValueOnce('/public/locales/en-US') + const overrideConfig = { + i18n: { + defaultLocale: 'en-US', + locales: ['en-US', 'fr-CA'], }, - initialLocale: 'en-US', - userConfig: { - i18n: { - defaultLocale: 'en-US', - locales: ['en-US', 'fr-CA'], + } as UserConfig + + + const props = await serverSideTranslations('en-US', undefined, overrideConfig) + expect(path.resolve).toHaveBeenCalledWith(process.cwd(), `./public/locales/${overrideConfig.i18n.defaultLocale}`) + expect(fs.readdirSync).toHaveBeenCalledTimes(1) + expect(fs.readdirSync).toHaveBeenCalledWith(expect.stringMatching('/public/locales/en-US')) + expect(Object.values(props._nextI18Next.initialI18nStore)) + .toEqual([{ one: {}, three: {}, two: {} }]) + }) + + it('returns props', async () => { + const props = await serverSideTranslations('en-US', [], { + i18n: { + defaultLocale: 'en-US', + locales: ['en-US', 'fr-CA'], + }, + } as UserConfig) + + expect(props).toEqual({ + _nextI18Next: { + initialI18nStore: { + 'en-US': {}, + }, + initialLocale: 'en-US', + userConfig: { + i18n: { + defaultLocale: 'en-US', + locales: ['en-US', 'fr-CA'], + }, }, }, - }, + }) }) }) }) diff --git a/src/serverSideTranslations.ts b/src/serverSideTranslations.ts index aa52c402..4546cad2 100644 --- a/src/serverSideTranslations.ts +++ b/src/serverSideTranslations.ts @@ -6,7 +6,7 @@ import createClient from './createClient' import { UserConfig, SSRConfig } from './types' -const DEFAULT_CONFIG_PATH = './next-i18next.config.js' +export const DEFAULT_CONFIG_PATH = './next-i18next.config.js' export const serverSideTranslations = async ( initialLocale: string, @@ -17,14 +17,16 @@ export const serverSideTranslations = async ( throw new Error('Initial locale argument was not passed into serverSideTranslations') } - let userConfig = configOverride + let userConfig: UserConfig | null = null - if (fs.existsSync(path.resolve(DEFAULT_CONFIG_PATH))) { + if (configOverride) { + userConfig = configOverride + } else if (fs.existsSync(path.resolve(DEFAULT_CONFIG_PATH))) { userConfig = await import(path.resolve(DEFAULT_CONFIG_PATH)) } - if (userConfig === null) { - throw new Error('next-i18next was unable to find a user config') + if (!userConfig) { + throw new Error('next-i18next was unable to find a user config or one was not passed to serverSideTranslations') } const config = createConfig({ From eec4c7a38df9f7cc6975b185c68bb909807c01e5 Mon Sep 17 00:00:00 2001 From: Dan Purdy Date: Fri, 30 Apr 2021 19:49:45 +0100 Subject: [PATCH 05/10] add fallback languages and tests for appWithTranslation --- src/appWithTranslation.client.test.tsx | 112 ++++++++++++++++++++++++- src/appWithTranslation.tsx | 6 +- 2 files changed, 114 insertions(+), 4 deletions(-) diff --git a/src/appWithTranslation.client.test.tsx b/src/appWithTranslation.client.test.tsx index c809b877..bec790d9 100644 --- a/src/appWithTranslation.client.test.tsx +++ b/src/appWithTranslation.client.test.tsx @@ -7,6 +7,8 @@ import createClient from './createClient' import { appWithTranslation } from './appWithTranslation' import { NextRouter } from 'next/router' +const i18nextConfig = require('../mocks/next-i18next.config') // eslint-disable-line + jest.mock('fs', () => ({ existsSync: jest.fn(), readdirSync: jest.fn(), @@ -25,7 +27,7 @@ jest.mock('./createClient', () => jest.fn()) const DummyApp = appWithTranslation(() => (
Hello world
-)) +), i18nextConfig) const createProps = (locale = 'en', router: Partial = {}) => ({ pageProps: { @@ -120,6 +122,114 @@ describe('appWithTranslation', () => { ).toThrow('appWithTranslation was called without a next-i18next config') }) + it('throws an error if userConfig and configOverride are both missing an i18n property', () => { + const DummyAppConfigOverride = appWithTranslation(() => ( +
Hello world
+ ), {} as any) + const customProps = { + ...createProps(), + pageProps: { + _nextI18Next: { + initialLocale: 'en', + userConfig: {}, + }, + } as any, + } as any + expect( + () => render( + + ) + ).toThrow('appWithTranslation was called without config.i18n') + }) + + it('throws an error if userConfig and configOverride are both missing a defaultLocale property', () => { + const DummyAppConfigOverride = appWithTranslation(() => ( +
Hello world
+ ), {i18n: {} as any}) + const customProps = { + ...createProps(), + pageProps: { + _nextI18Next: { + initialLocale: 'en', + userConfig: {i18n: {}}, + }, + } as any, + } as any + expect( + () => render( + + ) + ).toThrow('config.i18n does not include a defaultLocale property') + }) + + it('should use the initialLocale property if the router locale is undefined', () => { + const DummyAppConfigOverride = appWithTranslation(() => ( +
Hello world
+ )) + const customProps = { + ...createProps(), + pageProps: { + _nextI18Next: { + initialLocale: 'en', + userConfig: {i18n: { + defaultLocale: 'fr', + }}, + }, + } as any, + } as any + + customProps.router = { + ...customProps.router, + locale: undefined, + } + + + render( + + ) + + const [args] = (I18nextProvider as jest.Mock).mock.calls + expect(args[0].i18n.language).toEqual('en') + }) + + it('should use the userConfig defaltLocale property if the router locale is undefined and initialLocale is undefined', () => { + const DummyAppConfigOverride = appWithTranslation(() => ( +
Hello world
+ )) + const customProps = { + ...createProps(), + + pageProps: { + _nextI18Next: { + initialLocale: undefined, + userConfig: {i18n: { + defaultLocale: 'fr', + }}, + }, + } as any, + } as any + + customProps.router = { + ...customProps.router, + locale: undefined, + } + + render( + + ) + + const [args] = (I18nextProvider as jest.Mock).mock.calls + expect(args[0].i18n.language).toEqual('fr') + }) + it('returns an I18nextProvider', () => { renderComponent() expect(I18nextProvider).toHaveBeenCalledTimes(1) diff --git a/src/appWithTranslation.tsx b/src/appWithTranslation.tsx index 348ed1d1..b873a8eb 100644 --- a/src/appWithTranslation.tsx +++ b/src/appWithTranslation.tsx @@ -12,7 +12,7 @@ import { i18n as I18NextClient } from 'i18next' export { Trans, useTranslation, withTranslation } from 'react-i18next' type AppProps = NextJsAppProps & { - pageProps: SSRConfig + pageProps?: SSRConfig } export let globalI18n: I18NextClient @@ -32,7 +32,7 @@ export const appWithTranslation = ( // 3. UserConfig override changes const {config, i18n} = useMemo(() => { let { userConfig } = _nextI18Next - const { initialI18nStore } = _nextI18Next + const { initialLocale, initialI18nStore } = _nextI18Next if (!userConfig && configOverride === null) { throw new Error('appWithTranslation was called without a next-i18next config') @@ -51,7 +51,7 @@ export const appWithTranslation = ( } if (!locale) { - locale = userConfig.i18n.defaultLocale + locale = initialLocale || userConfig.i18n.defaultLocale } const config = createConfig({ From 85862fea59702c2bc4297d0a426c8a445f975595 Mon Sep 17 00:00:00 2001 From: Dan Purdy Date: Fri, 30 Apr 2021 19:50:35 +0100 Subject: [PATCH 06/10] Add example of client side translation loading Adds client side page example where translations are loaded via http-backend and then cached locally via localstorage --- .../withClientsideHttp/components/Footer.js | 19 + .../withClientsideHttp/components/Header.js | 29 + .../withClientsideHttp/next-i18next.config.js | 24 + examples/withClientsideHttp/next.config.js | 5 + examples/withClientsideHttp/package.json | 21 + examples/withClientsideHttp/pages/_app.js | 9 + .../withClientsideHttp/pages/client-page.js | 29 + examples/withClientsideHttp/pages/index.js | 55 + .../withClientsideHttp/pages/second-page.js | 36 + examples/withClientsideHttp/public/app.css | 87 + .../public/locales/de/client-page.json | 5 + .../public/locales/de/common.json | 9 + .../public/locales/de/footer.json | 3 + .../public/locales/de/second-page.json | 5 + .../public/locales/en/client-page.json | 5 + .../public/locales/en/common.json | 9 + .../public/locales/en/footer.json | 3 + .../public/locales/en/second-page.json | 5 + examples/withClientsideHttp/yarn.lock | 4096 +++++++++++++++++ 19 files changed, 4454 insertions(+) create mode 100644 examples/withClientsideHttp/components/Footer.js create mode 100644 examples/withClientsideHttp/components/Header.js create mode 100644 examples/withClientsideHttp/next-i18next.config.js create mode 100644 examples/withClientsideHttp/next.config.js create mode 100644 examples/withClientsideHttp/package.json create mode 100644 examples/withClientsideHttp/pages/_app.js create mode 100644 examples/withClientsideHttp/pages/client-page.js create mode 100644 examples/withClientsideHttp/pages/index.js create mode 100644 examples/withClientsideHttp/pages/second-page.js create mode 100644 examples/withClientsideHttp/public/app.css create mode 100644 examples/withClientsideHttp/public/locales/de/client-page.json create mode 100644 examples/withClientsideHttp/public/locales/de/common.json create mode 100644 examples/withClientsideHttp/public/locales/de/footer.json create mode 100644 examples/withClientsideHttp/public/locales/de/second-page.json create mode 100644 examples/withClientsideHttp/public/locales/en/client-page.json create mode 100644 examples/withClientsideHttp/public/locales/en/common.json create mode 100644 examples/withClientsideHttp/public/locales/en/footer.json create mode 100644 examples/withClientsideHttp/public/locales/en/second-page.json create mode 100644 examples/withClientsideHttp/yarn.lock diff --git a/examples/withClientsideHttp/components/Footer.js b/examples/withClientsideHttp/components/Footer.js new file mode 100644 index 00000000..89ae98f0 --- /dev/null +++ b/examples/withClientsideHttp/components/Footer.js @@ -0,0 +1,19 @@ +import { version } from 'next-i18next/package.json' +import { i18n, useTranslation } from 'next-i18next' + +export const Footer = () => { + + const { t } = useTranslation('footer', {i18n}) + + return ( +
+

+ {t('description')} +

+

+ next-i18next v + {version} +

+
+ ) +} diff --git a/examples/withClientsideHttp/components/Header.js b/examples/withClientsideHttp/components/Header.js new file mode 100644 index 00000000..28069cdb --- /dev/null +++ b/examples/withClientsideHttp/components/Header.js @@ -0,0 +1,29 @@ +import Head from 'next/head' + +export const Header = ({ heading, title }) => ( + <> + + {title} + + + + + + + + +

+ next-i18next +
+

+

+ {heading} +

+ + + + +) diff --git a/examples/withClientsideHttp/next-i18next.config.js b/examples/withClientsideHttp/next-i18next.config.js new file mode 100644 index 00000000..2720c8b0 --- /dev/null +++ b/examples/withClientsideHttp/next-i18next.config.js @@ -0,0 +1,24 @@ +const i18nextHttpBackend = require('i18next-http-backend/cjs') +const chainedBackend= require('i18next-chained-backend').default +const localStorageBackend = require('i18next-localstorage-backend').default + +module.exports = { + backend: { + backendOptions: [{}, {expirationTime: 60 * 60 * 1000}], // 1 hour + backends: process.browser ? [localStorageBackend, i18nextHttpBackend]: [], + }, + debug: true, + i18n: { + defaultLocale: 'en', + locales: ['en', 'de'], + }, + ns: ['common', 'second-page', 'footer'], // the namespaces needs to be listed here, to make sure they got preloaded + partialBundledLanguages: true, + react: { + useSuspense: false, + }, + serializeConfig: false, + use: process.browser ? + [chainedBackend] : + [], +} diff --git a/examples/withClientsideHttp/next.config.js b/examples/withClientsideHttp/next.config.js new file mode 100644 index 00000000..09374ad3 --- /dev/null +++ b/examples/withClientsideHttp/next.config.js @@ -0,0 +1,5 @@ +const { i18n } = require('./next-i18next.config') + +module.exports = { + i18n, +} diff --git a/examples/withClientsideHttp/package.json b/examples/withClientsideHttp/package.json new file mode 100644 index 00000000..b7609dd2 --- /dev/null +++ b/examples/withClientsideHttp/package.json @@ -0,0 +1,21 @@ +{ + "name": "v10", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start -p ${PORT:=3000}" + }, + "dependencies": { + "i18next-chained-backend": "^2.1.0", + "i18next-http-backend": "^1.2.2", + "i18next-localstorage-backend": "^3.1.2", + "next": "10.0.5", + "next-i18next": "link:../../" + }, + "devDependencies": { + "prop-types": "^15.7.2" + } +} diff --git a/examples/withClientsideHttp/pages/_app.js b/examples/withClientsideHttp/pages/_app.js new file mode 100644 index 00000000..f72ab9ba --- /dev/null +++ b/examples/withClientsideHttp/pages/_app.js @@ -0,0 +1,9 @@ +import { appWithTranslation } from 'next-i18next' +import nextI18nConfig from '../next-i18next.config' + +const MyApp = ({ Component, pageProps }) => + ( + + ) + +export default appWithTranslation(MyApp, nextI18nConfig) diff --git a/examples/withClientsideHttp/pages/client-page.js b/examples/withClientsideHttp/pages/client-page.js new file mode 100644 index 00000000..18c80133 --- /dev/null +++ b/examples/withClientsideHttp/pages/client-page.js @@ -0,0 +1,29 @@ +import Link from 'next/link' + +import { i18n, useTranslation } from 'next-i18next' + +import { Header } from '../components/Header' +import { Footer } from '../components/Footer' + +const ClientPage = () => { + const { t, ready } = useTranslation('client-page', {i18n}) + + return ( + <> +
+
+ + + +
+