@akinon/next 1.48.0-rc.0 → 1.48.0-rc.2

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,17 @@
1
1
  # @akinon/next
2
2
 
3
+ ## 1.48.0-rc.2
4
+
5
+ ### Minor Changes
6
+
7
+ - 2e6104d: ZERO-2888:Edit the numbering in the pagination and the visibility of the prev and next buttons
8
+
9
+ ## 1.48.0-rc.1
10
+
11
+ ### Minor Changes
12
+
13
+ - fdd0b41: ZERO-2706: Add optimized translation support
14
+
3
15
  ## 1.48.0-rc.0
4
16
 
5
17
  ### Minor Changes
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const localesPath = path.resolve(`public/locales/`);
6
+
7
+ async function generateTranslationIndex(locale_) {
8
+ let translations = {};
9
+
10
+ try {
11
+ const localeDirPath = path.resolve(`public/locales/${locale_}`);
12
+ const fileNames = fs.readdirSync(localeDirPath);
13
+
14
+ for await (const fileName of fileNames) {
15
+ if (fileName === 'index.json') {
16
+ continue;
17
+ }
18
+
19
+ const data = fs.readFileSync(
20
+ path.join(localeDirPath, `/${fileName}`),
21
+ 'utf-8'
22
+ );
23
+
24
+ translations[fileName.substring(0, fileName.lastIndexOf('.'))] =
25
+ JSON.parse(data);
26
+ }
27
+
28
+ fs.writeFileSync(
29
+ path.resolve(`public/locales/${locale_}/index.json`),
30
+ JSON.stringify(translations)
31
+ );
32
+ } catch (error) {
33
+ console.error(error);
34
+ }
35
+ }
36
+
37
+ const localePaths = fs.readdirSync(localesPath);
38
+
39
+ localePaths.forEach((localePath) => {
40
+ generateTranslationIndex(localePath);
41
+ });
@@ -4,3 +4,4 @@ const runScript = require('./run-script');
4
4
 
5
5
  runScript('pz-install-theme.js');
6
6
  runScript('pz-pre-check-dist.js');
7
+ runScript('pz-generate-translations.js');
package/bin/pz-predev.js CHANGED
@@ -5,3 +5,4 @@ const runScript = require('./run-script');
5
5
  runScript('pz-install-extensions.js');
6
6
  runScript('pz-check-env.js');
7
7
  runScript('pz-install-theme.js');
8
+ runScript('pz-generate-translations.js');
@@ -3,17 +3,29 @@ import ClientRoot from './client-root';
3
3
  import { cookies } from 'next/headers';
4
4
  import PzProviders from './pz-providers';
5
5
  import { WebVitals } from './web-vitals';
6
+ import settings from 'settings';
6
7
 
7
- export default function PzRoot({
8
+ export default async function PzRoot({
8
9
  translations,
9
- children
10
+ children,
11
+ locale
10
12
  }: {
11
- translations: any;
13
+ translations?: any;
12
14
  children: React.ReactNode;
15
+ locale?: string;
13
16
  }) {
14
17
  const nextCookies = cookies();
15
18
  const sessionid = nextCookies.get('osessionid')?.value;
16
19
 
20
+ if (!translations) {
21
+ const { getTranslations } =
22
+ settings.useOptimizedTranslations && locale
23
+ ? require('translations')
24
+ : require('../utils/server-translation');
25
+
26
+ translations = await getTranslations(locale);
27
+ }
28
+
17
29
  return (
18
30
  <PzProviders translations={translations}>
19
31
  <WebVitals />
@@ -5,26 +5,32 @@ import { category, product } from '../urls';
5
5
  import { Cache, CacheKey } from '../../lib/cache';
6
6
  import { parse } from 'lossless-json';
7
7
  import logger from '../../utils/log';
8
+ import { headers as nHeaders } from 'next/headers';
9
+ import { ServerVariables } from '../../utils/server-variables';
8
10
 
9
11
  function getCategoryDataHandler(
10
12
  pk: number,
11
- searchParams?: { [key: string]: string | string[] | undefined },
13
+ locale: string,
14
+ currency: string,
15
+ searchParams?: URLSearchParams,
12
16
  headers?: Record<string, string>
13
17
  ) {
14
18
  return async function () {
15
19
  const params = generateCommerceSearchParams(searchParams);
16
20
 
17
- const rawData = await appFetch<string>(
18
- `${category.getCategoryByPk(pk)}${params ? params : ''}`,
19
- {
21
+ const rawData = await appFetch<string>({
22
+ url: `${category.getCategoryByPk(pk)}${params ? params : ''}`,
23
+ locale,
24
+ currency,
25
+ init: {
20
26
  headers: {
21
27
  Accept: 'application/json',
22
28
  'Content-Type': 'application/json',
23
29
  ...(headers ?? {})
24
30
  }
25
31
  },
26
- FetchResponseType.TEXT
27
- );
32
+ responseType: FetchResponseType.TEXT
33
+ });
28
34
 
29
35
  let data: GetCategoryResponse;
30
36
 
@@ -58,15 +64,17 @@ function getCategoryDataHandler(
58
64
  return { data, breadcrumbData: undefined };
59
65
  }
60
66
 
61
- const breadcrumbData = await appFetch<any>(
62
- product.breadcrumbUrl(menuItemModel),
63
- {
67
+ const breadcrumbData = await appFetch<any>({
68
+ url: product.breadcrumbUrl(menuItemModel),
69
+ locale,
70
+ currency,
71
+ init: {
64
72
  headers: {
65
73
  Accept: 'application/json',
66
74
  'Content-Type': 'application/json'
67
75
  }
68
76
  }
69
- );
77
+ });
70
78
 
71
79
  return { data, breadcrumbData: breadcrumbData?.menu };
72
80
  };
@@ -75,33 +83,44 @@ function getCategoryDataHandler(
75
83
  export const getCategoryData = ({
76
84
  pk,
77
85
  searchParams,
78
- headers
86
+ headers,
87
+ locale = ServerVariables.locale,
88
+ currency = ServerVariables.currency
79
89
  }: {
80
90
  pk: number;
81
- searchParams?: { [key: string]: string | string[] | undefined };
91
+ locale?: string;
92
+ currency?: string;
93
+ searchParams?: URLSearchParams;
82
94
  headers?: Record<string, string>;
83
95
  }) => {
84
96
  return Cache.wrap(
85
97
  CacheKey.Category(pk, searchParams, headers),
86
- getCategoryDataHandler(pk, searchParams, headers),
98
+ locale,
99
+ getCategoryDataHandler(pk, locale, currency, searchParams, headers),
87
100
  {
88
101
  expire: 300
89
102
  }
90
103
  );
91
104
  };
92
105
 
93
- function getCategoryBySlugDataHandler(slug: string) {
106
+ function getCategoryBySlugDataHandler(
107
+ slug: string,
108
+ locale: string,
109
+ currency: string
110
+ ) {
94
111
  return async function () {
95
- const rawData = await appFetch<string>(
96
- category.getCategoryBySlug(slug),
97
- {
112
+ const rawData = await appFetch<string>({
113
+ url: category.getCategoryBySlug(slug),
114
+ locale,
115
+ currency,
116
+ init: {
98
117
  headers: {
99
118
  Accept: 'application/json',
100
119
  'Content-Type': 'application/json'
101
120
  }
102
121
  },
103
- FetchResponseType.TEXT
104
- );
122
+ responseType: FetchResponseType.TEXT
123
+ });
105
124
 
106
125
  let data: GetCategoryResponse;
107
126
 
@@ -129,10 +148,15 @@ function getCategoryBySlugDataHandler(slug: string) {
129
148
  };
130
149
  }
131
150
 
132
- export const getCategoryBySlugData = async ({ slug }) => {
151
+ export const getCategoryBySlugData = async ({
152
+ slug,
153
+ locale = ServerVariables.locale,
154
+ currency = ServerVariables.currency
155
+ }) => {
133
156
  return Cache.wrap(
134
157
  CacheKey.CategorySlug(slug),
135
- getCategoryBySlugDataHandler(slug),
158
+ locale,
159
+ getCategoryBySlugDataHandler(slug, locale, currency),
136
160
  {
137
161
  expire: 300
138
162
  }
@@ -2,13 +2,23 @@ import { flatpage } from '../urls';
2
2
  import { FlatPage } from '../../types';
3
3
  import appFetch from '../../utils/app-fetch';
4
4
  import { Cache, CacheKey } from '../../lib/cache';
5
+ import { ServerVariables } from '../../utils/server-variables';
5
6
 
6
- const getFlatPageDataHandler = (pk: number) => {
7
+ const getFlatPageDataHandler = (
8
+ pk: number,
9
+ locale: string,
10
+ currency: string
11
+ ) => {
7
12
  return async function () {
8
- const data = await appFetch<FlatPage>(flatpage.getFlatPageByPk(pk), {
9
- headers: {
10
- Accept: 'application/json',
11
- 'Content-Type': 'application/json'
13
+ const data = await appFetch<FlatPage>({
14
+ url: flatpage.getFlatPageByPk(pk),
15
+ locale,
16
+ currency,
17
+ init: {
18
+ headers: {
19
+ Accept: 'application/json',
20
+ 'Content-Type': 'application/json'
21
+ }
12
22
  }
13
23
  });
14
24
 
@@ -16,6 +26,18 @@ const getFlatPageDataHandler = (pk: number) => {
16
26
  };
17
27
  };
18
28
 
19
- export const getFlatPageData = ({ pk }: { pk: number }) => {
20
- return Cache.wrap(CacheKey.FlatPage(pk), getFlatPageDataHandler(pk));
29
+ export const getFlatPageData = ({
30
+ pk,
31
+ locale = ServerVariables.locale,
32
+ currency = ServerVariables.currency
33
+ }: {
34
+ pk: number;
35
+ locale?: string;
36
+ currency?: string;
37
+ }) => {
38
+ return Cache.wrap(
39
+ CacheKey.FlatPage(pk),
40
+ locale,
41
+ getFlatPageDataHandler(pk, locale, currency)
42
+ );
21
43
  };
@@ -1,15 +1,21 @@
1
- import { Cache, CacheKey } from "../../lib/cache";
2
- import { FormType } from "../../types/commerce/form";
1
+ import { Cache, CacheKey } from '../../lib/cache';
2
+ import { FormType } from '../../types/commerce/form';
3
3
 
4
- import appFetch from "../../utils/app-fetch";
5
- import { form } from "../urls";
4
+ import appFetch from '../../utils/app-fetch';
5
+ import { ServerVariables } from '../../utils/server-variables';
6
+ import { form } from '../urls';
6
7
 
7
- const getFormDataHandler = (pk: number) => {
8
+ const getFormDataHandler = (pk: number, locale: string, currency: string) => {
8
9
  return async function () {
9
- const data = await appFetch<FormType>(form.getForm(pk), {
10
- headers: {
11
- Accept: 'application/json',
12
- 'Content-Type': 'application/json'
10
+ const data = await appFetch<FormType>({
11
+ url: form.getForm(pk),
12
+ locale,
13
+ currency,
14
+ init: {
15
+ headers: {
16
+ Accept: 'application/json',
17
+ 'Content-Type': 'application/json'
18
+ }
13
19
  }
14
20
  });
15
21
 
@@ -17,6 +23,18 @@ const getFormDataHandler = (pk: number) => {
17
23
  };
18
24
  };
19
25
 
20
- export const getFormData = ({ pk }: { pk: number }) => {
21
- return Cache.wrap(CacheKey.Form(pk), getFormDataHandler(pk));
26
+ export const getFormData = ({
27
+ pk,
28
+ locale = ServerVariables.locale,
29
+ currency = ServerVariables.currency
30
+ }: {
31
+ pk: number;
32
+ locale?: string;
33
+ currency?: string;
34
+ }) => {
35
+ return Cache.wrap(
36
+ CacheKey.Form(pk),
37
+ locale,
38
+ getFormDataHandler(pk, locale, currency)
39
+ );
22
40
  };
@@ -2,23 +2,42 @@ import { landingpage } from '../urls';
2
2
  import { LandingPage } from '../../types/commerce/landingpage';
3
3
  import appFetch from '../../utils/app-fetch';
4
4
  import { Cache, CacheKey } from '../../lib/cache';
5
+ import { ServerVariables } from '../../utils/server-variables';
5
6
 
6
- const getLandingPageHandler = (pk: number) => {
7
+ const getLandingPageHandler = (
8
+ pk: number,
9
+ locale: string,
10
+ currency: string
11
+ ) => {
7
12
  return async function () {
8
- const data = await appFetch<LandingPage>(
9
- landingpage.getLandingPageByPk(pk),
10
- {
13
+ const data = await appFetch<LandingPage>({
14
+ url: landingpage.getLandingPageByPk(pk),
15
+ locale,
16
+ currency,
17
+ init: {
11
18
  headers: {
12
19
  Accept: 'application/json',
13
20
  'Content-Type': 'application/json'
14
21
  }
15
22
  }
16
- );
23
+ });
17
24
 
18
25
  return data;
19
26
  };
20
27
  };
21
28
 
22
- export const getLandingPageData = ({ pk }: { pk: number }) => {
23
- return Cache.wrap(CacheKey.LandingPage(pk), getLandingPageHandler(pk));
29
+ export const getLandingPageData = ({
30
+ pk,
31
+ locale = ServerVariables.locale,
32
+ currency = ServerVariables.currency
33
+ }: {
34
+ pk: number;
35
+ locale?: string;
36
+ currency?: string;
37
+ }) => {
38
+ return Cache.wrap(
39
+ CacheKey.LandingPage(pk),
40
+ locale,
41
+ getLandingPageHandler(pk, locale, currency)
42
+ );
24
43
  };
@@ -5,25 +5,30 @@ import { generateCommerceSearchParams } from '../../utils';
5
5
  import appFetch, { FetchResponseType } from '../../utils/app-fetch';
6
6
  import { parse } from 'lossless-json';
7
7
  import logger from '../../utils/log';
8
+ import { ServerVariables } from '../../utils/server-variables';
8
9
 
9
10
  const getListDataHandler = (
10
- searchParams: { [key: string]: string | string[] | undefined },
11
+ locale,
12
+ currency,
13
+ searchParams: URLSearchParams,
11
14
  headers?: Record<string, string>
12
15
  ) => {
13
16
  return async function () {
14
17
  const params = generateCommerceSearchParams(searchParams);
15
18
 
16
- const rawData = await appFetch<string>(
17
- `${category.list}${params}`,
18
- {
19
+ const rawData = await appFetch<string>({
20
+ url: `${category.list}${params}`,
21
+ locale,
22
+ currency,
23
+ init: {
19
24
  headers: {
20
25
  Accept: 'application/json',
21
26
  'Content-Type': 'application/json',
22
27
  ...(headers ?? {})
23
28
  }
24
29
  },
25
- FetchResponseType.TEXT
26
- );
30
+ responseType: FetchResponseType.TEXT
31
+ });
27
32
 
28
33
  let data: GetCategoryResponse;
29
34
 
@@ -51,15 +56,20 @@ const getListDataHandler = (
51
56
  };
52
57
 
53
58
  export const getListData = async ({
59
+ locale = ServerVariables.locale,
60
+ currency = ServerVariables.currency,
54
61
  searchParams,
55
62
  headers
56
63
  }: {
57
- searchParams: { [key: string]: string | string[] | undefined };
64
+ locale?: string;
65
+ currency?: string;
66
+ searchParams: URLSearchParams;
58
67
  headers?: Record<string, string>;
59
68
  }) => {
60
69
  return Cache.wrap(
61
70
  CacheKey.List(searchParams, headers),
62
- getListDataHandler(searchParams, headers),
71
+ locale,
72
+ getListDataHandler(locale, currency, searchParams, headers),
63
73
  {
64
74
  expire: 300
65
75
  }
@@ -1,6 +1,7 @@
1
1
  import { Cache, CacheKey } from '../../lib/cache';
2
2
  import { MenuItemType } from '../../types';
3
3
  import appFetch from '../../utils/app-fetch';
4
+ import { ServerVariables } from '../../utils/server-variables';
4
5
  import { misc } from '../urls';
5
6
 
6
7
  interface MenuResponse {
@@ -8,6 +9,8 @@ interface MenuResponse {
8
9
  }
9
10
 
10
11
  interface MenuHandlerParams {
12
+ locale?: string;
13
+ currency?: string;
11
14
  depth?: number;
12
15
  parent?: string;
13
16
  }
@@ -15,9 +18,18 @@ interface MenuHandlerParams {
15
18
  const DEFAULT_DEPTH = 3;
16
19
 
17
20
  const getMenuHandler =
18
- ({ depth, parent }: MenuHandlerParams = { depth: DEFAULT_DEPTH }) =>
21
+ ({
22
+ locale = ServerVariables.locale,
23
+ currency = ServerVariables.currency,
24
+ depth,
25
+ parent
26
+ }: MenuHandlerParams = {}) =>
19
27
  async () => {
20
- const response = await appFetch<MenuResponse>(misc.menus(depth, parent));
28
+ const response = await appFetch<MenuResponse>({
29
+ url: misc.menus(depth ?? DEFAULT_DEPTH, parent),
30
+ locale,
31
+ currency
32
+ });
21
33
 
22
34
  return response?.menu;
23
35
  };
@@ -30,6 +42,7 @@ const getMenuHandler =
30
42
  export const getMenu = async (params?: MenuHandlerParams) => {
31
43
  return Cache.wrap(
32
44
  CacheKey.Menu(params?.depth ?? DEFAULT_DEPTH, params?.parent),
45
+ params?.locale ?? ServerVariables.locale,
33
46
  getMenuHandler(params)
34
47
  );
35
48
  };
@@ -2,16 +2,21 @@ import { Cache, CacheKey } from '../../lib/cache';
2
2
  import { product } from '../urls';
3
3
  import { ProductCategoryResult, ProductResult } from '../../types';
4
4
  import appFetch from '../../utils/app-fetch';
5
+ import { ServerVariables } from '../../utils/server-variables';
5
6
  import logger from '../../utils/log';
6
7
 
7
8
  type GetProduct = {
8
9
  pk: number;
9
- searchParams?: { [key: string]: string | string[] | undefined };
10
+ locale?: string;
11
+ currency?: string;
12
+ searchParams?: URLSearchParams;
10
13
  groupProduct?: boolean;
11
14
  };
12
15
 
13
16
  const getProductDataHandler = ({
14
17
  pk,
18
+ locale,
19
+ currency,
15
20
  searchParams,
16
21
  groupProduct
17
22
  }: GetProduct) => {
@@ -28,24 +33,31 @@ const getProductDataHandler = ({
28
33
  .join('&');
29
34
  }
30
35
 
31
- const data = await appFetch<ProductResult>(url, {
32
- headers: {
33
- Accept: 'application/json',
34
- 'Content-Type': 'application/json'
36
+ const data = await appFetch<ProductResult>({
37
+ url,
38
+ locale,
39
+ currency,
40
+ init: {
41
+ headers: {
42
+ Accept: 'application/json',
43
+ 'Content-Type': 'application/json'
44
+ }
35
45
  }
36
46
  });
37
47
 
38
48
  const categoryUrl = product.categoryUrl(data.product.pk);
39
49
 
40
- const productCategoryData = await appFetch<ProductCategoryResult>(
41
- categoryUrl,
42
- {
50
+ const productCategoryData = await appFetch<ProductCategoryResult>({
51
+ url: categoryUrl,
52
+ locale,
53
+ currency,
54
+ init: {
43
55
  headers: {
44
56
  Accept: 'application/json',
45
57
  'Content-Type': 'application/json'
46
58
  }
47
59
  }
48
- );
60
+ });
49
61
 
50
62
  const menuItemModel = productCategoryData?.results[0]?.menuitemmodel;
51
63
 
@@ -59,10 +71,15 @@ const getProductDataHandler = ({
59
71
 
60
72
  const breadcrumbUrl = product.breadcrumbUrl(menuItemModel);
61
73
 
62
- const breadcrumbData = await appFetch<any>(breadcrumbUrl, {
63
- headers: {
64
- Accept: 'application/json',
65
- 'Content-Type': 'application/json'
74
+ const breadcrumbData = await appFetch<any>({
75
+ url: breadcrumbUrl,
76
+ locale,
77
+ currency,
78
+ init: {
79
+ headers: {
80
+ Accept: 'application/json',
81
+ 'Content-Type': 'application/json'
82
+ }
66
83
  }
67
84
  });
68
85
 
@@ -75,12 +92,18 @@ const getProductDataHandler = ({
75
92
 
76
93
  export const getProductData = async ({
77
94
  pk,
95
+ locale = ServerVariables.locale,
96
+ currency = ServerVariables.currency,
78
97
  searchParams,
79
98
  groupProduct
80
99
  }: GetProduct) => {
81
100
  return Cache.wrap(
82
- CacheKey[groupProduct ? 'GroupProduct' : 'Product'](pk, searchParams ?? {}),
83
- getProductDataHandler({ pk, searchParams, groupProduct }),
101
+ CacheKey[groupProduct ? 'GroupProduct' : 'Product'](
102
+ pk,
103
+ searchParams ?? new URLSearchParams()
104
+ ),
105
+ locale,
106
+ getProductDataHandler({ pk, locale, currency, searchParams, groupProduct }),
84
107
  {
85
108
  expire: 300
86
109
  }
@@ -1,23 +1,15 @@
1
1
  import appFetch from '../../utils/app-fetch';
2
2
  import { Cache, CacheKey } from '../../lib/cache';
3
3
  import { misc } from '../../data/urls';
4
- import logger from '../../utils/log';
4
+ import { ServerVariables } from '../../utils/server-variables';
5
5
 
6
- function getRootSeoDataHandler() {
7
- return async function () {
8
- let data = {};
9
-
10
- try {
11
- data = await appFetch<{ [key: string]: string }>(misc.cmsSeo('/'));
12
- } catch (error) {
13
- logger.error('Error while fetching root seo data', error);
14
- }
15
-
16
- return data;
17
- };
6
+ interface SeoDataParams {
7
+ url: string;
8
+ locale?: string;
9
+ currency?: string;
18
10
  }
19
11
 
20
- function getSeoDataHandler(url: string) {
12
+ function getSeoDataHandler({ url, locale, currency }: SeoDataParams) {
21
13
  return async function () {
22
14
  let data = {} as {
23
15
  title: string;
@@ -27,7 +19,7 @@ function getSeoDataHandler(url: string) {
27
19
  };
28
20
 
29
21
  try {
30
- data = await appFetch(misc.cmsSeo(url));
22
+ data = await appFetch({ url: misc.cmsSeo(url), locale, currency });
31
23
  } catch (error) {
32
24
  // logger.error('Error while fetching seo data', { url, error });
33
25
  }
@@ -36,13 +28,14 @@ function getSeoDataHandler(url: string) {
36
28
  };
37
29
  }
38
30
 
39
- /**
40
- * @deprecated Use getSeoData instead
41
- */
42
- export const getRootSeo = async () => {
43
- return Cache.wrap(CacheKey.RootSeo, getRootSeoDataHandler());
44
- };
45
-
46
- export const getSeoData = async (url: string) => {
47
- return Cache.wrap(CacheKey.Seo(url), getSeoDataHandler(url));
31
+ export const getSeoData = async (
32
+ url,
33
+ locale = ServerVariables.locale,
34
+ currency = ServerVariables.currency
35
+ ) => {
36
+ return Cache.wrap(
37
+ CacheKey.Seo(url),
38
+ locale,
39
+ getSeoDataHandler({ url, locale, currency })
40
+ );
48
41
  };
@@ -4,25 +4,30 @@ import { GetCategoryResponse } from '../../types';
4
4
  import { generateCommerceSearchParams } from '../../utils';
5
5
  import appFetch from '../../utils/app-fetch';
6
6
  import header from '../../redux/reducers/header';
7
+ import { ServerVariables } from '../../utils/server-variables';
7
8
 
8
9
  const getSpecialPageDataHandler = (
9
10
  pk: number,
10
- searchParams: { [key: string]: string | string[] | undefined },
11
+ locale: string,
12
+ currency: string,
13
+ searchParams: URLSearchParams,
11
14
  headers?: Record<string, string>
12
15
  ) => {
13
16
  return async function () {
14
17
  const params = generateCommerceSearchParams(searchParams);
15
18
 
16
- const data: GetCategoryResponse = await appFetch(
17
- `${category.getSpecialPageByPk(pk)}${params}`,
18
- {
19
+ const data: GetCategoryResponse = await appFetch({
20
+ url: `${category.getSpecialPageByPk(pk)}${params}`,
21
+ locale,
22
+ currency,
23
+ init: {
19
24
  headers: {
20
25
  Accept: 'application/json',
21
26
  'Content-Type': 'application/json',
22
27
  ...(headers ?? {})
23
28
  }
24
29
  }
25
- );
30
+ });
26
31
 
27
32
  return data;
28
33
  };
@@ -30,16 +35,21 @@ const getSpecialPageDataHandler = (
30
35
 
31
36
  export const getSpecialPageData = async ({
32
37
  pk,
38
+ locale = ServerVariables.locale,
39
+ currency = ServerVariables.currency,
33
40
  searchParams,
34
41
  headers
35
42
  }: {
36
43
  pk: number;
37
- searchParams: { [key: string]: string | string[] | undefined };
44
+ locale?: string;
45
+ currency?: string;
46
+ searchParams: URLSearchParams;
38
47
  headers?: Record<string, string>;
39
48
  }) => {
40
49
  return Cache.wrap(
41
50
  CacheKey.SpecialPage(pk, searchParams, headers),
42
- getSpecialPageDataHandler(pk, searchParams, headers),
51
+ locale,
52
+ getSpecialPageDataHandler(pk, locale, currency, searchParams, headers),
43
53
  {
44
54
  expire: 300
45
55
  }
@@ -3,25 +3,32 @@ import 'server-only';
3
3
  import { CacheOptions, WidgetResultType } from '../../types';
4
4
  import appFetch from '../../utils/app-fetch';
5
5
  import { widgets } from '../urls';
6
+ import { ServerVariables } from '../../utils/server-variables';
6
7
 
7
- const getWidgetDataHandler = (slug: string) => async () => {
8
- if (!slug) {
9
- return null;
10
- }
8
+ const getWidgetDataHandler =
9
+ (slug: string, locale: string, currency: string) => async () => {
10
+ if (!slug) {
11
+ return null;
12
+ }
11
13
 
12
- return await appFetch(widgets.getWidget(slug));
13
- };
14
+ return await appFetch({ url: widgets.getWidget(slug), locale, currency });
15
+ };
14
16
 
15
17
  export const getWidgetData = async <T>({
16
18
  slug,
19
+ locale = ServerVariables.locale,
20
+ currency = ServerVariables.currency,
17
21
  cacheOptions
18
22
  }: {
19
23
  slug: string;
24
+ locale?: string;
25
+ currency?: string;
20
26
  cacheOptions?: CacheOptions;
21
27
  }): Promise<WidgetResultType<T>> => {
22
28
  return Cache.wrap(
23
29
  CacheKey.Widget(slug),
24
- getWidgetDataHandler(slug),
30
+ locale,
31
+ getWidgetDataHandler(slug, locale, currency),
25
32
  cacheOptions
26
33
  );
27
34
  };
@@ -2,7 +2,6 @@ import settings from 'settings';
2
2
  import { LayoutProps, PageProps, RootLayoutProps } from '../../types';
3
3
  import { redirect } from 'next/navigation';
4
4
  import { ServerVariables } from '../../utils/server-variables';
5
- import { getTranslations } from '../../utils/server-translation';
6
5
  import { ROUTES } from 'routes';
7
6
  import logger from '../../utils/log';
8
7
 
@@ -50,7 +49,11 @@ const addRootLayoutProps = async (componentProps: RootLayoutProps) => {
50
49
  return redirect(ROUTES.HOME);
51
50
  }
52
51
 
52
+ const { getTranslations } = settings.useOptimizedTranslations
53
+ ? require('translations')
54
+ : require('../../utils/server-translation');
53
55
  const translations = await getTranslations(params.locale);
56
+
54
57
  componentProps.translations = translations;
55
58
 
56
59
  const locale = settings.localization.locales.find(
@@ -116,7 +116,7 @@ export default function usePagination(
116
116
  urlSearchParams.set('page', (Number(state.page) - 1).toString());
117
117
  return `${pathname}?${urlSearchParams.toString()}`;
118
118
  }
119
- return '#';
119
+ return null;
120
120
  }, [state.page, pathname, urlSearchParams]);
121
121
 
122
122
  const next = useMemo(() => {
@@ -124,7 +124,7 @@ export default function usePagination(
124
124
  urlSearchParams.set('page', (Number(state.page) + 1).toString());
125
125
  return `${pathname}?${urlSearchParams.toString()}`;
126
126
  }
127
- return '#';
127
+ return null;
128
128
  }, [state.page, state.last, pathname, urlSearchParams]);
129
129
 
130
130
  return {
package/lib/cache.ts CHANGED
@@ -3,7 +3,6 @@ import { RedisClientType } from 'redis';
3
3
  import Settings from 'settings';
4
4
  import { CacheOptions } from '../types';
5
5
  import logger from '../utils/log';
6
- import { ServerVariables } from '../utils/server-variables';
7
6
 
8
7
  const hashCacheKey = (object?: Record<string, string>) => {
9
8
  if (!object) {
@@ -20,16 +19,13 @@ const hashCacheKey = (object?: Record<string, string>) => {
20
19
  return `_${encodeURIComponent(cacheKey)}`;
21
20
  };
22
21
  export const CacheKey = {
23
- List: (
24
- searchParams: { [key: string]: string | string[] | undefined },
25
- headers?: Record<string, string>
26
- ) =>
22
+ List: (searchParams: URLSearchParams, headers?: Record<string, string>) =>
27
23
  `list_${encodeURIComponent(JSON.stringify(searchParams))}${hashCacheKey(
28
24
  headers
29
25
  )}`,
30
26
  Category: (
31
27
  pk: number,
32
- searchParams?: { [key: string]: string | string[] | undefined },
28
+ searchParams?: URLSearchParams,
33
29
  headers?: Record<string, string>
34
30
  ) =>
35
31
  `category_${pk}_${encodeURIComponent(
@@ -38,20 +34,15 @@ export const CacheKey = {
38
34
  CategorySlug: (slug: string) => `category_${slug}`,
39
35
  SpecialPage: (
40
36
  pk: number,
41
- searchParams: { [key: string]: string | string[] | undefined },
37
+ searchParams: URLSearchParams,
42
38
  headers?: Record<string, string>
43
39
  ) =>
44
40
  `special_page_${pk}_${encodeURIComponent(
45
41
  JSON.stringify(searchParams)
46
42
  )}${hashCacheKey(headers)}`,
47
- Product: (
48
- pk: number,
49
- searchParams: { [key: string]: string | string[] | undefined }
50
- ) => `product_${pk}_${encodeURIComponent(JSON.stringify(searchParams))}`,
51
- GroupProduct: (
52
- pk: number,
53
- searchParams: { [key: string]: string | string[] | undefined }
54
- ) =>
43
+ Product: (pk: number, searchParams: URLSearchParams) =>
44
+ `product_${pk}_${encodeURIComponent(JSON.stringify(searchParams))}`,
45
+ GroupProduct: (pk: number, searchParams: URLSearchParams) =>
55
46
  `group_product_${pk}_${encodeURIComponent(JSON.stringify(searchParams))}`,
56
47
  FlatPage: (pk: number) => `flat_page_${pk}`,
57
48
  LandingPage: (pk: number) => `landing_page_${pk}`,
@@ -67,10 +58,8 @@ export const CacheKey = {
67
58
  export class Cache {
68
59
  static PROXY_URL = `${process.env.NEXT_PUBLIC_URL}/api/cache`;
69
60
 
70
- static formatKey(key: string) {
71
- return encodeURIComponent(
72
- `${Settings.commerceUrl}_${ServerVariables.locale}_${key}`
73
- );
61
+ static formatKey(key: string, locale: string) {
62
+ return encodeURIComponent(`${Settings.commerceUrl}_${locale}_${key}`);
74
63
  }
75
64
 
76
65
  static clientPool: Pool<RedisClientType> = createPool(
@@ -163,6 +152,7 @@ export class Cache {
163
152
 
164
153
  static async wrap<T = any>(
165
154
  key: string,
155
+ locale: string,
166
156
  handler: () => Promise<T>,
167
157
  options?: CacheOptions
168
158
  ): Promise<T> {
@@ -186,7 +176,7 @@ export class Cache {
186
176
  };
187
177
 
188
178
  const _options = Object.assign(defaultOptions, options);
189
- const formattedKey = Cache.formatKey(key);
179
+ const formattedKey = Cache.formatKey(key, locale);
190
180
 
191
181
  logger.debug('Cache wrap', { key, formattedKey, _options });
192
182
 
@@ -43,9 +43,14 @@ const resolvePrettyUrlHandler =
43
43
  return prettyUrlResult;
44
44
  };
45
45
 
46
- const resolvePrettyUrl = async (pathname: string, ip: string | null) => {
46
+ const resolvePrettyUrl = async (
47
+ pathname: string,
48
+ locale: string,
49
+ ip: string | null
50
+ ) => {
47
51
  return Cache.wrap(
48
52
  CacheKey.PrettyUrl(pathname),
53
+ locale,
49
54
  resolvePrettyUrlHandler(pathname, ip),
50
55
  {
51
56
  useProxy: true
@@ -88,6 +93,7 @@ const withPrettyUrl =
88
93
  )
89
94
  ? url.pathname
90
95
  : prettyUrlPathname,
96
+ matchedLanguagePrefix,
91
97
  ip
92
98
  );
93
99
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@akinon/next",
3
3
  "description": "Core package for Project Zero Next",
4
- "version": "1.48.0-rc.0",
4
+ "version": "1.48.0-rc.2",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -30,7 +30,7 @@
30
30
  "set-cookie-parser": "2.6.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@akinon/eslint-plugin-projectzero": "1.48.0-rc.0",
33
+ "@akinon/eslint-plugin-projectzero": "1.48.0-rc.2",
34
34
  "@types/react-redux": "7.1.30",
35
35
  "@types/set-cookie-parser": "2.4.7",
36
36
  "@typescript-eslint/eslint-plugin": "6.7.4",
@@ -63,14 +63,12 @@ export async function generateMetadata({ params }: PageProps) {
63
63
  .filter((x) => !x.startsWith('searchparams'))
64
64
  .join('/');
65
65
 
66
- const searchParams = Object.fromEntries(
67
- new URLSearchParams(
68
- decodeURIComponent(
69
- prettyurl
70
- .find((x) => x.startsWith('searchparams'))
71
- ?.replace('searchparams%7C', '')
72
- ) ?? {}
73
- ).entries()
66
+ const searchParams = new URLSearchParams(
67
+ decodeURIComponent(
68
+ prettyurl
69
+ .find((x) => x.startsWith('searchparams'))
70
+ ?.replace('searchparams%7C', '')
71
+ ) ?? {}
74
72
  );
75
73
 
76
74
  const prettyUrlResult = await resolvePrettyUrlHandler(pageSlug, null)();
@@ -162,7 +160,7 @@ export default async function Page({ params }) {
162
160
  ...params,
163
161
  pk: result.pk
164
162
  },
165
- searchParams
163
+ searchParams: new URLSearchParams(searchParams)
166
164
  };
167
165
 
168
166
  if (result.path.startsWith('/category/')) {
package/types/index.ts CHANGED
@@ -191,6 +191,7 @@ export interface Settings {
191
191
  masterpassJsUrl?: string;
192
192
  };
193
193
  customNotFoundEnabled: boolean;
194
+ useOptimizedTranslations?: boolean;
194
195
  plugins?: Record<string, Record<string, any>>;
195
196
  includedProxyHeaders?: string[];
196
197
  }
@@ -224,8 +225,8 @@ export type ImageOptions = CDNOptions & {
224
225
  export type Translations = { [key: string]: object };
225
226
 
226
227
  export interface PageProps<T = any> {
227
- params: T;
228
- searchParams: { [key: string]: string | string[] | undefined };
228
+ params: T & { locale: string; currency: string };
229
+ searchParams: URLSearchParams;
229
230
  }
230
231
 
231
232
  export interface LayoutProps<T = any> extends PageProps<T> {
@@ -233,7 +234,11 @@ export interface LayoutProps<T = any> extends PageProps<T> {
233
234
  }
234
235
 
235
236
  export interface RootLayoutProps<
236
- T = { commerce: string; locale: string; currency: string }
237
+ T = {
238
+ commerce: string;
239
+ locale: string;
240
+ currency: string;
241
+ }
237
242
  > extends LayoutProps<T> {
238
243
  translations: Translations;
239
244
  locale: Locale & {
@@ -1,18 +1,26 @@
1
1
  import Settings from 'settings';
2
- import { ServerVariables } from './server-variables';
3
2
  import logger from '../utils/log';
4
3
  import { headers, cookies } from 'next/headers';
4
+ import { ServerVariables } from './server-variables';
5
5
 
6
6
  export enum FetchResponseType {
7
7
  JSON = 'json',
8
8
  TEXT = 'text'
9
9
  }
10
10
 
11
- const appFetch = async <T>(
12
- url: RequestInfo,
13
- init: RequestInit = {},
11
+ const appFetch = async <T>({
12
+ url,
13
+ locale,
14
+ currency,
15
+ init = {},
14
16
  responseType = FetchResponseType.JSON
15
- ): Promise<T> => {
17
+ }: {
18
+ url: RequestInfo;
19
+ locale: string;
20
+ currency: string;
21
+ init?: RequestInit;
22
+ responseType?: FetchResponseType;
23
+ }): Promise<T> => {
16
24
  let response: T;
17
25
  let status: number;
18
26
  let ip = '';
@@ -24,7 +32,7 @@ const appFetch = async <T>(
24
32
 
25
33
  const commerceUrl = Settings.commerceUrl;
26
34
  const currentLocale = Settings.localization.locales.find(
27
- (locale) => locale.value === ServerVariables.locale
35
+ (l) => l.value === locale
28
36
  );
29
37
 
30
38
  if (commerceUrl === 'default') {
@@ -38,7 +46,7 @@ const appFetch = async <T>(
38
46
  ...(init.headers ?? {}),
39
47
  ...(ServerVariables.globalHeaders ?? {}),
40
48
  'Accept-Language': currentLocale.apiValue,
41
- 'x-currency': ServerVariables.currency,
49
+ 'x-currency': currency,
42
50
  'x-forwarded-for': ip,
43
51
  cookie: nextCookies.toString()
44
52
  };
@@ -1,15 +1,13 @@
1
1
  import logger from './log';
2
2
 
3
- export const generateCommerceSearchParams = (searchParams?: {
4
- [key: string]: string | string[] | undefined;
5
- }) => {
3
+ export const generateCommerceSearchParams = (
4
+ searchParams?: URLSearchParams
5
+ ) => {
6
6
  if (!searchParams) {
7
7
  return null;
8
8
  }
9
9
 
10
- const urlSerchParams = new URLSearchParams(
11
- searchParams as Record<string, string>
12
- );
10
+ const urlSerchParams = new URLSearchParams(searchParams);
13
11
 
14
12
  Object.entries(searchParams).forEach(([key, value]) => {
15
13
  if (typeof value === 'object') {
@@ -5,7 +5,6 @@ import { getTranslateFn } from '../utils';
5
5
  import { Translations } from '../types';
6
6
  import settings from 'settings';
7
7
  import logger from './log';
8
- import { unstable_cache } from 'next/cache';
9
8
 
10
9
  export const translations: Translations = {};
11
10
 
@@ -52,10 +51,17 @@ export async function getTranslations(locale_: string) {
52
51
  return translations;
53
52
  }
54
53
 
55
- export const getCachedTranslations = unstable_cache(async (locale: string) =>
56
- getTranslations(locale)
57
- );
58
-
59
54
  export function t(path: string) {
60
55
  return getTranslateFn(path, translations);
61
56
  }
57
+
58
+ export async function t_(path: string, locale?: string) {
59
+ let translations_ = translations;
60
+
61
+ if (settings.useOptimizedTranslations && locale) {
62
+ const { getTranslations } = require('translations');
63
+ translations_ = await getTranslations(locale);
64
+ }
65
+
66
+ return getTranslateFn(path, translations_);
67
+ }
package/with-pz-config.js CHANGED
@@ -57,7 +57,8 @@ const defaultConfig = {
57
57
  ...pzPlugins.reduce((acc, plugin) => {
58
58
  acc[`@akinon/${plugin}`] = false;
59
59
  return acc;
60
- }, {})
60
+ }, {}),
61
+ translations: false
61
62
  };
62
63
  return config;
63
64
  },