@akinon/projectzero 2.0.0-beta.11 → 2.0.0-beta.13
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 +104 -21
- package/app-template/.env.example +1 -0
- package/app-template/.github/instructions/account.instructions.md +749 -0
- package/app-template/.github/instructions/checkout.instructions.md +678 -0
- package/app-template/.github/instructions/default.instructions.md +279 -0
- package/app-template/.github/instructions/edge-cases.instructions.md +73 -0
- package/app-template/.github/instructions/routing.instructions.md +603 -0
- package/app-template/.github/instructions/settings.instructions.md +338 -0
- package/app-template/.gitignore +3 -0
- package/app-template/AGENTS.md +7 -0
- package/app-template/CHANGELOG.md +1348 -284
- package/app-template/Procfile +1 -1
- package/app-template/akinon.json +0 -3
- package/app-template/build.sh +10 -0
- package/app-template/docs/advanced-usage.md +101 -0
- package/app-template/docs/sentry-usage.md +35 -0
- package/app-template/next-env.d.ts +1 -0
- package/app-template/{next.config.ts → next.config.mjs} +6 -6
- package/app-template/package.json +58 -51
- package/app-template/postcss.config.mjs +1 -4
- package/app-template/public/locales/en/checkout.json +6 -0
- package/app-template/public/locales/en/common.json +50 -1
- package/app-template/public/locales/en/product.json +62 -1
- package/app-template/public/locales/tr/checkout.json +6 -0
- package/app-template/public/locales/tr/common.json +50 -1
- package/app-template/public/locales/tr/product.json +63 -0
- package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +9 -9
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +6 -6
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +6 -6
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +1 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +1 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +2 -2
- package/app-template/src/app/[pz]/category/[pk]/page.tsx +27 -0
- package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +2 -3
- package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +3 -10
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/not-found.tsx +5 -7
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
- package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
- package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +6 -12
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/[node]/route.ts +2 -2
- package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
- package/app-template/src/app/api/form/[...id]/route.ts +1 -7
- package/app-template/src/app/api/image-proxy/route.ts +1 -0
- package/app-template/src/app/api/product-categories/route.ts +1 -0
- package/app-template/src/app/api/similar-product-list/route.ts +1 -0
- package/app-template/src/app/api/similar-products/route.ts +1 -0
- package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
- package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
- package/app-template/src/assets/globals.scss +4 -133
- package/app-template/src/auth.ts +3 -0
- package/app-template/src/components/__tests__/badge.test.tsx +2 -2
- package/app-template/src/components/__tests__/link.test.tsx +2 -0
- package/app-template/src/components/accordion.tsx +23 -20
- package/app-template/src/components/button.tsx +1 -1
- package/app-template/src/components/carousel-core.tsx +4 -11
- package/app-template/src/components/checkbox.tsx +1 -1
- package/app-template/src/components/currency-select.tsx +1 -0
- package/app-template/src/components/file-input.tsx +27 -7
- package/app-template/src/components/generate-form-fields.tsx +49 -10
- package/app-template/src/components/input.tsx +11 -5
- package/app-template/src/components/modal.tsx +32 -16
- package/app-template/src/components/pagination.tsx +1 -0
- package/app-template/src/components/price.tsx +1 -1
- package/app-template/src/components/pwa-tags.tsx +1 -0
- package/app-template/src/components/select.tsx +39 -27
- package/app-template/src/components/shimmer.tsx +1 -1
- package/app-template/src/components/types/index.ts +25 -1
- package/app-template/src/hooks/use-fav-button.tsx +4 -8
- package/app-template/src/hooks/use-product-cart.ts +77 -0
- package/app-template/src/hooks/use-stock-alert.ts +74 -0
- package/app-template/src/plugins.js +12 -2
- package/app-template/src/redux/middlewares/category.ts +5 -4
- package/app-template/src/redux/store.ts +21 -1
- package/app-template/src/routes/index.ts +2 -1
- package/app-template/src/settings.js +3 -1
- package/app-template/src/types/index.ts +74 -3
- package/app-template/src/types/next-auth.d.ts +2 -2
- package/app-template/src/utils/variant-validation.ts +41 -0
- package/app-template/src/views/account/address-form.tsx +8 -4
- package/app-template/src/views/account/contact-form.tsx +2 -2
- package/app-template/src/views/account/content-header.tsx +4 -3
- package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
- package/app-template/src/views/account/order.tsx +1 -1
- package/app-template/src/views/account/orders/order-cancellation-item.tsx +1 -1
- package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +1 -1
- package/app-template/src/views/basket/basket-item.tsx +6 -1
- package/app-template/src/views/basket/summary.tsx +16 -0
- package/app-template/src/views/breadcrumb.tsx +2 -2
- package/app-template/src/views/category/category-info.tsx +2 -1
- package/app-template/src/views/category/filters/index.tsx +1 -1
- package/app-template/src/views/checkout/auth.tsx +1 -1
- package/app-template/src/views/checkout/layout/header.tsx +1 -1
- package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -1
- package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +121 -0
- package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +4 -4
- package/app-template/src/views/checkout/steps/shipping/address-box.tsx +3 -3
- package/app-template/src/views/checkout/steps/shipping/addresses.tsx +1 -1
- package/app-template/src/views/checkout/summary.tsx +12 -2
- package/app-template/src/views/find-in-store/index.tsx +2 -2
- package/app-template/src/views/header/action-menu.tsx +2 -6
- package/app-template/src/views/header/band.tsx +2 -2
- package/app-template/src/views/header/index.tsx +1 -1
- package/app-template/src/views/header/mini-basket.tsx +2 -2
- package/app-template/src/views/header/mobile-menu.tsx +6 -6
- package/app-template/src/views/header/navbar.tsx +1 -1
- package/app-template/src/views/header/pwa-back-button.tsx +1 -1
- package/app-template/src/views/header/search/index.tsx +13 -3
- package/app-template/src/views/header/search/results.tsx +1 -1
- package/app-template/src/views/header/user-menu.tsx +1 -3
- package/app-template/src/views/login/index.tsx +14 -13
- package/app-template/src/views/otp-login/index.tsx +11 -6
- package/app-template/src/views/product/layout.tsx +15 -1
- package/app-template/src/views/product/product-actions.tsx +165 -0
- package/app-template/src/views/product/product-info.tsx +69 -261
- package/app-template/src/views/product/product-share.tsx +56 -0
- package/app-template/src/views/product/product-variants.tsx +26 -0
- package/app-template/src/views/product/slider.tsx +22 -1
- package/app-template/src/views/product-pointer-banner-item.tsx +1 -1
- package/app-template/src/views/register/index.tsx +17 -21
- package/app-template/src/views/sales-contract-modal/index.tsx +17 -17
- package/app-template/src/widgets/footer-info.tsx +1 -1
- package/app-template/src/widgets/footer-menu.tsx +7 -3
- package/app-template/src/widgets/footer-subscription/index.tsx +1 -1
- package/app-template/src/widgets/home-stories-eng.tsx +43 -35
- package/app-template/tailwind.config.js +129 -1
- package/app-template/tsconfig.json +29 -11
- package/codemods/migrate-segments/index.js +591 -0
- package/commands/plugins.ts +62 -14
- package/dist/commands/plugins.js +62 -14
- package/package.json +1 -1
- package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
- package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
- package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
- package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
- package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
- package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/error.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
package/app-template/Procfile
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
web:
|
|
1
|
+
web: PORT=8008 HOSTNAME=0.0.0.0 node .next/standalone/server.js
|
package/app-template/akinon.json
CHANGED
package/app-template/build.sh
CHANGED
|
@@ -41,3 +41,104 @@ const middleware: NextMiddleware = (
|
|
|
41
41
|
return NextResponse.next();
|
|
42
42
|
};
|
|
43
43
|
```
|
|
44
|
+
|
|
45
|
+
## Custom Segments
|
|
46
|
+
|
|
47
|
+
The `[pz]` segment encodes `locale`, `currency`, and `url` by default. You can add custom segments via `pzSegments` in `settings.js` to encode additional values into the URL.
|
|
48
|
+
|
|
49
|
+
### Configuration
|
|
50
|
+
|
|
51
|
+
Define custom segments in `settings.js` with a `resolve` function that computes the segment value at request time:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
/** @type {import('@akinon/next/types').Settings} */
|
|
55
|
+
module.exports = {
|
|
56
|
+
// ...
|
|
57
|
+
usePzSegment: true,
|
|
58
|
+
pzSegments: {
|
|
59
|
+
segments: [
|
|
60
|
+
{
|
|
61
|
+
name: 'segment',
|
|
62
|
+
resolve: (context) => context.req.cookies.get('pz-segment')?.value ?? 'default'
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Default segments (`locale`, `currency`, `url`) are always included automatically. You only need to define your custom ones.
|
|
70
|
+
|
|
71
|
+
### Resolve Context
|
|
72
|
+
|
|
73
|
+
The `resolve` function receives a context object with the following properties:
|
|
74
|
+
|
|
75
|
+
| Property | Type | Description |
|
|
76
|
+
|------------|------------------|--------------------------------------|
|
|
77
|
+
| `req` | `PzNextRequest` | The incoming request object (cookies, headers, middlewareParams) |
|
|
78
|
+
| `event` | `NextFetchEvent` | The Next.js fetch event (waitUntil, etc.) |
|
|
79
|
+
| `url` | `NextURL` | Cloned URL object of the current request |
|
|
80
|
+
| `locale` | `string` | Resolved locale value |
|
|
81
|
+
| `currency` | `string` | Resolved currency value |
|
|
82
|
+
| `pathname` | `string` | Pathname without locale prefix |
|
|
83
|
+
|
|
84
|
+
### Reading Segment Values
|
|
85
|
+
|
|
86
|
+
In server components, use `parsePzParams` to read all segment values (both built-in and custom):
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { parsePzParams } from '@akinon/next/utils'
|
|
90
|
+
import settings from 'settings'
|
|
91
|
+
|
|
92
|
+
export default function Page({ params }) {
|
|
93
|
+
const { locale, currency, url, segment } = parsePzParams(params, settings)
|
|
94
|
+
// ...
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
In client components, use the `usePzParams` hook:
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
'use client'
|
|
102
|
+
import { usePzParams } from '@akinon/next/hooks/use-pz-params'
|
|
103
|
+
|
|
104
|
+
export default function MyComponent() {
|
|
105
|
+
const { locale, currency, url, segment } = usePzParams()
|
|
106
|
+
// ...
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Example: Cookie-based Segment
|
|
111
|
+
|
|
112
|
+
A segment that reads a value from a cookie and falls back to a default:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
pzSegments: {
|
|
116
|
+
segments: [
|
|
117
|
+
{
|
|
118
|
+
name: 'segment',
|
|
119
|
+
resolve: (context) => context.req.cookies.get('pz-segment')?.value ?? 'default'
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This encodes the cookie value into the `[pz]` URL parameter. The resulting URL structure becomes:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
/tr--TL--<encoded-url>--default/page-path
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Migration from Legacy Structure
|
|
132
|
+
|
|
133
|
+
To migrate a project using the legacy `[commerce]/[locale]/[currency]` directory structure to the new `[pz]` segment:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx projectzero codemod --codemod=migrate-segments
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This codemod will:
|
|
140
|
+
- Detect all dynamic segments and merge them into `[pz]/`
|
|
141
|
+
- Update `settings.js` with `usePzSegment: true`
|
|
142
|
+
- Clean up middleware rewrite blocks
|
|
143
|
+
- Update path references in `tsconfig.json`, `next.config.js`, and source files
|
|
144
|
+
- Replace `params.locale` / `params.currency` / `params.url` usages with `parsePzParams`
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Sentry Usage
|
|
3
|
+
sidebar_label: Sentry Usage
|
|
4
|
+
slug: sentry-usage
|
|
5
|
+
custom_edit_url: null
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Sentry is a powerful tool for monitoring and debugging applications. In the context of the Project Zero Next application, it can be used to track errors, performance issues, and other important metrics. This document provides guidelines on how to effectively use Sentry for the Project Zero Next application.
|
|
9
|
+
|
|
10
|
+
## Filtering PZ Next Errors and Warnings
|
|
11
|
+
|
|
12
|
+
To filter out errors and warnings that are specific to the PZ Next application, you can use the following tag:
|
|
13
|
+
|
|
14
|
+
APP_TYPE = ProjectZeroNext
|
|
15
|
+
|
|
16
|
+
## Filtering Only Client-Side Errors
|
|
17
|
+
|
|
18
|
+
To filter out client-side errors, you can use the following tag:
|
|
19
|
+
|
|
20
|
+
TYPE = client
|
|
21
|
+
|
|
22
|
+
## Filtering Only Server-Side Errors
|
|
23
|
+
|
|
24
|
+
To filter out server-side errors, you can use the following tag:
|
|
25
|
+
|
|
26
|
+
TYPE = server
|
|
27
|
+
|
|
28
|
+
## Filtering Client-Side 500 Error Pages
|
|
29
|
+
|
|
30
|
+
To filter out 500 error pages caused by the client-side code, you can use the following tags:
|
|
31
|
+
|
|
32
|
+
TYPE = Client
|
|
33
|
+
LOG_TYPE = UNCAUGHT_ERROR_PAGE
|
|
34
|
+
|
|
35
|
+
You can use the **"Breadcrumbs"** feature in Sentry to track the navigation path that led to the error. This can help you understand how users arrived at the error page and what actions they took before encountering the issue.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
3
|
/// <reference types="next/navigation-types/compat/navigation" />
|
|
4
|
+
import "./.next/types/routes.d.ts";
|
|
4
5
|
|
|
5
6
|
// NOTE: This file should not be edited
|
|
6
7
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type { NextConfig } from 'next';
|
|
2
1
|
import withPWA from 'next-pwa';
|
|
3
2
|
import { withSentryConfig } from '@sentry/nextjs';
|
|
4
3
|
import withPzConfig from '@akinon/next/with-pz-config.js';
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
/** @type {import('next').NextConfig} */
|
|
6
|
+
const nextConfig = {
|
|
7
7
|
// Your Next.js config to override defaults
|
|
8
8
|
rewrites: async () => {
|
|
9
9
|
return [
|
|
10
10
|
{
|
|
11
|
-
source: '/:
|
|
12
|
-
destination: '/:
|
|
11
|
+
source: '/:pz/sitemap.xml',
|
|
12
|
+
destination: '/:pz/xml-sitemap'
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
source: '/:
|
|
16
|
-
destination: '/:
|
|
15
|
+
source: '/:pz/sitemap/:node',
|
|
16
|
+
destination: '/:pz/xml-sitemap/:node'
|
|
17
17
|
}
|
|
18
18
|
];
|
|
19
19
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projectzeronext",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.13",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"clean": "rm -rf node_modules && rm -rf .next",
|
|
8
|
-
"dev": "next dev",
|
|
9
|
-
"dev-ssl": "next dev --experimental-https",
|
|
10
|
-
"build": "next build",
|
|
8
|
+
"dev": "next dev --webpack",
|
|
9
|
+
"dev-ssl": "next dev --experimental-https --webpack",
|
|
10
|
+
"build": "next build --webpack",
|
|
11
11
|
"start": "next start -p 8008",
|
|
12
12
|
"type-check": "tsc",
|
|
13
13
|
"lint": "next lint",
|
|
@@ -24,74 +24,83 @@
|
|
|
24
24
|
"test:middleware": "jest middleware-matcher.test.ts --bail"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@akinon/next": "2.0.0-beta.
|
|
28
|
-
"@akinon/pz-akifast": "2.0.0-beta.
|
|
29
|
-
"@akinon/pz-
|
|
30
|
-
"@akinon/pz-
|
|
31
|
-
"@akinon/pz-
|
|
32
|
-
"@akinon/pz-
|
|
33
|
-
"@akinon/pz-
|
|
34
|
-
"@akinon/pz-
|
|
35
|
-
"@akinon/pz-
|
|
36
|
-
"@akinon/pz-
|
|
37
|
-
"@akinon/pz-
|
|
38
|
-
"@akinon/pz-
|
|
39
|
-
"@akinon/pz-
|
|
40
|
-
"@akinon/pz-
|
|
41
|
-
"@akinon/pz-
|
|
42
|
-
"@akinon/pz-
|
|
27
|
+
"@akinon/next": "2.0.0-beta.13",
|
|
28
|
+
"@akinon/pz-akifast": "2.0.0-beta.13",
|
|
29
|
+
"@akinon/pz-apple-pay": "2.0.0-beta.13",
|
|
30
|
+
"@akinon/pz-b2b": "2.0.0-beta.13",
|
|
31
|
+
"@akinon/pz-basket-gift-pack": "2.0.0-beta.13",
|
|
32
|
+
"@akinon/pz-bkm": "2.0.0-beta.13",
|
|
33
|
+
"@akinon/pz-checkout-gift-pack": "2.0.0-beta.13",
|
|
34
|
+
"@akinon/pz-click-collect": "2.0.0-beta.13",
|
|
35
|
+
"@akinon/pz-credit-payment": "2.0.0-beta.13",
|
|
36
|
+
"@akinon/pz-cybersource-uc": "2.0.0-beta.13",
|
|
37
|
+
"@akinon/pz-flow-payment": "2.0.0-beta.13",
|
|
38
|
+
"@akinon/pz-google-pay": "2.0.0-beta.13",
|
|
39
|
+
"@akinon/pz-gpay": "2.0.0-beta.13",
|
|
40
|
+
"@akinon/pz-haso": "2.0.0-beta.13",
|
|
41
|
+
"@akinon/pz-hepsipay": "2.0.0-beta.13",
|
|
42
|
+
"@akinon/pz-masterpass": "2.0.0-beta.13",
|
|
43
|
+
"@akinon/pz-masterpass-rest": "2.0.0-beta.13",
|
|
44
|
+
"@akinon/pz-multi-basket": "2.0.0-beta.13",
|
|
45
|
+
"@akinon/pz-one-click-checkout": "2.0.0-beta.13",
|
|
46
|
+
"@akinon/pz-otp": "2.0.0-beta.13",
|
|
47
|
+
"@akinon/pz-pay-on-delivery": "2.0.0-beta.13",
|
|
48
|
+
"@akinon/pz-saved-card": "2.0.0-beta.13",
|
|
49
|
+
"@akinon/pz-similar-products": "2.0.0-beta.13",
|
|
50
|
+
"@akinon/pz-tabby-extension": "2.0.0-beta.13",
|
|
51
|
+
"@akinon/pz-tamara-extension": "2.0.0-beta.13",
|
|
52
|
+
"@akinon/pz-virtual-try-on": "2.0.0-beta.13",
|
|
43
53
|
"@hookform/resolvers": "2.9.0",
|
|
44
|
-
"@next/third-parties": "
|
|
54
|
+
"@next/third-parties": "16.1.6",
|
|
45
55
|
"@react-google-maps/api": "2.17.1",
|
|
46
|
-
"@tailwindcss/postcss": "4.0.0",
|
|
47
56
|
"dayjs": "1.11.5",
|
|
48
57
|
"lossless-json": "2.0.5",
|
|
49
|
-
"next": "
|
|
50
|
-
"next-auth": "
|
|
58
|
+
"next": "16.1.6",
|
|
59
|
+
"next-auth": "5.0.0-beta.30",
|
|
51
60
|
"next-pwa": "5.6.0",
|
|
52
61
|
"pino": "8.11.0",
|
|
53
|
-
"postcss": "8.
|
|
54
|
-
"react": "19.
|
|
55
|
-
"react-dom": "19.
|
|
62
|
+
"postcss": "8.4.49",
|
|
63
|
+
"react": "19.2.4",
|
|
64
|
+
"react-dom": "19.2.4",
|
|
56
65
|
"react-google-recaptcha": "2.1.0",
|
|
57
|
-
"react-hook-form": "7.
|
|
66
|
+
"react-hook-form": "7.71.2",
|
|
58
67
|
"react-intersection-observer": "9.4.0",
|
|
59
68
|
"react-multi-carousel": "2.8.4",
|
|
60
69
|
"react-string-replace": "1.1.0",
|
|
61
70
|
"start-server-and-test": "2.0.3",
|
|
62
|
-
"tailwind-merge": "
|
|
71
|
+
"tailwind-merge": "1.8.0",
|
|
63
72
|
"yup": "0.32.11"
|
|
64
73
|
},
|
|
65
74
|
"devDependencies": {
|
|
66
|
-
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.
|
|
75
|
+
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.13",
|
|
67
76
|
"@semantic-release/changelog": "6.0.2",
|
|
68
77
|
"@semantic-release/exec": "6.0.3",
|
|
69
78
|
"@semantic-release/git": "10.0.1",
|
|
70
|
-
"@tailwindcss/
|
|
71
|
-
"@
|
|
79
|
+
"@tailwindcss/postcss": "4.2.0",
|
|
80
|
+
"@tailwindcss/typography": "0.5.19",
|
|
81
|
+
"@testing-library/dom": "10.4.0",
|
|
72
82
|
"@testing-library/jest-dom": "5.16.4",
|
|
73
|
-
"@testing-library/react": "
|
|
83
|
+
"@testing-library/react": "16.3.2",
|
|
74
84
|
"@testing-library/user-event": "14.1.1",
|
|
75
85
|
"@types/googlemaps": "3.43.3",
|
|
76
|
-
"@types/jest": "
|
|
77
|
-
"@types/react": "19.
|
|
78
|
-
"@types/react-dom": "19.
|
|
79
|
-
"@typescript-eslint/eslint-plugin": "
|
|
80
|
-
"@typescript-eslint/parser": "
|
|
81
|
-
"autoprefixer": "10.4.21",
|
|
86
|
+
"@types/jest": "29.5.14",
|
|
87
|
+
"@types/react": "19.2.14",
|
|
88
|
+
"@types/react-dom": "19.2.3",
|
|
89
|
+
"@typescript-eslint/eslint-plugin": "6.7.4",
|
|
90
|
+
"@typescript-eslint/parser": "6.7.4",
|
|
82
91
|
"client-only": "0.0.1",
|
|
83
92
|
"clsx": "1.1.1",
|
|
84
93
|
"currency-symbol-map": "5.1.0",
|
|
85
|
-
"eslint": "
|
|
86
|
-
"eslint-config-next": "
|
|
87
|
-
"eslint-config-prettier": "
|
|
94
|
+
"eslint": "8.14.0",
|
|
95
|
+
"eslint-config-next": "16.1.6",
|
|
96
|
+
"eslint-config-prettier": "8.5.0",
|
|
88
97
|
"husky": "8.0.0",
|
|
89
98
|
"jest": "29.7.0",
|
|
90
99
|
"jest-css-modules-transform": "4.3.0",
|
|
91
100
|
"jest-environment-jsdom": "29.7.0",
|
|
92
101
|
"lint-staged": "13.1.0",
|
|
93
|
-
"prettier": "
|
|
94
|
-
"react-number-format": "5.4
|
|
102
|
+
"prettier": "2.6.2",
|
|
103
|
+
"react-number-format": "5.3.4",
|
|
95
104
|
"sass": "1.49.9",
|
|
96
105
|
"semantic-release": "19.0.5",
|
|
97
106
|
"server-only": "0.0.1",
|
|
@@ -100,13 +109,11 @@
|
|
|
100
109
|
"stylelint-config-standard": "25.0.0",
|
|
101
110
|
"stylelint-scss": "4.2.0",
|
|
102
111
|
"stylelint-selector-bem-pattern": "2.1.1",
|
|
103
|
-
"tailwindcss": "4.
|
|
104
|
-
"ts-jest": "29.
|
|
112
|
+
"tailwindcss": "4.2.0",
|
|
113
|
+
"ts-jest": "29.2.6",
|
|
105
114
|
"ts-node": "10.7.0",
|
|
106
|
-
"typescript": "5.
|
|
115
|
+
"typescript": "5.9.3"
|
|
107
116
|
},
|
|
108
|
-
"resolutions": {
|
|
109
|
-
|
|
110
|
-
},
|
|
111
|
-
"packageManager": "yarn@1.22.22"
|
|
117
|
+
"resolutions": {},
|
|
118
|
+
"packageManager": "yarn@1.22.17"
|
|
112
119
|
}
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"subtotal": "Subtotal",
|
|
38
38
|
"shipping": "Shipping",
|
|
39
39
|
"discounts_total": "Discounts Total",
|
|
40
|
+
"loyalty_money_total": "Loyalty Money Total",
|
|
40
41
|
"total": "Total",
|
|
41
42
|
"delivery_info": "Delivery Info",
|
|
42
43
|
"change": "change",
|
|
@@ -138,6 +139,11 @@
|
|
|
138
139
|
"payments": "Payments",
|
|
139
140
|
"per_month": "Per Month",
|
|
140
141
|
"total": "Total"
|
|
142
|
+
},
|
|
143
|
+
"store_credit": {
|
|
144
|
+
"use_my_store_credits": "Use my pz-zero credits",
|
|
145
|
+
"available_balance": "Available Balance",
|
|
146
|
+
"insufficient_balance": "Your pz-zero credits are not sufficient to pay for the order, please select an additional payment method to cover the balance of <Amount/>"
|
|
141
147
|
}
|
|
142
148
|
},
|
|
143
149
|
"agreement": {
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
"navbar": {
|
|
18
18
|
"search": "SEARCH"
|
|
19
19
|
},
|
|
20
|
+
"good": "Good",
|
|
21
|
+
"bad": "Bad",
|
|
20
22
|
"mobile_menu": {
|
|
21
23
|
"back": "Back"
|
|
22
24
|
},
|
|
@@ -27,7 +29,25 @@
|
|
|
27
29
|
"clean": "clean",
|
|
28
30
|
"categories": "CATEGORIES",
|
|
29
31
|
"view_all": "VIEW ALL",
|
|
30
|
-
"not_found": "Search Results Not Found"
|
|
32
|
+
"not_found": "Search Results Not Found",
|
|
33
|
+
"image_search": {
|
|
34
|
+
"title": "Search by Image",
|
|
35
|
+
"upload_image": "Upload an image to find similar products",
|
|
36
|
+
"select_image": "Select Image",
|
|
37
|
+
"crop_image": "Crop Image",
|
|
38
|
+
"cancel_crop": "Cancel Crop",
|
|
39
|
+
"apply_crop": "Apply Crop",
|
|
40
|
+
"try_another": "Try Another Image",
|
|
41
|
+
"search_image": "Search Image",
|
|
42
|
+
"similar_products": "Similar Products",
|
|
43
|
+
"loading_cropper": "Loading cropper...",
|
|
44
|
+
"no_products": "No similar products found",
|
|
45
|
+
"best_results": "For best results:",
|
|
46
|
+
"tip_1": "Upload clear images of products",
|
|
47
|
+
"tip_2": "Use images with simple backgrounds",
|
|
48
|
+
"tip_3": "Focus on the main product",
|
|
49
|
+
"tip_4": "Use the crop tool to focus on specific details"
|
|
50
|
+
}
|
|
31
51
|
},
|
|
32
52
|
"page_404": {
|
|
33
53
|
"title": "Page not found.",
|
|
@@ -71,5 +91,34 @@
|
|
|
71
91
|
"file_input": {
|
|
72
92
|
"select_file": "Select File",
|
|
73
93
|
"no_file": "No file selected"
|
|
94
|
+
},
|
|
95
|
+
"product": {
|
|
96
|
+
"no_products": "No products found",
|
|
97
|
+
"new_image": "New Image",
|
|
98
|
+
"view_similar_styles": "View Similar Styles",
|
|
99
|
+
"clear_all_filters": "Clear All Filters",
|
|
100
|
+
"reset_to_original": "Reset to Original",
|
|
101
|
+
"similar_styles": "Similar Styles",
|
|
102
|
+
"filters": "Filters",
|
|
103
|
+
"active_filters": "Active Filters"
|
|
104
|
+
},
|
|
105
|
+
"similar_products": {
|
|
106
|
+
"errors": {
|
|
107
|
+
"file_size_too_large": "Image size should be less than 5MB",
|
|
108
|
+
"invalid_image_file": "The selected file is not a valid image",
|
|
109
|
+
"invalid_image_format": "Invalid image format detected",
|
|
110
|
+
"search_failed": "Search failed. Please try again later",
|
|
111
|
+
"connection_failed": "Image search failed. Please check your connection and try again",
|
|
112
|
+
"invalid_image_properties": "Invalid image properties detected",
|
|
113
|
+
"file_read_error": "Error reading the file",
|
|
114
|
+
"processing_error": "Error processing image",
|
|
115
|
+
"crop_processing_error": "Error processing cropped image"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"forms": {
|
|
119
|
+
"sending": "Sending...",
|
|
120
|
+
"success": "Form submitted successfully!",
|
|
121
|
+
"error": "An error occurred while submitting the form. Please try again.",
|
|
122
|
+
"submit_error": "Form submit error:"
|
|
74
123
|
}
|
|
75
124
|
}
|
|
@@ -32,8 +32,69 @@
|
|
|
32
32
|
"installment": "Installment",
|
|
33
33
|
"stock_alert": {
|
|
34
34
|
"title": "Stock Alert",
|
|
35
|
-
"success_description": "When your size is back in stock we
|
|
35
|
+
"success_description": "When your size is back in stock we'll send an email to: <Email/>",
|
|
36
36
|
"error_description": "An unexpected error has occured. Please try again later.",
|
|
37
37
|
"close_button": "CLOSE"
|
|
38
|
+
},
|
|
39
|
+
"virtual_try_on": {
|
|
40
|
+
"title": "Virtual Try On",
|
|
41
|
+
"title_result": "Virtual Try-On Result",
|
|
42
|
+
"button_text": "Enter Virtual Cabin",
|
|
43
|
+
"loading": "Loading...",
|
|
44
|
+
"upload_title": "Upload Your Photo",
|
|
45
|
+
"upload_prompt": "Click to upload image",
|
|
46
|
+
"upload_requirements": "Max 1MB, JPEG/PNG/WebP only",
|
|
47
|
+
"instructions": "Upload a clear photo of yourself for the best virtual try-on experience. Make sure you are facing the camera directly.",
|
|
48
|
+
"try_on": "Try On",
|
|
49
|
+
"virtual_cabin": "Virtual Cabin",
|
|
50
|
+
"upload_info": "Your photo is used solely for generating the virtual try-on and is not stored permanently.",
|
|
51
|
+
"edit_photo": "Edit Photo",
|
|
52
|
+
"processing": "Processing...",
|
|
53
|
+
"processing_title": "Almost ready!",
|
|
54
|
+
"processing_message": "We are processing your photo to provide the best result. Please wait.",
|
|
55
|
+
"result_title": "Virtual Cabin Result",
|
|
56
|
+
"result_placeholder": "Upload your photo to see the result",
|
|
57
|
+
"error": "Virtual try-on failed. Please try again.",
|
|
58
|
+
"error_message": "Please try again with a photo where the model is clearly visible and has a simpler background.",
|
|
59
|
+
"feedback_prompt": "How did the virtual try-on work for you?",
|
|
60
|
+
"feedback_like": "I like it",
|
|
61
|
+
"feedback_dislike": "I don't like it",
|
|
62
|
+
"reset_crop": "Reset Crop",
|
|
63
|
+
"retry": "Retry",
|
|
64
|
+
"retry_upload": "Upload Again",
|
|
65
|
+
"click_to_view_details": "Click on the image to view details.",
|
|
66
|
+
"back_to_basket": "Back to Cart",
|
|
67
|
+
"products_listed_count": "{{count}} products from your cart that are suitable for Virtual Cabin are listed.",
|
|
68
|
+
"select_up_to_3": "Please select up to 3 products to continue.",
|
|
69
|
+
"select_products": "Select Products",
|
|
70
|
+
"no_suitable_products": "No suitable products found in your cart for virtual try-on.",
|
|
71
|
+
"rule_1": "Background should be plain and well-lit.",
|
|
72
|
+
"rule_2": "Choose a bright, clear, and high-quality image.",
|
|
73
|
+
"rule_3": "Details on your body should be clearly distinguishable.",
|
|
74
|
+
"rule_4": "Look directly at the camera and show your face from the front.",
|
|
75
|
+
"rule_5": "Crop the photo according to the product you want to try on.",
|
|
76
|
+
"rule_6": "You can only upload images in JPEG or PNG format.",
|
|
77
|
+
"photo_preview": "Photo Preview",
|
|
78
|
+
"error_title": "An Error Occurred",
|
|
79
|
+
"legal": {
|
|
80
|
+
"title": "Consent Statement",
|
|
81
|
+
"text": "I hereby declare that I give my <strong>explicit consent</strong> for the image I will upload to be used for <strong>AI-powered processing, enhancement, analysis, and content creation</strong> purposes.",
|
|
82
|
+
"accept": "Accept",
|
|
83
|
+
"error": "Please accept the consent statement."
|
|
84
|
+
},
|
|
85
|
+
"multiple_results_title": "Virtual Try-On Results",
|
|
86
|
+
"multiple_results_subtitle": "Try-on completed for {{count}} products",
|
|
87
|
+
"error_incompatible": "Image Not Compatible",
|
|
88
|
+
"error_auto_reported": "Error automatically reported",
|
|
89
|
+
"feedback_question": "How was the result?",
|
|
90
|
+
"feedback_success": "Success",
|
|
91
|
+
"feedback_failed": "Failed",
|
|
92
|
+
"feedback_thank_you": "Thank you for your feedback!",
|
|
93
|
+
"recreate_button": "Recreate",
|
|
94
|
+
"close_button": "Close",
|
|
95
|
+
"change_photo": "Change",
|
|
96
|
+
"starting": "Starting...",
|
|
97
|
+
"will_start": "will start virtual try-on for",
|
|
98
|
+
"products_count": "products"
|
|
38
99
|
}
|
|
39
100
|
}
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"subtotal": "Ara toplam",
|
|
38
38
|
"shipping": "Kargo",
|
|
39
39
|
"discounts_total": "İndirimler Toplamı",
|
|
40
|
+
"loyalty_money_total": "Sadakat Parası Toplamı",
|
|
40
41
|
"total": "Toplam",
|
|
41
42
|
"delivery_info": "Teslimat Bilgileri",
|
|
42
43
|
"change": "değiştir",
|
|
@@ -138,6 +139,11 @@
|
|
|
138
139
|
"payments": "Ödemeler",
|
|
139
140
|
"per_month": "Her ay",
|
|
140
141
|
"total": "Toplam"
|
|
142
|
+
},
|
|
143
|
+
"store_credit": {
|
|
144
|
+
"use_my_store_credits": "pz-zero kredilerimi kullan",
|
|
145
|
+
"available_balance": "Mevcut Bakiyem",
|
|
146
|
+
"insufficient_balance": "pz-zero kredileriniz siparişi ödemek için yeterli değil, lütfen <Amount/> tutarını karşılamak için ek bir ödeme yöntemi seçin."
|
|
141
147
|
}
|
|
142
148
|
},
|
|
143
149
|
"agreement": {
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
"navbar": {
|
|
18
18
|
"search": "ARA"
|
|
19
19
|
},
|
|
20
|
+
"good": "İyi",
|
|
21
|
+
"bad": "Kötü",
|
|
20
22
|
"mobile_menu": {
|
|
21
23
|
"back": "Geri"
|
|
22
24
|
},
|
|
@@ -27,7 +29,25 @@
|
|
|
27
29
|
"clean": "temizle",
|
|
28
30
|
"categories": "KATEGORİLER",
|
|
29
31
|
"view_all": "HEPSİNİ GÖSTER",
|
|
30
|
-
"not_found": "Arama Sonuçları Bulunamadı"
|
|
32
|
+
"not_found": "Arama Sonuçları Bulunamadı",
|
|
33
|
+
"image_search": {
|
|
34
|
+
"title": "Görsel ile Ara",
|
|
35
|
+
"upload_image": "Benzer ürünleri bulmak için bir görsel yükleyin",
|
|
36
|
+
"select_image": "Görsel Seç",
|
|
37
|
+
"crop_image": "Görsel Kırp",
|
|
38
|
+
"cancel_crop": "Kırpmayı İptal Et",
|
|
39
|
+
"apply_crop": "Kırpmayı Uygula",
|
|
40
|
+
"try_another": "Başka Görsel Dene",
|
|
41
|
+
"search_image": "Arama Görseli",
|
|
42
|
+
"similar_products": "Benzer Ürünler",
|
|
43
|
+
"loading_cropper": "Kırpıcı yükleniyor...",
|
|
44
|
+
"no_products": "Benzer ürün bulunamadı",
|
|
45
|
+
"best_results": "En iyi sonuçlar için:",
|
|
46
|
+
"tip_1": "Net ürün görselleri yükleyin",
|
|
47
|
+
"tip_2": "Basit arka planlı görseller kullanın",
|
|
48
|
+
"tip_3": "Ana ürüne odaklanın",
|
|
49
|
+
"tip_4": "Belirli detaylara odaklanmak için kırpma aracını kullanın"
|
|
50
|
+
}
|
|
31
51
|
},
|
|
32
52
|
"page_404": {
|
|
33
53
|
"title": "Sayfa bulunamadı.",
|
|
@@ -71,5 +91,34 @@
|
|
|
71
91
|
"file_input": {
|
|
72
92
|
"select_file": "Dosya Seç",
|
|
73
93
|
"no_file": "Dosya seçilmedi"
|
|
94
|
+
},
|
|
95
|
+
"product": {
|
|
96
|
+
"no_products": "Ürün bulunamadı",
|
|
97
|
+
"new_image": "Yeni Görsel",
|
|
98
|
+
"view_similar_styles": "Benzer Stillere Göz At",
|
|
99
|
+
"clear_all_filters": "Tüm Filtreleri Temizle",
|
|
100
|
+
"reset_to_original": "Orjinale Dön",
|
|
101
|
+
"similar_styles": "Benzer Stillere Göz At",
|
|
102
|
+
"filters": "Filtreler",
|
|
103
|
+
"active_filters": "Aktif Filtreler"
|
|
104
|
+
},
|
|
105
|
+
"similar_products": {
|
|
106
|
+
"errors": {
|
|
107
|
+
"file_size_too_large": "Görsel boyutu 5MB'dan küçük olmalıdır",
|
|
108
|
+
"invalid_image_file": "Seçilen dosya geçerli bir görsel değil",
|
|
109
|
+
"invalid_image_format": "Geçersiz görsel formatı tespit edildi",
|
|
110
|
+
"search_failed": "Arama başarısız oldu. Lütfen daha sonra tekrar deneyin",
|
|
111
|
+
"connection_failed": "Görsel arama başarısız oldu. Lütfen bağlantınızı kontrol edip tekrar deneyin",
|
|
112
|
+
"invalid_image_properties": "Geçersiz görsel özellikleri tespit edildi",
|
|
113
|
+
"file_read_error": "Dosya okuma hatası",
|
|
114
|
+
"processing_error": "Görsel işleme hatası",
|
|
115
|
+
"crop_processing_error": "Kırpılan görsel işleme hatası"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"forms": {
|
|
119
|
+
"sending": "Gönderiliyor...",
|
|
120
|
+
"success": "Form başarıyla gönderildi!",
|
|
121
|
+
"error": "Form gönderilirken bir hata oluştu. Lütfen tekrar deneyin.",
|
|
122
|
+
"submit_error": "Form gönderme hatası:"
|
|
74
123
|
}
|
|
75
124
|
}
|