@djangocfg/ext-payments 1.0.22 → 1.0.23

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/dist/config.cjs CHANGED
@@ -27,7 +27,7 @@ var import_ext_base = require("@djangocfg/ext-base");
27
27
  // package.json
28
28
  var package_default = {
29
29
  name: "@djangocfg/ext-payments",
30
- version: "1.0.22",
30
+ version: "1.0.23",
31
31
  description: "Payments system extension for DjangoCFG",
32
32
  keywords: [
33
33
  "django",
@@ -101,16 +101,17 @@ var package_default = {
101
101
  "@djangocfg/i18n": "workspace:*",
102
102
  "@djangocfg/ui-core": "workspace:*",
103
103
  "@djangocfg/ui-nextjs": "workspace:*",
104
+ "@hookform/resolvers": "^5.2.2",
104
105
  consola: "^3.4.2",
105
106
  "lucide-react": "^0.545.0",
107
+ moment: "^2.30.1",
106
108
  next: "^16",
109
+ "next-intl": "^4",
107
110
  "p-retry": "^7.0.0",
108
111
  react: "^19",
109
- swr: "^2.3.7",
110
- zod: "^4.3.4",
111
- moment: "^2.30.1",
112
112
  "react-hook-form": "^7.69.0",
113
- "@hookform/resolvers": "^5.2.2"
113
+ swr: "^2.3.7",
114
+ zod: "^4.3.4"
114
115
  },
115
116
  devDependencies: {
116
117
  "@djangocfg/api": "workspace:*",
@@ -121,6 +122,7 @@ var package_default = {
121
122
  "@types/node": "^24.7.2",
122
123
  "@types/react": "^19.0.0",
123
124
  consola: "^3.4.2",
125
+ "next-intl": "^4.1.0",
124
126
  "p-retry": "^7.0.0",
125
127
  swr: "^2.3.7",
126
128
  tsup: "^8.5.0",
package/dist/config.js CHANGED
@@ -4,7 +4,7 @@ import { createExtensionConfig } from "@djangocfg/ext-base";
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "@djangocfg/ext-payments",
7
- version: "1.0.22",
7
+ version: "1.0.23",
8
8
  description: "Payments system extension for DjangoCFG",
9
9
  keywords: [
10
10
  "django",
@@ -78,16 +78,17 @@ var package_default = {
78
78
  "@djangocfg/i18n": "workspace:*",
79
79
  "@djangocfg/ui-core": "workspace:*",
80
80
  "@djangocfg/ui-nextjs": "workspace:*",
81
+ "@hookform/resolvers": "^5.2.2",
81
82
  consola: "^3.4.2",
82
83
  "lucide-react": "^0.545.0",
84
+ moment: "^2.30.1",
83
85
  next: "^16",
86
+ "next-intl": "^4",
84
87
  "p-retry": "^7.0.0",
85
88
  react: "^19",
86
- swr: "^2.3.7",
87
- zod: "^4.3.4",
88
- moment: "^2.30.1",
89
89
  "react-hook-form": "^7.69.0",
90
- "@hookform/resolvers": "^5.2.2"
90
+ swr: "^2.3.7",
91
+ zod: "^4.3.4"
91
92
  },
92
93
  devDependencies: {
93
94
  "@djangocfg/api": "workspace:*",
@@ -98,6 +99,7 @@ var package_default = {
98
99
  "@types/node": "^24.7.2",
99
100
  "@types/react": "^19.0.0",
100
101
  consola: "^3.4.2",
102
+ "next-intl": "^4.1.0",
101
103
  "p-retry": "^7.0.0",
102
104
  swr: "^2.3.7",
103
105
  tsup: "^8.5.0",
package/dist/i18n.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -19,15 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
20
  // src/i18n/index.ts
20
21
  var i18n_exports = {};
21
22
  __export(i18n_exports, {
22
- PAYMENTS_NAMESPACE: () => PAYMENTS_NAMESPACE,
23
23
  en: () => en,
24
24
  ko: () => ko,
25
- paymentsI18n: () => paymentsI18n,
26
- paymentsTranslations: () => paymentsTranslations,
27
- ru: () => ru
25
+ ru: () => ru,
26
+ usePaymentsT: () => usePaymentsT
28
27
  });
29
28
  module.exports = __toCommonJS(i18n_exports);
30
- var import_i18n = require("@djangocfg/ext-base/i18n");
29
+
30
+ // src/i18n/usePaymentsT.ts
31
+ var import_next_intl = require("next-intl");
32
+ var import_react = require("react");
31
33
 
32
34
  // src/i18n/locales/en.ts
33
35
  var en = {
@@ -401,20 +403,32 @@ var ko = {
401
403
  }
402
404
  };
403
405
 
404
- // src/i18n/index.ts
405
- var PAYMENTS_NAMESPACE = "payments";
406
- var paymentsI18n = (0, import_i18n.createExtensionI18n)({
407
- namespace: PAYMENTS_NAMESPACE,
408
- defaultLocale: "en",
409
- locales: { en, ru, ko }
410
- });
411
- var paymentsTranslations = paymentsI18n.getAllTranslations();
406
+ // src/i18n/usePaymentsT.ts
407
+ var translations = { en, ru, ko };
408
+ function getNestedValue(obj, path) {
409
+ const keys = path.split(".");
410
+ let result = obj;
411
+ for (const key of keys) {
412
+ if (result && typeof result === "object" && key in result) {
413
+ result = result[key];
414
+ } else {
415
+ return path;
416
+ }
417
+ }
418
+ return typeof result === "string" ? result : path;
419
+ }
420
+ function usePaymentsT() {
421
+ const locale = (0, import_next_intl.useLocale)();
422
+ const t = (0, import_react.useMemo)(() => translations[locale] || translations.en, [locale]);
423
+ return (0, import_react.useCallback)(
424
+ (key) => getNestedValue(t, key),
425
+ [t]
426
+ );
427
+ }
412
428
  // Annotate the CommonJS export names for ESM import in node:
413
429
  0 && (module.exports = {
414
- PAYMENTS_NAMESPACE,
415
430
  en,
416
431
  ko,
417
- paymentsI18n,
418
- paymentsTranslations,
419
- ru
432
+ ru,
433
+ usePaymentsT
420
434
  });
package/dist/i18n.d.cts CHANGED
@@ -1,16 +1,14 @@
1
- import * as _djangocfg_ext_base_i18n from '@djangocfg/ext-base/i18n';
2
- import { ExtensionKeys, PathKeys } from '@djangocfg/ext-base/i18n';
3
-
4
1
  /**
5
2
  * Payments Extension I18n Types
6
3
  */
7
-
8
4
  /**
9
- * All valid keys for payments translations (with namespace)
5
+ * Helper type to get dot-notation paths from nested object
10
6
  */
11
- type PaymentsKeys = ExtensionKeys<'payments', PaymentsTranslations>;
7
+ type PathKeys<T, Prefix extends string = ''> = T extends object ? {
8
+ [K in keyof T]: K extends string ? T[K] extends object ? PathKeys<T[K], `${Prefix}${K}.`> : `${Prefix}${K}` : never;
9
+ }[keyof T] : never;
12
10
  /**
13
- * Keys without namespace prefix (for createTypedExtensionT)
11
+ * Keys for payments translations
14
12
  */
15
13
  type PaymentsLocalKeys = PathKeys<PaymentsTranslations>;
16
14
  interface PaymentsTranslations {
@@ -149,23 +147,26 @@ interface PaymentsTranslations {
149
147
  };
150
148
  }
151
149
 
150
+ /**
151
+ * Self-contained translation hook for payments extension
152
+ *
153
+ * Uses built-in translations based on current locale from next-intl.
154
+ * No need to add translations to app's i18n config.
155
+ *
156
+ * @example
157
+ * ```tsx
158
+ * function BalanceCard() {
159
+ * const t = usePaymentsT();
160
+ * return <span>{t('balance.available')}</span>;
161
+ * }
162
+ * ```
163
+ */
164
+ declare function usePaymentsT(): (key: PaymentsLocalKeys) => string;
165
+
152
166
  declare const en: PaymentsTranslations;
153
167
 
154
168
  declare const ru: PaymentsTranslations;
155
169
 
156
170
  declare const ko: PaymentsTranslations;
157
171
 
158
- /** Payments extension namespace */
159
- declare const PAYMENTS_NAMESPACE: "payments";
160
- /**
161
- * Payments extension i18n instance
162
- */
163
- declare const paymentsI18n: _djangocfg_ext_base_i18n.ExtensionI18n<PaymentsTranslations>;
164
- /**
165
- * All payments translations ready to merge with app translations
166
- */
167
- declare const paymentsTranslations: Record<string, {
168
- [namespace: string]: PaymentsTranslations;
169
- }>;
170
-
171
- export { PAYMENTS_NAMESPACE, type PaymentsKeys, type PaymentsLocalKeys, type PaymentsTranslations, en, ko, paymentsI18n, paymentsTranslations, ru };
172
+ export { type PaymentsLocalKeys, type PaymentsTranslations, en, ko, ru, usePaymentsT };
package/dist/i18n.d.ts CHANGED
@@ -1,16 +1,14 @@
1
- import * as _djangocfg_ext_base_i18n from '@djangocfg/ext-base/i18n';
2
- import { ExtensionKeys, PathKeys } from '@djangocfg/ext-base/i18n';
3
-
4
1
  /**
5
2
  * Payments Extension I18n Types
6
3
  */
7
-
8
4
  /**
9
- * All valid keys for payments translations (with namespace)
5
+ * Helper type to get dot-notation paths from nested object
10
6
  */
11
- type PaymentsKeys = ExtensionKeys<'payments', PaymentsTranslations>;
7
+ type PathKeys<T, Prefix extends string = ''> = T extends object ? {
8
+ [K in keyof T]: K extends string ? T[K] extends object ? PathKeys<T[K], `${Prefix}${K}.`> : `${Prefix}${K}` : never;
9
+ }[keyof T] : never;
12
10
  /**
13
- * Keys without namespace prefix (for createTypedExtensionT)
11
+ * Keys for payments translations
14
12
  */
15
13
  type PaymentsLocalKeys = PathKeys<PaymentsTranslations>;
16
14
  interface PaymentsTranslations {
@@ -149,23 +147,26 @@ interface PaymentsTranslations {
149
147
  };
150
148
  }
151
149
 
150
+ /**
151
+ * Self-contained translation hook for payments extension
152
+ *
153
+ * Uses built-in translations based on current locale from next-intl.
154
+ * No need to add translations to app's i18n config.
155
+ *
156
+ * @example
157
+ * ```tsx
158
+ * function BalanceCard() {
159
+ * const t = usePaymentsT();
160
+ * return <span>{t('balance.available')}</span>;
161
+ * }
162
+ * ```
163
+ */
164
+ declare function usePaymentsT(): (key: PaymentsLocalKeys) => string;
165
+
152
166
  declare const en: PaymentsTranslations;
153
167
 
154
168
  declare const ru: PaymentsTranslations;
155
169
 
156
170
  declare const ko: PaymentsTranslations;
157
171
 
158
- /** Payments extension namespace */
159
- declare const PAYMENTS_NAMESPACE: "payments";
160
- /**
161
- * Payments extension i18n instance
162
- */
163
- declare const paymentsI18n: _djangocfg_ext_base_i18n.ExtensionI18n<PaymentsTranslations>;
164
- /**
165
- * All payments translations ready to merge with app translations
166
- */
167
- declare const paymentsTranslations: Record<string, {
168
- [namespace: string]: PaymentsTranslations;
169
- }>;
170
-
171
- export { PAYMENTS_NAMESPACE, type PaymentsKeys, type PaymentsLocalKeys, type PaymentsTranslations, en, ko, paymentsI18n, paymentsTranslations, ru };
172
+ export { type PaymentsLocalKeys, type PaymentsTranslations, en, ko, ru, usePaymentsT };
package/dist/i18n.js CHANGED
@@ -1,5 +1,8 @@
1
- // src/i18n/index.ts
2
- import { createExtensionI18n } from "@djangocfg/ext-base/i18n";
1
+ "use client";
2
+
3
+ // src/i18n/usePaymentsT.ts
4
+ import { useLocale } from "next-intl";
5
+ import { useMemo, useCallback } from "react";
3
6
 
4
7
  // src/i18n/locales/en.ts
5
8
  var en = {
@@ -373,19 +376,31 @@ var ko = {
373
376
  }
374
377
  };
375
378
 
376
- // src/i18n/index.ts
377
- var PAYMENTS_NAMESPACE = "payments";
378
- var paymentsI18n = createExtensionI18n({
379
- namespace: PAYMENTS_NAMESPACE,
380
- defaultLocale: "en",
381
- locales: { en, ru, ko }
382
- });
383
- var paymentsTranslations = paymentsI18n.getAllTranslations();
379
+ // src/i18n/usePaymentsT.ts
380
+ var translations = { en, ru, ko };
381
+ function getNestedValue(obj, path) {
382
+ const keys = path.split(".");
383
+ let result = obj;
384
+ for (const key of keys) {
385
+ if (result && typeof result === "object" && key in result) {
386
+ result = result[key];
387
+ } else {
388
+ return path;
389
+ }
390
+ }
391
+ return typeof result === "string" ? result : path;
392
+ }
393
+ function usePaymentsT() {
394
+ const locale = useLocale();
395
+ const t = useMemo(() => translations[locale] || translations.en, [locale]);
396
+ return useCallback(
397
+ (key) => getNestedValue(t, key),
398
+ [t]
399
+ );
400
+ }
384
401
  export {
385
- PAYMENTS_NAMESPACE,
386
402
  en,
387
403
  ko,
388
- paymentsI18n,
389
- paymentsTranslations,
390
- ru
404
+ ru,
405
+ usePaymentsT
391
406
  };
package/dist/index.cjs CHANGED
@@ -8,8 +8,7 @@ var zod = require('zod');
8
8
  var useSWR = require('swr');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
10
  var lucideReact = require('lucide-react');
11
- var i18n = require('@djangocfg/ext-base/i18n');
12
- var i18n$1 = require('@djangocfg/i18n');
11
+ var nextIntl = require('next-intl');
13
12
  var uiCore = require('@djangocfg/ui-core');
14
13
  var lib = require('@djangocfg/ui-core/lib');
15
14
  var moment3 = require('moment');
@@ -2428,17 +2427,30 @@ var ko = {
2428
2427
  }
2429
2428
  };
2430
2429
 
2431
- // src/i18n/index.ts
2432
- var PAYMENTS_NAMESPACE = "payments";
2433
- var paymentsI18n = i18n.createExtensionI18n({
2434
- namespace: PAYMENTS_NAMESPACE,
2435
- defaultLocale: "en",
2436
- locales: { en, ru, ko }
2437
- });
2438
- paymentsI18n.getAllTranslations();
2430
+ // src/i18n/usePaymentsT.ts
2431
+ var translations = { en, ru, ko };
2432
+ function getNestedValue(obj, path) {
2433
+ const keys = path.split(".");
2434
+ let result = obj;
2435
+ for (const key of keys) {
2436
+ if (result && typeof result === "object" && key in result) {
2437
+ result = result[key];
2438
+ } else {
2439
+ return path;
2440
+ }
2441
+ }
2442
+ return typeof result === "string" ? result : path;
2443
+ }
2444
+ function usePaymentsT() {
2445
+ const locale = nextIntl.useLocale();
2446
+ const t = react.useMemo(() => translations[locale] || translations.en, [locale]);
2447
+ return react.useCallback(
2448
+ (key) => getNestedValue(t, key),
2449
+ [t]
2450
+ );
2451
+ }
2439
2452
  function BalanceHero({ onAddFunds, onWithdraw, className }) {
2440
- const baseT = i18n$1.useT();
2441
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2453
+ const pt = usePaymentsT();
2442
2454
  const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
2443
2455
  const labels = react.useMemo(() => ({
2444
2456
  available: pt("balance.available"),
@@ -2599,8 +2611,7 @@ function ActivityList({
2599
2611
  limit = 10,
2600
2612
  className
2601
2613
  }) {
2602
- const baseT = i18n$1.useT();
2603
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2614
+ const pt = usePaymentsT();
2604
2615
  const { activity, isLoadingActivity, hasMoreActivity } = useWallet();
2605
2616
  const labels = react.useMemo(() => ({
2606
2617
  title: pt("activity.title"),
@@ -2861,8 +2872,7 @@ function CurrencyCombobox({
2861
2872
  disabled,
2862
2873
  placeholder
2863
2874
  }) {
2864
- const baseT = i18n$1.useT();
2865
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2875
+ const pt = usePaymentsT();
2866
2876
  const labels = react.useMemo(() => ({
2867
2877
  selectCurrency: pt("form.selectCurrency"),
2868
2878
  search: pt("form.search")
@@ -2894,8 +2904,7 @@ var AddFundsSchema = zod.z.object({
2894
2904
  });
2895
2905
  var STORAGE_KEY = "payments:addFunds";
2896
2906
  function AddFundsSheet({ open, onOpenChange, onSuccess }) {
2897
- const baseT = i18n$1.useT();
2898
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2907
+ const pt = usePaymentsT();
2899
2908
  const { currencies, isLoadingCurrencies, addFunds } = useWallet();
2900
2909
  const [isSubmitting, setIsSubmitting] = react.useState(false);
2901
2910
  const [error, setError] = react.useState(null);
@@ -3130,8 +3139,7 @@ var WithdrawSchema = zod.z.object({
3130
3139
  });
3131
3140
  var STORAGE_KEY2 = "payments:withdraw";
3132
3141
  function WithdrawSheet({ open, onOpenChange, onSuccess }) {
3133
- const baseT = i18n$1.useT();
3134
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
3142
+ const pt = usePaymentsT();
3135
3143
  const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
3136
3144
  const [isSubmitting, setIsSubmitting] = react.useState(false);
3137
3145
  const [error, setError] = react.useState(null);
@@ -3404,8 +3412,7 @@ var statusConfig2 = {
3404
3412
  }
3405
3413
  };
3406
3414
  function WithdrawalSheet({ withdrawalId, open, onOpenChange }) {
3407
- const baseT = i18n$1.useT();
3408
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
3415
+ const pt = usePaymentsT();
3409
3416
  const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
3410
3417
  const labels = react.useMemo(() => ({
3411
3418
  title: pt("sheets.withdrawalTitle"),
@@ -3661,8 +3668,7 @@ var statusConfig3 = {
3661
3668
  }
3662
3669
  };
3663
3670
  function PaymentSheet({ paymentId, open, onOpenChange, onCreateNew }) {
3664
- const baseT = i18n$1.useT();
3665
- const pt = i18n.createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
3671
+ const pt = usePaymentsT();
3666
3672
  const { getPaymentDetails } = useWallet();
3667
3673
  const [timeLeft, setTimeLeft] = react.useState("");
3668
3674
  const labels = react.useMemo(() => ({
@@ -3970,7 +3976,7 @@ function WalletPage() {
3970
3976
  // package.json
3971
3977
  var package_default = {
3972
3978
  name: "@djangocfg/ext-payments",
3973
- version: "1.0.22",
3979
+ version: "1.0.23",
3974
3980
  description: "Payments system extension for DjangoCFG",
3975
3981
  keywords: [
3976
3982
  "django",
@@ -4044,16 +4050,17 @@ var package_default = {
4044
4050
  "@djangocfg/i18n": "workspace:*",
4045
4051
  "@djangocfg/ui-core": "workspace:*",
4046
4052
  "@djangocfg/ui-nextjs": "workspace:*",
4053
+ "@hookform/resolvers": "^5.2.2",
4047
4054
  consola: "^3.4.2",
4048
4055
  "lucide-react": "^0.545.0",
4056
+ moment: "^2.30.1",
4049
4057
  next: "^16",
4058
+ "next-intl": "^4",
4050
4059
  "p-retry": "^7.0.0",
4051
4060
  react: "^19",
4052
- swr: "^2.3.7",
4053
- zod: "^4.3.4",
4054
- moment: "^2.30.1",
4055
4061
  "react-hook-form": "^7.69.0",
4056
- "@hookform/resolvers": "^5.2.2"
4062
+ swr: "^2.3.7",
4063
+ zod: "^4.3.4"
4057
4064
  },
4058
4065
  devDependencies: {
4059
4066
  "@djangocfg/api": "workspace:*",
@@ -4064,6 +4071,7 @@ var package_default = {
4064
4071
  "@types/node": "^24.7.2",
4065
4072
  "@types/react": "^19.0.0",
4066
4073
  consola: "^3.4.2",
4074
+ "next-intl": "^4.1.0",
4067
4075
  "p-retry": "^7.0.0",
4068
4076
  swr: "^2.3.7",
4069
4077
  tsup: "^8.5.0",
package/dist/index.js CHANGED
@@ -6,8 +6,7 @@ import { z } from 'zod';
6
6
  import useSWR, { useSWRConfig } from 'swr';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
8
  import { Plus, ArrowUpRight, RefreshCw, AlertCircle, XCircle, CheckCircle2, Loader2, Clock, ArrowDownLeft, History, ChevronRight, Ban, ExternalLink } from 'lucide-react';
9
- import { createExtensionI18n, createTypedExtensionT } from '@djangocfg/ext-base/i18n';
10
- import { useT } from '@djangocfg/i18n';
9
+ import { useLocale } from 'next-intl';
11
10
  import { Skeleton, Button, TokenIcon, useLocalStorage, ResponsiveSheet, ResponsiveSheetContent, ResponsiveSheetHeader, ResponsiveSheetTitle, ResponsiveSheetDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Alert, AlertDescription, CopyButton, Combobox } from '@djangocfg/ui-core';
12
11
  import { cn } from '@djangocfg/ui-core/lib';
13
12
  import moment3 from 'moment';
@@ -2420,17 +2419,30 @@ var ko = {
2420
2419
  }
2421
2420
  };
2422
2421
 
2423
- // src/i18n/index.ts
2424
- var PAYMENTS_NAMESPACE = "payments";
2425
- var paymentsI18n = createExtensionI18n({
2426
- namespace: PAYMENTS_NAMESPACE,
2427
- defaultLocale: "en",
2428
- locales: { en, ru, ko }
2429
- });
2430
- paymentsI18n.getAllTranslations();
2422
+ // src/i18n/usePaymentsT.ts
2423
+ var translations = { en, ru, ko };
2424
+ function getNestedValue(obj, path) {
2425
+ const keys = path.split(".");
2426
+ let result = obj;
2427
+ for (const key of keys) {
2428
+ if (result && typeof result === "object" && key in result) {
2429
+ result = result[key];
2430
+ } else {
2431
+ return path;
2432
+ }
2433
+ }
2434
+ return typeof result === "string" ? result : path;
2435
+ }
2436
+ function usePaymentsT() {
2437
+ const locale = useLocale();
2438
+ const t = useMemo(() => translations[locale] || translations.en, [locale]);
2439
+ return useCallback(
2440
+ (key) => getNestedValue(t, key),
2441
+ [t]
2442
+ );
2443
+ }
2431
2444
  function BalanceHero({ onAddFunds, onWithdraw, className }) {
2432
- const baseT = useT();
2433
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2445
+ const pt = usePaymentsT();
2434
2446
  const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
2435
2447
  const labels = useMemo(() => ({
2436
2448
  available: pt("balance.available"),
@@ -2591,8 +2603,7 @@ function ActivityList({
2591
2603
  limit = 10,
2592
2604
  className
2593
2605
  }) {
2594
- const baseT = useT();
2595
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2606
+ const pt = usePaymentsT();
2596
2607
  const { activity, isLoadingActivity, hasMoreActivity } = useWallet();
2597
2608
  const labels = useMemo(() => ({
2598
2609
  title: pt("activity.title"),
@@ -2853,8 +2864,7 @@ function CurrencyCombobox({
2853
2864
  disabled,
2854
2865
  placeholder
2855
2866
  }) {
2856
- const baseT = useT();
2857
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2867
+ const pt = usePaymentsT();
2858
2868
  const labels = useMemo(() => ({
2859
2869
  selectCurrency: pt("form.selectCurrency"),
2860
2870
  search: pt("form.search")
@@ -2886,8 +2896,7 @@ var AddFundsSchema = z.object({
2886
2896
  });
2887
2897
  var STORAGE_KEY = "payments:addFunds";
2888
2898
  function AddFundsSheet({ open, onOpenChange, onSuccess }) {
2889
- const baseT = useT();
2890
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
2899
+ const pt = usePaymentsT();
2891
2900
  const { currencies, isLoadingCurrencies, addFunds } = useWallet();
2892
2901
  const [isSubmitting, setIsSubmitting] = useState(false);
2893
2902
  const [error, setError] = useState(null);
@@ -3122,8 +3131,7 @@ var WithdrawSchema = z.object({
3122
3131
  });
3123
3132
  var STORAGE_KEY2 = "payments:withdraw";
3124
3133
  function WithdrawSheet({ open, onOpenChange, onSuccess }) {
3125
- const baseT = useT();
3126
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
3134
+ const pt = usePaymentsT();
3127
3135
  const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
3128
3136
  const [isSubmitting, setIsSubmitting] = useState(false);
3129
3137
  const [error, setError] = useState(null);
@@ -3396,8 +3404,7 @@ var statusConfig2 = {
3396
3404
  }
3397
3405
  };
3398
3406
  function WithdrawalSheet({ withdrawalId, open, onOpenChange }) {
3399
- const baseT = useT();
3400
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
3407
+ const pt = usePaymentsT();
3401
3408
  const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
3402
3409
  const labels = useMemo(() => ({
3403
3410
  title: pt("sheets.withdrawalTitle"),
@@ -3653,8 +3660,7 @@ var statusConfig3 = {
3653
3660
  }
3654
3661
  };
3655
3662
  function PaymentSheet({ paymentId, open, onOpenChange, onCreateNew }) {
3656
- const baseT = useT();
3657
- const pt = createTypedExtensionT(baseT, PAYMENTS_NAMESPACE);
3663
+ const pt = usePaymentsT();
3658
3664
  const { getPaymentDetails } = useWallet();
3659
3665
  const [timeLeft, setTimeLeft] = useState("");
3660
3666
  const labels = useMemo(() => ({
@@ -3962,7 +3968,7 @@ function WalletPage() {
3962
3968
  // package.json
3963
3969
  var package_default = {
3964
3970
  name: "@djangocfg/ext-payments",
3965
- version: "1.0.22",
3971
+ version: "1.0.23",
3966
3972
  description: "Payments system extension for DjangoCFG",
3967
3973
  keywords: [
3968
3974
  "django",
@@ -4036,16 +4042,17 @@ var package_default = {
4036
4042
  "@djangocfg/i18n": "workspace:*",
4037
4043
  "@djangocfg/ui-core": "workspace:*",
4038
4044
  "@djangocfg/ui-nextjs": "workspace:*",
4045
+ "@hookform/resolvers": "^5.2.2",
4039
4046
  consola: "^3.4.2",
4040
4047
  "lucide-react": "^0.545.0",
4048
+ moment: "^2.30.1",
4041
4049
  next: "^16",
4050
+ "next-intl": "^4",
4042
4051
  "p-retry": "^7.0.0",
4043
4052
  react: "^19",
4044
- swr: "^2.3.7",
4045
- zod: "^4.3.4",
4046
- moment: "^2.30.1",
4047
4053
  "react-hook-form": "^7.69.0",
4048
- "@hookform/resolvers": "^5.2.2"
4054
+ swr: "^2.3.7",
4055
+ zod: "^4.3.4"
4049
4056
  },
4050
4057
  devDependencies: {
4051
4058
  "@djangocfg/api": "workspace:*",
@@ -4056,6 +4063,7 @@ var package_default = {
4056
4063
  "@types/node": "^24.7.2",
4057
4064
  "@types/react": "^19.0.0",
4058
4065
  consola: "^3.4.2",
4066
+ "next-intl": "^4.1.0",
4059
4067
  "p-retry": "^7.0.0",
4060
4068
  swr: "^2.3.7",
4061
4069
  tsup: "^8.5.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ext-payments",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "Payments system extension for DjangoCFG",
5
5
  "keywords": [
6
6
  "django",
@@ -69,31 +69,33 @@
69
69
  "check": "tsc --noEmit"
70
70
  },
71
71
  "peerDependencies": {
72
- "@djangocfg/api": "^2.1.111",
73
- "@djangocfg/ext-base": "^1.0.17",
74
- "@djangocfg/i18n": "^2.1.111",
75
- "@djangocfg/ui-core": "^2.1.111",
76
- "@djangocfg/ui-nextjs": "^2.1.111",
72
+ "@djangocfg/api": "^2.1.124",
73
+ "@djangocfg/ext-base": "^1.0.18",
74
+ "@djangocfg/i18n": "^2.1.124",
75
+ "@djangocfg/ui-core": "^2.1.124",
76
+ "@djangocfg/ui-nextjs": "^2.1.124",
77
+ "@hookform/resolvers": "^5.2.2",
77
78
  "consola": "^3.4.2",
78
79
  "lucide-react": "^0.545.0",
80
+ "moment": "^2.30.1",
79
81
  "next": "^16",
82
+ "next-intl": "^4",
80
83
  "p-retry": "^7.0.0",
81
84
  "react": "^19",
82
- "swr": "^2.3.7",
83
- "zod": "^4.3.4",
84
- "moment": "^2.30.1",
85
85
  "react-hook-form": "^7.69.0",
86
- "@hookform/resolvers": "^5.2.2"
86
+ "swr": "^2.3.7",
87
+ "zod": "^4.3.4"
87
88
  },
88
89
  "devDependencies": {
89
- "@djangocfg/api": "^2.1.111",
90
- "@djangocfg/ext-base": "^1.0.17",
91
- "@djangocfg/i18n": "^2.1.111",
92
- "@djangocfg/typescript-config": "^2.1.111",
93
- "@djangocfg/ui-nextjs": "^2.1.111",
90
+ "@djangocfg/api": "^2.1.124",
91
+ "@djangocfg/ext-base": "^1.0.18",
92
+ "@djangocfg/i18n": "^2.1.124",
93
+ "@djangocfg/typescript-config": "^2.1.124",
94
+ "@djangocfg/ui-nextjs": "^2.1.124",
94
95
  "@types/node": "^24.7.2",
95
96
  "@types/react": "^19.0.0",
96
97
  "consola": "^3.4.2",
98
+ "next-intl": "^4.1.0",
97
99
  "p-retry": "^7.0.0",
98
100
  "swr": "^2.3.7",
99
101
  "tsup": "^8.5.0",
@@ -9,9 +9,7 @@
9
9
  import { useMemo } from 'react';
10
10
  import { History, ChevronRight } from 'lucide-react';
11
11
 
12
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
13
- import { useT } from '@djangocfg/i18n';
14
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
12
+ import { usePaymentsT } from '../i18n';
15
13
  import { Button, Skeleton } from '@djangocfg/ui-core';
16
14
  import { cn } from '@djangocfg/ui-core/lib';
17
15
 
@@ -31,8 +29,7 @@ export function ActivityList({
31
29
  limit = 10,
32
30
  className,
33
31
  }: ActivityListProps) {
34
- const baseT = useT();
35
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
32
+ const pt = usePaymentsT();
36
33
  const { activity, isLoadingActivity, hasMoreActivity } = useWallet();
37
34
 
38
35
  // Prepare labels before render
@@ -13,9 +13,7 @@ import { useForm } from 'react-hook-form';
13
13
  import { z } from 'zod';
14
14
  import { zodResolver } from '@hookform/resolvers/zod';
15
15
 
16
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
17
- import { useT } from '@djangocfg/i18n';
18
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
16
+ import { usePaymentsT } from '../i18n';
19
17
  import {
20
18
  Alert,
21
19
  AlertDescription,
@@ -76,8 +74,7 @@ interface AddFundsSaved {
76
74
  }
77
75
 
78
76
  export function AddFundsSheet({ open, onOpenChange, onSuccess }: AddFundsSheetProps) {
79
- const baseT = useT();
80
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
77
+ const pt = usePaymentsT();
81
78
  const { currencies, isLoadingCurrencies, addFunds } = useWallet();
82
79
  const [isSubmitting, setIsSubmitting] = useState(false);
83
80
  const [error, setError] = useState<string | null>(null);
@@ -9,9 +9,7 @@
9
9
  import { useMemo } from 'react';
10
10
  import { Plus, ArrowUpRight, RefreshCw } from 'lucide-react';
11
11
 
12
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
13
- import { useT } from '@djangocfg/i18n';
14
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
12
+ import { usePaymentsT } from '../i18n';
15
13
  import { Button, Skeleton } from '@djangocfg/ui-core';
16
14
  import { cn } from '@djangocfg/ui-core/lib';
17
15
 
@@ -24,8 +22,7 @@ interface BalanceHeroProps {
24
22
  }
25
23
 
26
24
  export function BalanceHero({ onAddFunds, onWithdraw, className }: BalanceHeroProps) {
27
- const baseT = useT();
28
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
25
+ const pt = usePaymentsT();
29
26
  const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
30
27
 
31
28
  // Prepare labels before render
@@ -6,9 +6,7 @@
6
6
 
7
7
  import { useMemo } from 'react';
8
8
 
9
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
10
- import { useT } from '@djangocfg/i18n';
11
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
9
+ import { usePaymentsT } from '../i18n';
12
10
  import { Combobox, TokenIcon } from '@djangocfg/ui-core';
13
11
  import type { CurrencyOption } from '../types';
14
12
 
@@ -28,8 +26,7 @@ export function CurrencyCombobox({
28
26
  disabled,
29
27
  placeholder,
30
28
  }: CurrencyComboboxProps) {
31
- const baseT = useT();
32
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
29
+ const pt = usePaymentsT();
33
30
 
34
31
  const labels = useMemo(() => ({
35
32
  selectCurrency: pt('form.selectCurrency'),
@@ -19,9 +19,7 @@ import {
19
19
  import moment from 'moment';
20
20
  import useSWR from 'swr';
21
21
 
22
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
23
- import { useT } from '@djangocfg/i18n';
24
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
22
+ import { usePaymentsT } from '../i18n';
25
23
  import {
26
24
  Button,
27
25
  CopyButton,
@@ -87,8 +85,7 @@ const statusConfig: Record<string, { icon: any; color: string; bg: string; anima
87
85
  // ─────────────────────────────────────────────────────────────────────────────
88
86
 
89
87
  export function PaymentSheet({ paymentId, open, onOpenChange, onCreateNew }: PaymentSheetProps) {
90
- const baseT = useT();
91
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
88
+ const pt = usePaymentsT();
92
89
  const { getPaymentDetails } = useWallet();
93
90
  const [timeLeft, setTimeLeft] = useState<string>('');
94
91
 
@@ -13,9 +13,7 @@ import { useForm } from 'react-hook-form';
13
13
  import { z } from 'zod';
14
14
  import { zodResolver } from '@hookform/resolvers/zod';
15
15
 
16
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
17
- import { useT } from '@djangocfg/i18n';
18
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
16
+ import { usePaymentsT } from '../i18n';
19
17
  import {
20
18
  Alert,
21
19
  AlertDescription,
@@ -77,8 +75,7 @@ interface WithdrawSaved {
77
75
  // ─────────────────────────────────────────────────────────────────────────────
78
76
 
79
77
  export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetProps) {
80
- const baseT = useT();
81
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
78
+ const pt = usePaymentsT();
82
79
  const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
83
80
  const [isSubmitting, setIsSubmitting] = useState(false);
84
81
  const [error, setError] = useState<string | null>(null);
@@ -19,9 +19,7 @@ import {
19
19
  import moment from 'moment';
20
20
  import useSWR from 'swr';
21
21
 
22
- import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
23
- import { useT } from '@djangocfg/i18n';
24
- import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
22
+ import { usePaymentsT } from '../i18n';
25
23
  import {
26
24
  Button,
27
25
  CopyButton,
@@ -91,8 +89,7 @@ const statusConfig: Record<string, { icon: any; color: string; bg: string; anima
91
89
  // ─────────────────────────────────────────────────────────────────────────────
92
90
 
93
91
  export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: WithdrawalSheetProps) {
94
- const baseT = useT();
95
- const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
92
+ const pt = usePaymentsT();
96
93
  const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
97
94
 
98
95
  // Prepare labels before render
package/src/i18n/index.ts CHANGED
@@ -1,35 +1,26 @@
1
1
  /**
2
2
  * Payments Extension I18n
3
3
  *
4
- * Provides translations for the payments extension.
5
- * Can be merged with app translations using mergeExtensionTranslations from @djangocfg/ext-base/i18n
6
- */
7
-
8
- import { createExtensionI18n } from '@djangocfg/ext-base/i18n';
9
- import type { PaymentsTranslations } from './types';
10
- import { en } from './locales/en';
11
- import { ru } from './locales/ru';
12
- import { ko } from './locales/ko';
13
-
14
- /** Payments extension namespace */
15
- export const PAYMENTS_NAMESPACE = 'payments' as const;
16
-
17
- /**
18
- * Payments extension i18n instance
4
+ * Self-contained translations - no app configuration needed.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { usePaymentsT } from '@djangocfg/ext-payments/i18n';
9
+ *
10
+ * function MyComponent() {
11
+ * const t = usePaymentsT();
12
+ * return <span>{t('balance.available')}</span>;
13
+ * }
14
+ * ```
19
15
  */
20
- export const paymentsI18n = createExtensionI18n<PaymentsTranslations>({
21
- namespace: PAYMENTS_NAMESPACE,
22
- defaultLocale: 'en',
23
- locales: { en, ru, ko },
24
- });
25
16
 
26
- /**
27
- * All payments translations ready to merge with app translations
28
- */
29
- export const paymentsTranslations = paymentsI18n.getAllTranslations();
17
+ // Self-contained hook (recommended)
18
+ export { usePaymentsT } from './usePaymentsT';
30
19
 
31
20
  // Types
32
- export type { PaymentsTranslations, PaymentsKeys, PaymentsLocalKeys } from './types';
21
+ export type { PaymentsTranslations, PaymentsLocalKeys } from './types';
33
22
 
34
- // Re-export locales for direct access if needed
35
- export { en, ru, ko };
23
+ // Locales (for direct access if needed)
24
+ export { en } from './locales/en';
25
+ export { ru } from './locales/ru';
26
+ export { ko } from './locales/ko';
package/src/i18n/types.ts CHANGED
@@ -2,15 +2,21 @@
2
2
  * Payments Extension I18n Types
3
3
  */
4
4
 
5
- import type { ExtensionKeys, PathKeys } from '@djangocfg/ext-base/i18n';
6
-
7
5
  /**
8
- * All valid keys for payments translations (with namespace)
6
+ * Helper type to get dot-notation paths from nested object
9
7
  */
10
- export type PaymentsKeys = ExtensionKeys<'payments', PaymentsTranslations>;
8
+ type PathKeys<T, Prefix extends string = ''> = T extends object
9
+ ? {
10
+ [K in keyof T]: K extends string
11
+ ? T[K] extends object
12
+ ? PathKeys<T[K], `${Prefix}${K}.`>
13
+ : `${Prefix}${K}`
14
+ : never;
15
+ }[keyof T]
16
+ : never;
11
17
 
12
18
  /**
13
- * Keys without namespace prefix (for createTypedExtensionT)
19
+ * Keys for payments translations
14
20
  */
15
21
  export type PaymentsLocalKeys = PathKeys<PaymentsTranslations>;
16
22
 
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Self-contained translation hook for ext-payments
5
+ *
6
+ * Uses built-in translations, no app configuration needed.
7
+ */
8
+
9
+ import { useLocale } from 'next-intl';
10
+ import { useMemo, useCallback } from 'react';
11
+
12
+ import type { PaymentsTranslations, PaymentsLocalKeys } from './types';
13
+ import { en } from './locales/en';
14
+ import { ru } from './locales/ru';
15
+ import { ko } from './locales/ko';
16
+
17
+ const translations: Record<string, PaymentsTranslations> = { en, ru, ko };
18
+
19
+ /**
20
+ * Get nested value from object by dot-notation path
21
+ */
22
+ function getNestedValue(obj: Record<string, unknown>, path: string): string {
23
+ const keys = path.split('.');
24
+ let result: unknown = obj;
25
+
26
+ for (const key of keys) {
27
+ if (result && typeof result === 'object' && key in result) {
28
+ result = (result as Record<string, unknown>)[key];
29
+ } else {
30
+ return path; // Return key if not found
31
+ }
32
+ }
33
+
34
+ return typeof result === 'string' ? result : path;
35
+ }
36
+
37
+ /**
38
+ * Self-contained translation hook for payments extension
39
+ *
40
+ * Uses built-in translations based on current locale from next-intl.
41
+ * No need to add translations to app's i18n config.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * function BalanceCard() {
46
+ * const t = usePaymentsT();
47
+ * return <span>{t('balance.available')}</span>;
48
+ * }
49
+ * ```
50
+ */
51
+ export function usePaymentsT(): (key: PaymentsLocalKeys) => string {
52
+ const locale = useLocale();
53
+
54
+ const t = useMemo(() => translations[locale] || translations.en, [locale]);
55
+
56
+ return useCallback(
57
+ (key: PaymentsLocalKeys): string => getNestedValue(t as unknown as Record<string, unknown>, key),
58
+ [t]
59
+ );
60
+ }