gt-next 11.1.14 → 11.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # gt-next
2
2
 
3
+ ## 11.1.16
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2139](https://github.com/generaltranslation/gt/pull/2139) [`bc12b5d`](https://github.com/generaltranslation/gt/commit/bc12b5d85bf050e42f31b38c8aa3fedd60594f61) Thanks [@eoinest](https://github.com/eoinest)! - Avoid a full browser reload when a route already resolves to the default locale.
8
+
9
+ - Updated dependencies []:
10
+ - @generaltranslation/react-core@11.1.16
11
+ - gt-react@11.1.16
12
+
13
+ ## 11.1.15
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies []:
18
+ - @generaltranslation/react-core@11.1.15
19
+ - gt-react@11.1.15
20
+
3
21
  ## 11.1.14
4
22
 
5
23
  ### Patch Changes
@@ -32,12 +32,13 @@ function Client_GTProvider(props) {
32
32
  const i18nConfig = (0, gt_i18n_internal.getI18nConfig)();
33
33
  const localeRoutingEnabled = (0, gt_i18n_internal.getCookieValue)(document.cookie, require_utils_cookies.defaultLocaleRoutingEnabledCookieName) === "true";
34
34
  const defaultLocale = i18nConfig.getDefaultLocale();
35
+ const locales = i18nConfig.getLocales();
35
36
  const currentPathname = globalThis.location.pathname;
36
- const localeRoutingApplies = localeRoutingEnabled && require_utils_pathRegex.pathnameMatchesRegex(currentPathname, pathRegex);
37
- const currentPathLocale = localeRoutingApplies ? extractLocale(currentPathname, i18nConfig) : null;
38
- if (localeRoutingApplies && locale === defaultLocale && currentPathLocale && currentPathLocale !== defaultLocale) {
39
- reloadBrowserPage();
40
- return;
37
+ if (localeRoutingEnabled && require_utils_pathRegex.pathnameMatchesRegex(currentPathname, pathRegex) && locale === defaultLocale) {
38
+ if (resolvePathLocale(currentPathname, i18nConfig, defaultLocale, locales) !== defaultLocale) {
39
+ reloadBrowserPage();
40
+ return;
41
+ }
41
42
  }
42
43
  refreshServerComponents();
43
44
  }, [refreshServerComponents, reloadBrowserPage]);
@@ -64,9 +65,7 @@ function usePathCheck({ reloadBrowserPage, refreshServerComponents, locale, refe
64
65
  const locales = i18nConfig.getLocales();
65
66
  const defaultLocale = i18nConfig.getDefaultLocale();
66
67
  if ((0, gt_i18n_internal.getCookieValue)(document.cookie, localeRoutingEnabledCookieName) === "true" && require_utils_pathRegex.pathnameMatchesRegex(pathname, pathRegex)) {
67
- const extractedLocale = extractLocale(pathname, i18nConfig) || defaultLocale;
68
- let currentPathLocale = i18nConfig.determineLocale([i18nConfig.isGTServicesEnabled() ? i18nConfig.standardizeLocale(extractedLocale) : extractedLocale, defaultLocale], locales);
69
- if (currentPathLocale) currentPathLocale = i18nConfig.resolveAliasLocale(currentPathLocale);
68
+ const currentPathLocale = resolvePathLocale(pathname, i18nConfig, defaultLocale, locales);
70
69
  if (currentPathLocale && locales.includes(currentPathLocale) && currentPathLocale !== locale) {
71
70
  document.cookie = `${localeRoutingEnabledCookieName}=;path=/`;
72
71
  if (locale === defaultLocale) reloadBrowserPage();
@@ -82,6 +81,12 @@ function usePathCheck({ reloadBrowserPage, refreshServerComponents, locale, refe
82
81
  refreshServerComponents
83
82
  ]);
84
83
  }
84
+ function resolvePathLocale(pathname, i18nConfig, defaultLocale, locales) {
85
+ const extractedLocale = extractLocale(pathname, i18nConfig);
86
+ if (!extractedLocale) return defaultLocale;
87
+ const currentPathLocale = i18nConfig.determineLocale([i18nConfig.isGTServicesEnabled() ? i18nConfig.standardizeLocale(extractedLocale) : extractedLocale], locales);
88
+ return currentPathLocale ? i18nConfig.resolveAliasLocale(currentPathLocale) : defaultLocale;
89
+ }
85
90
  function extractLocale(pathname, i18nConfig) {
86
91
  const matches = pathname.match(/^\/([^/]+)(?:\/|$)/);
87
92
  return matches ? i18nConfig.resolveAliasLocale(matches[1]) : null;
@@ -1 +1 @@
1
- {"version":3,"file":"client-boundary.js","names":["compilePathRegex","defaultLocaleRoutingEnabledCookieName","pathnameMatchesRegex","GTProvider","defaultReferrerLocaleCookieName"],"sources":["../../src/utils/client-boundary.tsx"],"sourcesContent":["'use client';\n\n/**\n * This is a small boundary for RSC consumption of client components\n * Cannot be consumed through gt-react/index.rsc as deciding btwn\n * gt-react/index.server and gt-react/index.client can only happen\n * here. This matters for GTProvider, but not for LocaleSelector.\n * This pattern is just good to follow for carrying over different\n * behaviors between client and server from gt-react.\n */\n\nexport { LocaleSelector as Client_LocaleSelector } from 'gt-react';\nexport { RegionSelector as Client_RegionSelector } from 'gt-react';\n\nimport { getCookieValue, getI18nConfig, I18nConfig } from 'gt-i18n/internal';\nimport { GTProvider, type SharedGTProviderProps } from 'gt-react';\nimport { usePathname, useRouter } from 'next/navigation';\nimport { useCallback, useEffect } from 'react';\nimport { initializeGTClient } from '../setup/initGT.client';\nimport {\n defaultLocaleRoutingEnabledCookieName,\n defaultReferrerLocaleCookieName,\n} from './cookies';\nimport { compilePathRegex, pathnameMatchesRegex } from './pathRegex';\n\n// withGTConfig exposes this build-time value to both middleware and client code.\nconst pathRegex = compilePathRegex(process.env._GENERALTRANSLATION_PATH_REGEX);\n\n/**\n * Only need to initalize client. We know server was already\n * inialaized by index.rsc.ts. We do not know yet if client\n * has been initialized by index.client.ts.\n */\nif (typeof window !== 'undefined') {\n initializeGTClient();\n}\n\n/**\n * Small wrapper to embed nextjs app router behavior\n */\nexport function Client_GTProvider(props: SharedGTProviderProps) {\n const router = useRouter();\n const refreshServerComponents = useCallback(() => {\n router.refresh();\n }, [router]);\n const reloadBrowserPage = useCallback(() => {\n globalThis.location.reload();\n }, []);\n const syncServerContent = useCallback<\n NonNullable<SharedGTProviderProps['_reload']>\n >(\n ({ locale }) => {\n const i18nConfig = getI18nConfig();\n const localeRoutingEnabled =\n getCookieValue(\n document.cookie,\n defaultLocaleRoutingEnabledCookieName\n ) === 'true';\n const defaultLocale = i18nConfig.getDefaultLocale();\n const currentPathname = globalThis.location.pathname;\n const localeRoutingApplies =\n localeRoutingEnabled &&\n pathnameMatchesRegex(currentPathname, pathRegex);\n const currentPathLocale = localeRoutingApplies\n ? extractLocale(currentPathname, i18nConfig)\n : null;\n\n if (\n localeRoutingApplies &&\n locale === defaultLocale &&\n currentPathLocale &&\n currentPathLocale !== defaultLocale\n ) {\n reloadBrowserPage();\n return;\n }\n\n refreshServerComponents();\n },\n [refreshServerComponents, reloadBrowserPage]\n );\n usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale: props.locale,\n });\n return <GTProvider {...props} _reload={syncServerContent} />;\n}\n\n/**\n * Synchronizes server content if the URL locale does not match the selected\n * locale.\n * TODO: optimize this hook\n */\nfunction usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale,\n referrerLocaleCookieName = defaultReferrerLocaleCookieName,\n localeRoutingEnabledCookieName = defaultLocaleRoutingEnabledCookieName,\n}: {\n reloadBrowserPage: () => void;\n refreshServerComponents: () => void;\n locale: string;\n referrerLocaleCookieName?: string;\n localeRoutingEnabledCookieName?: string;\n}) {\n const pathname = usePathname();\n\n useEffect(() => {\n // Track the referrer locale for middleware\n const i18nConfig = getI18nConfig();\n document.cookie = `${referrerLocaleCookieName}=${i18nConfig.resolveAliasLocale(locale)};path=/`;\n\n // Synchronize server content if the pathname changes\n const locales = i18nConfig.getLocales();\n const defaultLocale = i18nConfig.getDefaultLocale();\n const localeRoutingEnabled =\n getCookieValue(document.cookie, localeRoutingEnabledCookieName) ===\n 'true';\n if (localeRoutingEnabled && pathnameMatchesRegex(pathname, pathRegex)) {\n // Extract locale from pathname\n const extractedLocale =\n extractLocale(pathname, i18nConfig) || defaultLocale;\n let currentPathLocale = i18nConfig.determineLocale(\n [\n i18nConfig.isGTServicesEnabled()\n ? i18nConfig.standardizeLocale(extractedLocale)\n : extractedLocale,\n defaultLocale,\n ],\n locales\n );\n if (currentPathLocale) {\n currentPathLocale = i18nConfig.resolveAliasLocale(currentPathLocale);\n }\n\n if (\n currentPathLocale &&\n locales.includes(currentPathLocale) &&\n currentPathLocale !== locale\n ) {\n // clear cookie (avoids infinite loop when there is no middleware)\n document.cookie = `${localeRoutingEnabledCookieName}=;path=/`;\n\n if (locale === defaultLocale) {\n // A browser navigation follows the middleware redirect that removes\n // the default locale prefix. Next.js router.refresh() does not.\n reloadBrowserPage();\n } else {\n refreshServerComponents();\n }\n }\n }\n }, [\n pathname,\n locale,\n referrerLocaleCookieName,\n localeRoutingEnabledCookieName,\n reloadBrowserPage,\n refreshServerComponents,\n ]);\n}\n\nfunction extractLocale(\n pathname: string,\n i18nConfig: I18nConfig\n): string | null {\n const matches = pathname.match(/^\\/([^/]+)(?:\\/|$)/);\n return matches ? i18nConfig.resolveAliasLocale(matches[1]) : null;\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,MAAM,YAAYA,wBAAAA,iBAAiB,QAAQ,IAAI,+BAA+B;;;;;;AAO9E,IAAI,OAAO,WAAW,YACpB,6BAAA,oBAAoB;;;;AAMtB,SAAgB,kBAAkB,OAA8B;CAC9D,MAAM,UAAA,GAAA,mBAAA,YAAoB;CAC1B,MAAM,2BAAA,GAAA,MAAA,mBAA4C;AAChD,SAAO,SAAS;IACf,CAAC,OAAO,CAAC;CACZ,MAAM,qBAAA,GAAA,MAAA,mBAAsC;AAC1C,aAAW,SAAS,QAAQ;IAC3B,EAAE,CAAC;CACN,MAAM,qBAAA,GAAA,MAAA,cAGH,EAAE,aAAa;EACd,MAAM,cAAA,GAAA,iBAAA,gBAA4B;EAClC,MAAM,wBAAA,GAAA,iBAAA,gBAEF,SAAS,QACTC,sBAAAA,sCACD,KAAK;EACR,MAAM,gBAAgB,WAAW,kBAAkB;EACnD,MAAM,kBAAkB,WAAW,SAAS;EAC5C,MAAM,uBACJ,wBACAC,wBAAAA,qBAAqB,iBAAiB,UAAU;EAClD,MAAM,oBAAoB,uBACtB,cAAc,iBAAiB,WAAW,GAC1C;AAEJ,MACE,wBACA,WAAW,iBACX,qBACA,sBAAsB,eACtB;AACA,sBAAmB;AACnB;;AAGF,2BAAyB;IAE3B,CAAC,yBAAyB,kBAAkB,CAC7C;AACD,cAAa;EACX;EACA;EACA,QAAQ,MAAM;EACf,CAAC;AACF,QAAO,iBAAA,GAAA,kBAAA,KAACC,SAAAA,YAAD;EAAY,GAAI;EAAO,SAAS;EAAqB,CAAA;;;;;;;AAQ9D,SAAS,aAAa,EACpB,mBACA,yBACA,QACA,2BAA2BC,sBAAAA,iCAC3B,iCAAiCH,sBAAAA,yCAOhC;CACD,MAAM,YAAA,GAAA,mBAAA,cAAwB;AAE9B,EAAA,GAAA,MAAA,iBAAgB;EAEd,MAAM,cAAA,GAAA,iBAAA,gBAA4B;AAClC,WAAS,SAAS,GAAG,yBAAyB,GAAG,WAAW,mBAAmB,OAAO,CAAC;EAGvF,MAAM,UAAU,WAAW,YAAY;EACvC,MAAM,gBAAgB,WAAW,kBAAkB;AAInD,OAAA,GAAA,iBAAA,gBAFiB,SAAS,QAAQ,+BAA+B,KAC/D,UAC0BC,wBAAAA,qBAAqB,UAAU,UAAU,EAAE;GAErE,MAAM,kBACJ,cAAc,UAAU,WAAW,IAAI;GACzC,IAAI,oBAAoB,WAAW,gBACjC,CACE,WAAW,qBAAqB,GAC5B,WAAW,kBAAkB,gBAAgB,GAC7C,iBACJ,cACD,EACD,QACD;AACD,OAAI,kBACF,qBAAoB,WAAW,mBAAmB,kBAAkB;AAGtE,OACE,qBACA,QAAQ,SAAS,kBAAkB,IACnC,sBAAsB,QACtB;AAEA,aAAS,SAAS,GAAG,+BAA+B;AAEpD,QAAI,WAAW,cAGb,oBAAmB;QAEnB,0BAAyB;;;IAI9B;EACD;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;AAGJ,SAAS,cACP,UACA,YACe;CACf,MAAM,UAAU,SAAS,MAAM,qBAAqB;AACpD,QAAO,UAAU,WAAW,mBAAmB,QAAQ,GAAG,GAAG"}
1
+ {"version":3,"file":"client-boundary.js","names":["compilePathRegex","defaultLocaleRoutingEnabledCookieName","pathnameMatchesRegex","GTProvider","defaultReferrerLocaleCookieName"],"sources":["../../src/utils/client-boundary.tsx"],"sourcesContent":["'use client';\n\n/**\n * This is a small boundary for RSC consumption of client components\n * Cannot be consumed through gt-react/index.rsc as deciding btwn\n * gt-react/index.server and gt-react/index.client can only happen\n * here. This matters for GTProvider, but not for LocaleSelector.\n * This pattern is just good to follow for carrying over different\n * behaviors between client and server from gt-react.\n */\n\nexport { LocaleSelector as Client_LocaleSelector } from 'gt-react';\nexport { RegionSelector as Client_RegionSelector } from 'gt-react';\n\nimport { getCookieValue, getI18nConfig, I18nConfig } from 'gt-i18n/internal';\nimport { GTProvider, type SharedGTProviderProps } from 'gt-react';\nimport { usePathname, useRouter } from 'next/navigation';\nimport { useCallback, useEffect } from 'react';\nimport { initializeGTClient } from '../setup/initGT.client';\nimport {\n defaultLocaleRoutingEnabledCookieName,\n defaultReferrerLocaleCookieName,\n} from './cookies';\nimport { compilePathRegex, pathnameMatchesRegex } from './pathRegex';\n\n// withGTConfig exposes this build-time value to both middleware and client code.\nconst pathRegex = compilePathRegex(process.env._GENERALTRANSLATION_PATH_REGEX);\n\n/**\n * Only need to initalize client. We know server was already\n * inialaized by index.rsc.ts. We do not know yet if client\n * has been initialized by index.client.ts.\n */\nif (typeof window !== 'undefined') {\n initializeGTClient();\n}\n\n/**\n * Small wrapper to embed nextjs app router behavior\n */\nexport function Client_GTProvider(props: SharedGTProviderProps) {\n const router = useRouter();\n const refreshServerComponents = useCallback(() => {\n router.refresh();\n }, [router]);\n const reloadBrowserPage = useCallback(() => {\n globalThis.location.reload();\n }, []);\n const syncServerContent = useCallback<\n NonNullable<SharedGTProviderProps['_reload']>\n >(\n ({ locale }) => {\n const i18nConfig = getI18nConfig();\n const localeRoutingEnabled =\n getCookieValue(\n document.cookie,\n defaultLocaleRoutingEnabledCookieName\n ) === 'true';\n const defaultLocale = i18nConfig.getDefaultLocale();\n const locales = i18nConfig.getLocales();\n const currentPathname = globalThis.location.pathname;\n const localeRoutingApplies =\n localeRoutingEnabled &&\n pathnameMatchesRegex(currentPathname, pathRegex);\n if (localeRoutingApplies && locale === defaultLocale) {\n const currentPathLocale = resolvePathLocale(\n currentPathname,\n i18nConfig,\n defaultLocale,\n locales\n );\n if (currentPathLocale !== defaultLocale) {\n reloadBrowserPage();\n return;\n }\n }\n\n refreshServerComponents();\n },\n [refreshServerComponents, reloadBrowserPage]\n );\n usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale: props.locale,\n });\n return <GTProvider {...props} _reload={syncServerContent} />;\n}\n\n/**\n * Synchronizes server content if the URL locale does not match the selected\n * locale.\n * TODO: optimize this hook\n */\nfunction usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale,\n referrerLocaleCookieName = defaultReferrerLocaleCookieName,\n localeRoutingEnabledCookieName = defaultLocaleRoutingEnabledCookieName,\n}: {\n reloadBrowserPage: () => void;\n refreshServerComponents: () => void;\n locale: string;\n referrerLocaleCookieName?: string;\n localeRoutingEnabledCookieName?: string;\n}) {\n const pathname = usePathname();\n\n useEffect(() => {\n // Track the referrer locale for middleware\n const i18nConfig = getI18nConfig();\n document.cookie = `${referrerLocaleCookieName}=${i18nConfig.resolveAliasLocale(locale)};path=/`;\n\n // Synchronize server content if the pathname changes\n const locales = i18nConfig.getLocales();\n const defaultLocale = i18nConfig.getDefaultLocale();\n const localeRoutingEnabled =\n getCookieValue(document.cookie, localeRoutingEnabledCookieName) ===\n 'true';\n if (localeRoutingEnabled && pathnameMatchesRegex(pathname, pathRegex)) {\n // Extract locale from pathname\n const currentPathLocale = resolvePathLocale(\n pathname,\n i18nConfig,\n defaultLocale,\n locales\n );\n\n if (\n currentPathLocale &&\n locales.includes(currentPathLocale) &&\n currentPathLocale !== locale\n ) {\n // clear cookie (avoids infinite loop when there is no middleware)\n document.cookie = `${localeRoutingEnabledCookieName}=;path=/`;\n\n if (locale === defaultLocale) {\n // A browser navigation follows the middleware redirect that removes\n // the default locale prefix. Next.js router.refresh() does not.\n reloadBrowserPage();\n } else {\n refreshServerComponents();\n }\n }\n }\n }, [\n pathname,\n locale,\n referrerLocaleCookieName,\n localeRoutingEnabledCookieName,\n reloadBrowserPage,\n refreshServerComponents,\n ]);\n}\n\nfunction resolvePathLocale(\n pathname: string,\n i18nConfig: I18nConfig,\n defaultLocale: string,\n locales: string[]\n): string {\n const extractedLocale = extractLocale(pathname, i18nConfig);\n if (!extractedLocale) {\n return defaultLocale;\n }\n\n const currentPathLocale = i18nConfig.determineLocale(\n [\n i18nConfig.isGTServicesEnabled()\n ? i18nConfig.standardizeLocale(extractedLocale)\n : extractedLocale,\n ],\n locales\n );\n return currentPathLocale\n ? i18nConfig.resolveAliasLocale(currentPathLocale)\n : defaultLocale;\n}\n\nfunction extractLocale(\n pathname: string,\n i18nConfig: I18nConfig\n): string | null {\n const matches = pathname.match(/^\\/([^/]+)(?:\\/|$)/);\n return matches ? i18nConfig.resolveAliasLocale(matches[1]) : null;\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,MAAM,YAAYA,wBAAAA,iBAAiB,QAAQ,IAAI,+BAA+B;;;;;;AAO9E,IAAI,OAAO,WAAW,YACpB,6BAAA,oBAAoB;;;;AAMtB,SAAgB,kBAAkB,OAA8B;CAC9D,MAAM,UAAA,GAAA,mBAAA,YAAoB;CAC1B,MAAM,2BAAA,GAAA,MAAA,mBAA4C;AAChD,SAAO,SAAS;IACf,CAAC,OAAO,CAAC;CACZ,MAAM,qBAAA,GAAA,MAAA,mBAAsC;AAC1C,aAAW,SAAS,QAAQ;IAC3B,EAAE,CAAC;CACN,MAAM,qBAAA,GAAA,MAAA,cAGH,EAAE,aAAa;EACd,MAAM,cAAA,GAAA,iBAAA,gBAA4B;EAClC,MAAM,wBAAA,GAAA,iBAAA,gBAEF,SAAS,QACTC,sBAAAA,sCACD,KAAK;EACR,MAAM,gBAAgB,WAAW,kBAAkB;EACnD,MAAM,UAAU,WAAW,YAAY;EACvC,MAAM,kBAAkB,WAAW,SAAS;AAI5C,MAFE,wBACAC,wBAAAA,qBAAqB,iBAAiB,UAAU,IACtB,WAAW;OACX,kBACxB,iBACA,YACA,eACA,QAEmB,KAAK,eAAe;AACvC,uBAAmB;AACnB;;;AAIJ,2BAAyB;IAE3B,CAAC,yBAAyB,kBAAkB,CAC7C;AACD,cAAa;EACX;EACA;EACA,QAAQ,MAAM;EACf,CAAC;AACF,QAAO,iBAAA,GAAA,kBAAA,KAACC,SAAAA,YAAD;EAAY,GAAI;EAAO,SAAS;EAAqB,CAAA;;;;;;;AAQ9D,SAAS,aAAa,EACpB,mBACA,yBACA,QACA,2BAA2BC,sBAAAA,iCAC3B,iCAAiCH,sBAAAA,yCAOhC;CACD,MAAM,YAAA,GAAA,mBAAA,cAAwB;AAE9B,EAAA,GAAA,MAAA,iBAAgB;EAEd,MAAM,cAAA,GAAA,iBAAA,gBAA4B;AAClC,WAAS,SAAS,GAAG,yBAAyB,GAAG,WAAW,mBAAmB,OAAO,CAAC;EAGvF,MAAM,UAAU,WAAW,YAAY;EACvC,MAAM,gBAAgB,WAAW,kBAAkB;AAInD,OAAA,GAAA,iBAAA,gBAFiB,SAAS,QAAQ,+BAA+B,KAC/D,UAC0BC,wBAAAA,qBAAqB,UAAU,UAAU,EAAE;GAErE,MAAM,oBAAoB,kBACxB,UACA,YACA,eACA,QACD;AAED,OACE,qBACA,QAAQ,SAAS,kBAAkB,IACnC,sBAAsB,QACtB;AAEA,aAAS,SAAS,GAAG,+BAA+B;AAEpD,QAAI,WAAW,cAGb,oBAAmB;QAEnB,0BAAyB;;;IAI9B;EACD;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;AAGJ,SAAS,kBACP,UACA,YACA,eACA,SACQ;CACR,MAAM,kBAAkB,cAAc,UAAU,WAAW;AAC3D,KAAI,CAAC,gBACH,QAAO;CAGT,MAAM,oBAAoB,WAAW,gBACnC,CACE,WAAW,qBAAqB,GAC5B,WAAW,kBAAkB,gBAAgB,GAC7C,gBACL,EACD,QACD;AACD,QAAO,oBACH,WAAW,mBAAmB,kBAAkB,GAChD;;AAGN,SAAS,cACP,UACA,YACe;CACf,MAAM,UAAU,SAAS,MAAM,qBAAqB;AACpD,QAAO,UAAU,WAAW,mBAAmB,QAAQ,GAAG,GAAG"}
@@ -30,12 +30,13 @@ function Client_GTProvider(props) {
30
30
  const i18nConfig = getI18nConfig();
31
31
  const localeRoutingEnabled = getCookieValue(document.cookie, defaultLocaleRoutingEnabledCookieName) === "true";
32
32
  const defaultLocale = i18nConfig.getDefaultLocale();
33
+ const locales = i18nConfig.getLocales();
33
34
  const currentPathname = globalThis.location.pathname;
34
- const localeRoutingApplies = localeRoutingEnabled && pathnameMatchesRegex(currentPathname, pathRegex);
35
- const currentPathLocale = localeRoutingApplies ? extractLocale(currentPathname, i18nConfig) : null;
36
- if (localeRoutingApplies && locale === defaultLocale && currentPathLocale && currentPathLocale !== defaultLocale) {
37
- reloadBrowserPage();
38
- return;
35
+ if (localeRoutingEnabled && pathnameMatchesRegex(currentPathname, pathRegex) && locale === defaultLocale) {
36
+ if (resolvePathLocale(currentPathname, i18nConfig, defaultLocale, locales) !== defaultLocale) {
37
+ reloadBrowserPage();
38
+ return;
39
+ }
39
40
  }
40
41
  refreshServerComponents();
41
42
  }, [refreshServerComponents, reloadBrowserPage]);
@@ -62,9 +63,7 @@ function usePathCheck({ reloadBrowserPage, refreshServerComponents, locale, refe
62
63
  const locales = i18nConfig.getLocales();
63
64
  const defaultLocale = i18nConfig.getDefaultLocale();
64
65
  if (getCookieValue(document.cookie, localeRoutingEnabledCookieName) === "true" && pathnameMatchesRegex(pathname, pathRegex)) {
65
- const extractedLocale = extractLocale(pathname, i18nConfig) || defaultLocale;
66
- let currentPathLocale = i18nConfig.determineLocale([i18nConfig.isGTServicesEnabled() ? i18nConfig.standardizeLocale(extractedLocale) : extractedLocale, defaultLocale], locales);
67
- if (currentPathLocale) currentPathLocale = i18nConfig.resolveAliasLocale(currentPathLocale);
66
+ const currentPathLocale = resolvePathLocale(pathname, i18nConfig, defaultLocale, locales);
68
67
  if (currentPathLocale && locales.includes(currentPathLocale) && currentPathLocale !== locale) {
69
68
  document.cookie = `${localeRoutingEnabledCookieName}=;path=/`;
70
69
  if (locale === defaultLocale) reloadBrowserPage();
@@ -80,6 +79,12 @@ function usePathCheck({ reloadBrowserPage, refreshServerComponents, locale, refe
80
79
  refreshServerComponents
81
80
  ]);
82
81
  }
82
+ function resolvePathLocale(pathname, i18nConfig, defaultLocale, locales) {
83
+ const extractedLocale = extractLocale(pathname, i18nConfig);
84
+ if (!extractedLocale) return defaultLocale;
85
+ const currentPathLocale = i18nConfig.determineLocale([i18nConfig.isGTServicesEnabled() ? i18nConfig.standardizeLocale(extractedLocale) : extractedLocale], locales);
86
+ return currentPathLocale ? i18nConfig.resolveAliasLocale(currentPathLocale) : defaultLocale;
87
+ }
83
88
  function extractLocale(pathname, i18nConfig) {
84
89
  const matches = pathname.match(/^\/([^/]+)(?:\/|$)/);
85
90
  return matches ? i18nConfig.resolveAliasLocale(matches[1]) : null;
@@ -1 +1 @@
1
- {"version":3,"file":"client-boundary.mjs","names":[],"sources":["../../src/utils/client-boundary.tsx"],"sourcesContent":["'use client';\n\n/**\n * This is a small boundary for RSC consumption of client components\n * Cannot be consumed through gt-react/index.rsc as deciding btwn\n * gt-react/index.server and gt-react/index.client can only happen\n * here. This matters for GTProvider, but not for LocaleSelector.\n * This pattern is just good to follow for carrying over different\n * behaviors between client and server from gt-react.\n */\n\nexport { LocaleSelector as Client_LocaleSelector } from 'gt-react';\nexport { RegionSelector as Client_RegionSelector } from 'gt-react';\n\nimport { getCookieValue, getI18nConfig, I18nConfig } from 'gt-i18n/internal';\nimport { GTProvider, type SharedGTProviderProps } from 'gt-react';\nimport { usePathname, useRouter } from 'next/navigation';\nimport { useCallback, useEffect } from 'react';\nimport { initializeGTClient } from '../setup/initGT.client';\nimport {\n defaultLocaleRoutingEnabledCookieName,\n defaultReferrerLocaleCookieName,\n} from './cookies';\nimport { compilePathRegex, pathnameMatchesRegex } from './pathRegex';\n\n// withGTConfig exposes this build-time value to both middleware and client code.\nconst pathRegex = compilePathRegex(process.env._GENERALTRANSLATION_PATH_REGEX);\n\n/**\n * Only need to initalize client. We know server was already\n * inialaized by index.rsc.ts. We do not know yet if client\n * has been initialized by index.client.ts.\n */\nif (typeof window !== 'undefined') {\n initializeGTClient();\n}\n\n/**\n * Small wrapper to embed nextjs app router behavior\n */\nexport function Client_GTProvider(props: SharedGTProviderProps) {\n const router = useRouter();\n const refreshServerComponents = useCallback(() => {\n router.refresh();\n }, [router]);\n const reloadBrowserPage = useCallback(() => {\n globalThis.location.reload();\n }, []);\n const syncServerContent = useCallback<\n NonNullable<SharedGTProviderProps['_reload']>\n >(\n ({ locale }) => {\n const i18nConfig = getI18nConfig();\n const localeRoutingEnabled =\n getCookieValue(\n document.cookie,\n defaultLocaleRoutingEnabledCookieName\n ) === 'true';\n const defaultLocale = i18nConfig.getDefaultLocale();\n const currentPathname = globalThis.location.pathname;\n const localeRoutingApplies =\n localeRoutingEnabled &&\n pathnameMatchesRegex(currentPathname, pathRegex);\n const currentPathLocale = localeRoutingApplies\n ? extractLocale(currentPathname, i18nConfig)\n : null;\n\n if (\n localeRoutingApplies &&\n locale === defaultLocale &&\n currentPathLocale &&\n currentPathLocale !== defaultLocale\n ) {\n reloadBrowserPage();\n return;\n }\n\n refreshServerComponents();\n },\n [refreshServerComponents, reloadBrowserPage]\n );\n usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale: props.locale,\n });\n return <GTProvider {...props} _reload={syncServerContent} />;\n}\n\n/**\n * Synchronizes server content if the URL locale does not match the selected\n * locale.\n * TODO: optimize this hook\n */\nfunction usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale,\n referrerLocaleCookieName = defaultReferrerLocaleCookieName,\n localeRoutingEnabledCookieName = defaultLocaleRoutingEnabledCookieName,\n}: {\n reloadBrowserPage: () => void;\n refreshServerComponents: () => void;\n locale: string;\n referrerLocaleCookieName?: string;\n localeRoutingEnabledCookieName?: string;\n}) {\n const pathname = usePathname();\n\n useEffect(() => {\n // Track the referrer locale for middleware\n const i18nConfig = getI18nConfig();\n document.cookie = `${referrerLocaleCookieName}=${i18nConfig.resolveAliasLocale(locale)};path=/`;\n\n // Synchronize server content if the pathname changes\n const locales = i18nConfig.getLocales();\n const defaultLocale = i18nConfig.getDefaultLocale();\n const localeRoutingEnabled =\n getCookieValue(document.cookie, localeRoutingEnabledCookieName) ===\n 'true';\n if (localeRoutingEnabled && pathnameMatchesRegex(pathname, pathRegex)) {\n // Extract locale from pathname\n const extractedLocale =\n extractLocale(pathname, i18nConfig) || defaultLocale;\n let currentPathLocale = i18nConfig.determineLocale(\n [\n i18nConfig.isGTServicesEnabled()\n ? i18nConfig.standardizeLocale(extractedLocale)\n : extractedLocale,\n defaultLocale,\n ],\n locales\n );\n if (currentPathLocale) {\n currentPathLocale = i18nConfig.resolveAliasLocale(currentPathLocale);\n }\n\n if (\n currentPathLocale &&\n locales.includes(currentPathLocale) &&\n currentPathLocale !== locale\n ) {\n // clear cookie (avoids infinite loop when there is no middleware)\n document.cookie = `${localeRoutingEnabledCookieName}=;path=/`;\n\n if (locale === defaultLocale) {\n // A browser navigation follows the middleware redirect that removes\n // the default locale prefix. Next.js router.refresh() does not.\n reloadBrowserPage();\n } else {\n refreshServerComponents();\n }\n }\n }\n }, [\n pathname,\n locale,\n referrerLocaleCookieName,\n localeRoutingEnabledCookieName,\n reloadBrowserPage,\n refreshServerComponents,\n ]);\n}\n\nfunction extractLocale(\n pathname: string,\n i18nConfig: I18nConfig\n): string | null {\n const matches = pathname.match(/^\\/([^/]+)(?:\\/|$)/);\n return matches ? i18nConfig.resolveAliasLocale(matches[1]) : null;\n}\n"],"mappings":";;;;;;;;;;AA0BA,MAAM,YAAY,iBAAiB,QAAQ,IAAI,+BAA+B;;;;;;AAO9E,IAAI,OAAO,WAAW,YACpB,qBAAoB;;;;AAMtB,SAAgB,kBAAkB,OAA8B;CAC9D,MAAM,SAAS,WAAW;CAC1B,MAAM,0BAA0B,kBAAkB;AAChD,SAAO,SAAS;IACf,CAAC,OAAO,CAAC;CACZ,MAAM,oBAAoB,kBAAkB;AAC1C,aAAW,SAAS,QAAQ;IAC3B,EAAE,CAAC;CACN,MAAM,oBAAoB,aAGvB,EAAE,aAAa;EACd,MAAM,aAAa,eAAe;EAClC,MAAM,uBACJ,eACE,SAAS,QACT,sCACD,KAAK;EACR,MAAM,gBAAgB,WAAW,kBAAkB;EACnD,MAAM,kBAAkB,WAAW,SAAS;EAC5C,MAAM,uBACJ,wBACA,qBAAqB,iBAAiB,UAAU;EAClD,MAAM,oBAAoB,uBACtB,cAAc,iBAAiB,WAAW,GAC1C;AAEJ,MACE,wBACA,WAAW,iBACX,qBACA,sBAAsB,eACtB;AACA,sBAAmB;AACnB;;AAGF,2BAAyB;IAE3B,CAAC,yBAAyB,kBAAkB,CAC7C;AACD,cAAa;EACX;EACA;EACA,QAAQ,MAAM;EACf,CAAC;AACF,QAAO,oBAAC,YAAD;EAAY,GAAI;EAAO,SAAS;EAAqB,CAAA;;;;;;;AAQ9D,SAAS,aAAa,EACpB,mBACA,yBACA,QACA,2BAA2B,iCAC3B,iCAAiC,yCAOhC;CACD,MAAM,WAAW,aAAa;AAE9B,iBAAgB;EAEd,MAAM,aAAa,eAAe;AAClC,WAAS,SAAS,GAAG,yBAAyB,GAAG,WAAW,mBAAmB,OAAO,CAAC;EAGvF,MAAM,UAAU,WAAW,YAAY;EACvC,MAAM,gBAAgB,WAAW,kBAAkB;AAInD,MAFE,eAAe,SAAS,QAAQ,+BAA+B,KAC/D,UAC0B,qBAAqB,UAAU,UAAU,EAAE;GAErE,MAAM,kBACJ,cAAc,UAAU,WAAW,IAAI;GACzC,IAAI,oBAAoB,WAAW,gBACjC,CACE,WAAW,qBAAqB,GAC5B,WAAW,kBAAkB,gBAAgB,GAC7C,iBACJ,cACD,EACD,QACD;AACD,OAAI,kBACF,qBAAoB,WAAW,mBAAmB,kBAAkB;AAGtE,OACE,qBACA,QAAQ,SAAS,kBAAkB,IACnC,sBAAsB,QACtB;AAEA,aAAS,SAAS,GAAG,+BAA+B;AAEpD,QAAI,WAAW,cAGb,oBAAmB;QAEnB,0BAAyB;;;IAI9B;EACD;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;AAGJ,SAAS,cACP,UACA,YACe;CACf,MAAM,UAAU,SAAS,MAAM,qBAAqB;AACpD,QAAO,UAAU,WAAW,mBAAmB,QAAQ,GAAG,GAAG"}
1
+ {"version":3,"file":"client-boundary.mjs","names":[],"sources":["../../src/utils/client-boundary.tsx"],"sourcesContent":["'use client';\n\n/**\n * This is a small boundary for RSC consumption of client components\n * Cannot be consumed through gt-react/index.rsc as deciding btwn\n * gt-react/index.server and gt-react/index.client can only happen\n * here. This matters for GTProvider, but not for LocaleSelector.\n * This pattern is just good to follow for carrying over different\n * behaviors between client and server from gt-react.\n */\n\nexport { LocaleSelector as Client_LocaleSelector } from 'gt-react';\nexport { RegionSelector as Client_RegionSelector } from 'gt-react';\n\nimport { getCookieValue, getI18nConfig, I18nConfig } from 'gt-i18n/internal';\nimport { GTProvider, type SharedGTProviderProps } from 'gt-react';\nimport { usePathname, useRouter } from 'next/navigation';\nimport { useCallback, useEffect } from 'react';\nimport { initializeGTClient } from '../setup/initGT.client';\nimport {\n defaultLocaleRoutingEnabledCookieName,\n defaultReferrerLocaleCookieName,\n} from './cookies';\nimport { compilePathRegex, pathnameMatchesRegex } from './pathRegex';\n\n// withGTConfig exposes this build-time value to both middleware and client code.\nconst pathRegex = compilePathRegex(process.env._GENERALTRANSLATION_PATH_REGEX);\n\n/**\n * Only need to initalize client. We know server was already\n * inialaized by index.rsc.ts. We do not know yet if client\n * has been initialized by index.client.ts.\n */\nif (typeof window !== 'undefined') {\n initializeGTClient();\n}\n\n/**\n * Small wrapper to embed nextjs app router behavior\n */\nexport function Client_GTProvider(props: SharedGTProviderProps) {\n const router = useRouter();\n const refreshServerComponents = useCallback(() => {\n router.refresh();\n }, [router]);\n const reloadBrowserPage = useCallback(() => {\n globalThis.location.reload();\n }, []);\n const syncServerContent = useCallback<\n NonNullable<SharedGTProviderProps['_reload']>\n >(\n ({ locale }) => {\n const i18nConfig = getI18nConfig();\n const localeRoutingEnabled =\n getCookieValue(\n document.cookie,\n defaultLocaleRoutingEnabledCookieName\n ) === 'true';\n const defaultLocale = i18nConfig.getDefaultLocale();\n const locales = i18nConfig.getLocales();\n const currentPathname = globalThis.location.pathname;\n const localeRoutingApplies =\n localeRoutingEnabled &&\n pathnameMatchesRegex(currentPathname, pathRegex);\n if (localeRoutingApplies && locale === defaultLocale) {\n const currentPathLocale = resolvePathLocale(\n currentPathname,\n i18nConfig,\n defaultLocale,\n locales\n );\n if (currentPathLocale !== defaultLocale) {\n reloadBrowserPage();\n return;\n }\n }\n\n refreshServerComponents();\n },\n [refreshServerComponents, reloadBrowserPage]\n );\n usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale: props.locale,\n });\n return <GTProvider {...props} _reload={syncServerContent} />;\n}\n\n/**\n * Synchronizes server content if the URL locale does not match the selected\n * locale.\n * TODO: optimize this hook\n */\nfunction usePathCheck({\n reloadBrowserPage,\n refreshServerComponents,\n locale,\n referrerLocaleCookieName = defaultReferrerLocaleCookieName,\n localeRoutingEnabledCookieName = defaultLocaleRoutingEnabledCookieName,\n}: {\n reloadBrowserPage: () => void;\n refreshServerComponents: () => void;\n locale: string;\n referrerLocaleCookieName?: string;\n localeRoutingEnabledCookieName?: string;\n}) {\n const pathname = usePathname();\n\n useEffect(() => {\n // Track the referrer locale for middleware\n const i18nConfig = getI18nConfig();\n document.cookie = `${referrerLocaleCookieName}=${i18nConfig.resolveAliasLocale(locale)};path=/`;\n\n // Synchronize server content if the pathname changes\n const locales = i18nConfig.getLocales();\n const defaultLocale = i18nConfig.getDefaultLocale();\n const localeRoutingEnabled =\n getCookieValue(document.cookie, localeRoutingEnabledCookieName) ===\n 'true';\n if (localeRoutingEnabled && pathnameMatchesRegex(pathname, pathRegex)) {\n // Extract locale from pathname\n const currentPathLocale = resolvePathLocale(\n pathname,\n i18nConfig,\n defaultLocale,\n locales\n );\n\n if (\n currentPathLocale &&\n locales.includes(currentPathLocale) &&\n currentPathLocale !== locale\n ) {\n // clear cookie (avoids infinite loop when there is no middleware)\n document.cookie = `${localeRoutingEnabledCookieName}=;path=/`;\n\n if (locale === defaultLocale) {\n // A browser navigation follows the middleware redirect that removes\n // the default locale prefix. Next.js router.refresh() does not.\n reloadBrowserPage();\n } else {\n refreshServerComponents();\n }\n }\n }\n }, [\n pathname,\n locale,\n referrerLocaleCookieName,\n localeRoutingEnabledCookieName,\n reloadBrowserPage,\n refreshServerComponents,\n ]);\n}\n\nfunction resolvePathLocale(\n pathname: string,\n i18nConfig: I18nConfig,\n defaultLocale: string,\n locales: string[]\n): string {\n const extractedLocale = extractLocale(pathname, i18nConfig);\n if (!extractedLocale) {\n return defaultLocale;\n }\n\n const currentPathLocale = i18nConfig.determineLocale(\n [\n i18nConfig.isGTServicesEnabled()\n ? i18nConfig.standardizeLocale(extractedLocale)\n : extractedLocale,\n ],\n locales\n );\n return currentPathLocale\n ? i18nConfig.resolveAliasLocale(currentPathLocale)\n : defaultLocale;\n}\n\nfunction extractLocale(\n pathname: string,\n i18nConfig: I18nConfig\n): string | null {\n const matches = pathname.match(/^\\/([^/]+)(?:\\/|$)/);\n return matches ? i18nConfig.resolveAliasLocale(matches[1]) : null;\n}\n"],"mappings":";;;;;;;;;;AA0BA,MAAM,YAAY,iBAAiB,QAAQ,IAAI,+BAA+B;;;;;;AAO9E,IAAI,OAAO,WAAW,YACpB,qBAAoB;;;;AAMtB,SAAgB,kBAAkB,OAA8B;CAC9D,MAAM,SAAS,WAAW;CAC1B,MAAM,0BAA0B,kBAAkB;AAChD,SAAO,SAAS;IACf,CAAC,OAAO,CAAC;CACZ,MAAM,oBAAoB,kBAAkB;AAC1C,aAAW,SAAS,QAAQ;IAC3B,EAAE,CAAC;CACN,MAAM,oBAAoB,aAGvB,EAAE,aAAa;EACd,MAAM,aAAa,eAAe;EAClC,MAAM,uBACJ,eACE,SAAS,QACT,sCACD,KAAK;EACR,MAAM,gBAAgB,WAAW,kBAAkB;EACnD,MAAM,UAAU,WAAW,YAAY;EACvC,MAAM,kBAAkB,WAAW,SAAS;AAI5C,MAFE,wBACA,qBAAqB,iBAAiB,UAAU,IACtB,WAAW;OACX,kBACxB,iBACA,YACA,eACA,QAEmB,KAAK,eAAe;AACvC,uBAAmB;AACnB;;;AAIJ,2BAAyB;IAE3B,CAAC,yBAAyB,kBAAkB,CAC7C;AACD,cAAa;EACX;EACA;EACA,QAAQ,MAAM;EACf,CAAC;AACF,QAAO,oBAAC,YAAD;EAAY,GAAI;EAAO,SAAS;EAAqB,CAAA;;;;;;;AAQ9D,SAAS,aAAa,EACpB,mBACA,yBACA,QACA,2BAA2B,iCAC3B,iCAAiC,yCAOhC;CACD,MAAM,WAAW,aAAa;AAE9B,iBAAgB;EAEd,MAAM,aAAa,eAAe;AAClC,WAAS,SAAS,GAAG,yBAAyB,GAAG,WAAW,mBAAmB,OAAO,CAAC;EAGvF,MAAM,UAAU,WAAW,YAAY;EACvC,MAAM,gBAAgB,WAAW,kBAAkB;AAInD,MAFE,eAAe,SAAS,QAAQ,+BAA+B,KAC/D,UAC0B,qBAAqB,UAAU,UAAU,EAAE;GAErE,MAAM,oBAAoB,kBACxB,UACA,YACA,eACA,QACD;AAED,OACE,qBACA,QAAQ,SAAS,kBAAkB,IACnC,sBAAsB,QACtB;AAEA,aAAS,SAAS,GAAG,+BAA+B;AAEpD,QAAI,WAAW,cAGb,oBAAmB;QAEnB,0BAAyB;;;IAI9B;EACD;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;AAGJ,SAAS,kBACP,UACA,YACA,eACA,SACQ;CACR,MAAM,kBAAkB,cAAc,UAAU,WAAW;AAC3D,KAAI,CAAC,gBACH,QAAO;CAGT,MAAM,oBAAoB,WAAW,gBACnC,CACE,WAAW,qBAAqB,GAC5B,WAAW,kBAAkB,gBAAgB,GAC7C,gBACL,EACD,QACD;AACD,QAAO,oBACH,WAAW,mBAAmB,kBAAkB,GAChD;;AAGN,SAAS,cACP,UACA,YACe;CACf,MAAM,UAAU,SAAS,MAAM,qBAAqB;AACpD,QAAO,UAAU,WAAW,mBAAmB,QAAQ,GAAG,GAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gt-next",
3
- "version": "11.1.14",
3
+ "version": "11.1.16",
4
4
  "description": "A Next.js library for automatic internationalization.",
5
5
  "main": "dist/index.server.js",
6
6
  "peerDependencies": {
@@ -29,9 +29,9 @@
29
29
  ],
30
30
  "dependencies": {
31
31
  "@generaltranslation/format": "0.1.8",
32
- "@generaltranslation/react-core": "11.1.14",
32
+ "@generaltranslation/react-core": "11.1.16",
33
33
  "generaltranslation": "9.1.7",
34
- "gt-react": "11.1.14",
34
+ "gt-react": "11.1.16",
35
35
  "gt-i18n": "1.0.17"
36
36
  },
37
37
  "repository": {