feat(subscribe): Add subscription credits

This commit is contained in:
web@ppanel 2024-12-31 20:16:14 +07:00
parent 701cdee6de
commit 5bc7905a52
93 changed files with 1224 additions and 1098 deletions

View File

@ -556,6 +556,8 @@ declare namespace API {
trade_no: string;
status: number;
subscribe_id: number;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
@ -577,6 +579,8 @@ declare namespace API {
status: number;
subscribe_id: number;
subscribe: Subscribe;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};

View File

@ -173,6 +173,8 @@ declare namespace API {
trade_no: string;
status: number;
subscribe_id: number;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
@ -194,6 +196,8 @@ declare namespace API {
status: number;
subscribe_id: number;
subscribe: Subscribe;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};

View File

@ -26,7 +26,7 @@ import { Button } from '@workspace/ui/components/button';
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
import { Separator } from '@workspace/ui/components/separator';
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { getNextResetDate, isBrowser } from '@workspace/ui/utils';
import { isBrowser } from '@workspace/ui/utils';
import { differenceInDays } from 'date-fns';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
@ -35,12 +35,12 @@ import { QRCodeCanvas } from 'qrcode.react';
import { useState } from 'react';
import { toast } from 'sonner';
import Renewal from '@/components/subscribe/renewal';
import ResetTraffic from '@/components/subscribe/reset-traffic';
import useGlobalStore from '@/config/use-global';
import { getStat } from '@/services/common/common';
import { getPlatform } from '@/utils/common';
import CopyToClipboard from 'react-copy-to-clipboard';
import Renewal from '../order/renewal';
import ResetTraffic from '../order/reset-traffic';
import Subscribe from '../subscribe/page';
export default function Content() {
@ -173,15 +173,14 @@ export default function Content() {
</li>
<li>
<span className='text-muted-foreground'>{t('nextResetDays')}</span>
<span className='text-2xl font-semibold'>
{differenceInDays(getNextResetDate(item.start_time), new Date()) ||
t('unknown')}
</span>
<span className='text-2xl font-semibold'>{t('unknown')}</span>
</li>
<li>
<span className='text-muted-foreground'>{t('expirationDays')}</span>
<span className='text-2xl font-semibold'>
{differenceInDays(new Date(item.expire_time), new Date()) || t('unknown')}
{item.expire_time
? differenceInDays(new Date(item.expire_time), new Date()) || t('unknown')
: t('noLimit')}
</span>
</li>
</ul>

View File

@ -1,235 +0,0 @@
'use client';
import useGlobalStore from '@/config/use-global';
import { checkoutOrder, preCreateOrder, purchase } from '@/services/user/order';
import { getAvailablePaymentMethods } from '@/services/user/payment';
import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Card, CardContent } from '@workspace/ui/components/card';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@workspace/ui/components/dialog';
import { Input } from '@workspace/ui/components/input';
import { Label } from '@workspace/ui/components/label';
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
import { Separator } from '@workspace/ui/components/separator';
import { LoaderCircle } from 'lucide-react';
import { useTranslations } from 'next-intl';
import Image from 'next/legacy/image';
import { useRouter } from 'next/navigation';
import { useEffect, useState, useTransition } from 'react';
import { SubscribeBilling } from '../subscribe/billing';
import { SubscribeDetail } from '../subscribe/detail';
export default function Purchase({
subscribe,
setSubscribe,
}: {
subscribe?: API.Subscribe;
setSubscribe: (subscribe?: API.Subscribe) => void;
}) {
const t = useTranslations('order');
const { getUserInfo } = useGlobalStore();
const router = useRouter();
const [params, setParams] = useState<API.PurchaseOrderRequest>({
quantity: 1,
subscribe_id: subscribe?.id as number,
payment: 'balance',
coupon: '',
});
const [loading, startTransition] = useTransition();
const { data: order } = useQuery({
queryKey: ['preCreateOrder', params],
queryFn: async () => {
const { data } = await preCreateOrder({
...params,
subscribe_id: subscribe?.id as number,
});
return data.data;
},
enabled: !!params?.subscribe_id,
});
const { data: paymentMethods } = useQuery({
queryKey: ['getAvailablePaymentMethods'],
queryFn: async () => {
const { data } = await getAvailablePaymentMethods();
return data.data?.list || [];
},
});
useEffect(() => {
if (subscribe) {
setParams((prev) => ({
...prev,
quantity: 1,
subscribe_id: subscribe?.id,
}));
}
}, [subscribe]);
return (
<Dialog
open={!!subscribe?.id}
onOpenChange={(open) => {
if (!open) setSubscribe(undefined);
}}
>
<DialogContent className='flex h-full max-w-screen-lg flex-col overflow-hidden border-none p-0 md:h-auto'>
<DialogHeader className='p-6 pb-0'>
<DialogTitle>{t('buySubscription')}</DialogTitle>
</DialogHeader>
<div className='grid w-full flex-grow gap-3 overflow-auto p-6 pt-0 lg:grid-cols-2'>
<Card className='border-transparent shadow-none md:border-inherit md:shadow'>
<CardContent className='grid gap-3 p-0 text-sm md:p-6'>
<SubscribeDetail
subscribe={{
...subscribe,
quantity: params.quantity,
}}
/>
<Separator />
<SubscribeBilling
order={{
...order,
quantity: params.quantity,
unit_price: subscribe?.unit_price,
}}
/>
</CardContent>
</Card>
<div className='flex flex-col justify-between text-sm'>
<div className='grid gap-3'>
<div className='font-semibold'>{t('purchaseDuration')}</div>
<RadioGroup
value={String(params.quantity)}
onValueChange={(value) => {
setParams({
...params,
quantity: Number(value),
});
}}
className='flex flex-wrap gap-0.5 *:w-20 md:gap-2'
>
{subscribe?.unit_time !== 'Minute' && (
<div className='relative'>
<RadioGroupItem value='1' id='1' className='peer sr-only' />
<Label
htmlFor='1'
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary relative flex h-full flex-col items-center justify-center gap-2 rounded-md border-2 p-2'
>
1 / {t(subscribe?.unit_time || 'Month')}
</Label>
</div>
)}
{subscribe?.discount?.map((item) => (
<div key={item.quantity}>
<RadioGroupItem
value={String(item.quantity)}
id={String(item.quantity)}
className='peer sr-only'
/>
<Label
htmlFor={String(item.quantity)}
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary relative flex h-full flex-col items-center justify-center gap-2 rounded-md border-2 p-2'
>
{item.quantity} / {t(subscribe?.unit_time || 'Month')}
{item.discount < 100 && (
<Badge variant='destructive'>-{100 - item.discount}%</Badge>
)}
</Label>
</div>
))}
</RadioGroup>
<div className='flex'>
<Input
placeholder={t('enterCoupon')}
value={params.coupon}
onChange={(e) => {
setParams({
...params,
coupon: e.target.value.trim(),
});
}}
/>
</div>
<div className='font-semibold'>{t('paymentMethod')}</div>
<RadioGroup
className='mb-6 grid grid-cols-5 gap-2'
value={params.payment}
onValueChange={(value) => {
setParams({
...params,
payment: value,
});
}}
>
{paymentMethods?.map((item) => {
return (
<div key={item.mark}>
<RadioGroupItem value={item.mark} id={item.mark} className='peer sr-only' />
<Label
htmlFor={item.mark}
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary flex flex-col items-center justify-between rounded-md border-2 py-2'
>
<div className='mb-3 size-12'>
<Image
src={item.icon || `/payment/${item.mark}.svg`}
width={48}
height={48}
alt={item.name!}
/>
</div>
<span className='w-full overflow-hidden text-ellipsis whitespace-nowrap text-center'>
{item.name || t(`methods.${item.mark}`)}
</span>
</Label>
</div>
);
})}
</RadioGroup>
</div>
<Button
className='fixed bottom-0 left-0 w-full rounded-none md:relative md:mt-6'
disabled={loading}
onClick={async () => {
startTransition(async () => {
try {
const response = await purchase(params);
const orderNo = response.data.data?.order_no;
if (orderNo) {
const { data } = await checkoutOrder({
orderNo,
});
const type = data.data?.type;
const checkout_url = data.data?.checkout_url;
if (type === 'link') {
const width = 600;
const height = 800;
const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2;
window.open(
checkout_url,
'newWindow',
`width=${width},height=${height},top=${top},left=${left},menubar=0,scrollbars=1,resizable=1,status=1,titlebar=0,toolbar=0,location=1`,
);
}
getUserInfo();
router.push(`/payment?order_no=${orderNo}`);
}
} catch (error) {
console.log(error);
}
});
}}
>
{loading && <LoaderCircle className='mr-2 animate-spin' />}
{t('buyNow')}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}

View File

@ -1,236 +0,0 @@
'use client';
import useGlobalStore from '@/config/use-global';
import { checkoutOrder, preCreateOrder, renewal } from '@/services/user/order';
import { getAvailablePaymentMethods } from '@/services/user/payment';
import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Card, CardContent } from '@workspace/ui/components/card';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@workspace/ui/components/dialog';
import { Input } from '@workspace/ui/components/input';
import { Label } from '@workspace/ui/components/label';
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
import { Separator } from '@workspace/ui/components/separator';
import { LoaderCircle } from 'lucide-react';
import { useTranslations } from 'next-intl';
import Image from 'next/legacy/image';
import { useRouter } from 'next/navigation';
import { useEffect, useState, useTransition } from 'react';
import { SubscribeBilling } from '../subscribe/billing';
import { SubscribeDetail } from '../subscribe/detail';
export default function Renewal({ token, subscribe }: { token: string; subscribe: API.Subscribe }) {
const t = useTranslations('order');
const { getUserInfo } = useGlobalStore();
const [open, setOpen] = useState<boolean>(false);
const router = useRouter();
const [params, setParams] = useState<API.RenewalOrderRequest>({
quantity: 1,
subscribe_id: subscribe.id,
payment: 'balance',
coupon: '',
subscribe_token: token,
});
const [loading, startTransition] = useTransition();
const { data: order } = useQuery({
queryKey: ['preCreateOrder', params],
queryFn: async () => {
const { data } = await preCreateOrder({
...params,
subscribe_id: subscribe.id,
});
return data.data;
},
enabled: !!subscribe.id && open,
});
const { data: paymentMethods } = useQuery({
queryKey: ['getAvailablePaymentMethods'],
queryFn: async () => {
const { data } = await getAvailablePaymentMethods();
return data.data?.list || [];
},
});
useEffect(() => {
if (subscribe.id && token) {
setParams((prev) => ({
...prev,
quantity: 1,
subscribe_id: subscribe.id,
subscribe_token: token,
}));
}
}, [subscribe.id, token]);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button size='sm'>{t('renew')}</Button>
</DialogTrigger>
<DialogContent className='flex h-full max-w-screen-lg flex-col overflow-hidden md:h-auto'>
<DialogHeader>
<DialogTitle>{t('renewSubscription')}</DialogTitle>
</DialogHeader>
<div className='grid w-full gap-3 lg:grid-cols-2'>
<Card className='border-transparent shadow-none md:border-inherit md:shadow'>
<CardContent className='grid gap-3 p-0 text-sm md:p-6'>
<SubscribeDetail
subscribe={{
...subscribe,
quantity: params.quantity,
}}
/>
<Separator />
<SubscribeBilling
order={{
...order,
quantity: params.quantity,
unit_price: subscribe?.unit_price,
}}
/>
</CardContent>
</Card>
<div className='flex flex-col justify-between text-sm'>
<div className='grid gap-3'>
<div className='font-semibold'>{t('purchaseDuration')}</div>
<RadioGroup
value={String(params.quantity)}
onValueChange={(value) => {
setParams({
...params,
quantity: Number(value),
});
}}
className='flex flex-wrap gap-2'
>
{subscribe?.unit_time !== 'Minute' && (
<div className='relative'>
<RadioGroupItem value='1' id='1' className='peer sr-only' />
<Label
htmlFor='1'
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary relative flex h-full flex-col items-center justify-center gap-2 rounded-md border-2 p-2'
>
1 / {t(subscribe?.unit_time || 'Month')}
</Label>
</div>
)}
{subscribe?.discount?.map((item) => (
<div key={item.quantity}>
<RadioGroupItem
value={String(item.quantity)}
id={String(item.quantity)}
className='peer sr-only'
/>
<Label
htmlFor={String(item.quantity)}
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary relative flex h-full flex-col items-center justify-center gap-2 rounded-md border-2 p-2'
>
{item.quantity} / {t(subscribe?.unit_time || 'Month')}
{item.discount < 100 && (
<Badge variant='destructive'>-{100 - item.discount}%</Badge>
)}
</Label>
</div>
))}
</RadioGroup>
<div className='flex'>
<Input
placeholder={t('enterCoupon')}
value={params.coupon}
onChange={(e) => {
setParams({
...params,
coupon: e.target.value.trim(),
});
}}
/>
</div>
<div className='font-semibold'>{t('paymentMethod')}</div>
<RadioGroup
className='grid grid-cols-5 gap-2'
value={params.payment}
onValueChange={(value) => {
setParams({
...params,
payment: value,
});
}}
>
{paymentMethods?.map((item) => {
return (
<div key={item.mark}>
<RadioGroupItem value={item.mark} id={item.mark} className='peer sr-only' />
<Label
htmlFor={item.mark}
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary flex flex-col items-center justify-between rounded-md border-2 py-2'
>
<div className='mb-3 size-12'>
<Image
src={item.icon || `/payment/${item.mark}.svg`}
width={48}
height={48}
alt={item.name!}
/>
</div>
<span className='w-full overflow-hidden text-ellipsis whitespace-nowrap text-center'>
{item.name || t(`methods.${item.mark}`)}
</span>
</Label>
</div>
);
})}
</RadioGroup>
</div>
<Button
className='fixed bottom-0 left-0 w-full rounded-none md:relative md:mt-6'
disabled={loading}
onClick={async () => {
startTransition(async () => {
try {
const response = await renewal(params);
const orderNo = response.data.data?.order_no;
if (orderNo) {
const { data } = await checkoutOrder({
orderNo,
});
const type = data.data?.type;
const checkout_url = data.data?.checkout_url;
if (type === 'link') {
const width = 600;
const height = 800;
const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2;
window.open(
checkout_url,
'newWindow',
`width=${width},height=${height},top=${top},left=${left},menubar=0,scrollbars=1,resizable=1,status=1,titlebar=0,toolbar=0,location=1`,
);
}
getUserInfo();
router.push(`/payment?order_no=${orderNo}`);
}
} catch (error) {
console.log(error);
}
});
}}
>
{loading && <LoaderCircle className='mr-2 animate-spin' />}
{t('buyNow')}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}

View File

@ -1,6 +1,8 @@
'use client';
import { Display } from '@/components/display';
import { SubscribeBilling } from '@/components/subscribe/billing';
import { SubscribeDetail } from '@/components/subscribe/detail';
import useGlobalStore from '@/config/use-global';
import { checkoutOrder, queryOrderDetail } from '@/services/user/order';
import { Icon } from '@iconify/react';
@ -22,9 +24,6 @@ import { useTranslations } from 'next-intl';
import Link from 'next/link';
import { QRCodeCanvas } from 'qrcode.react';
import { useEffect, useState } from 'react';
import { SubscribeBilling } from '../subscribe/billing';
import { SubscribeDetail } from '../subscribe/detail';
import StripePayment from './stripe';
export default function Page() {

View File

@ -1,6 +1,7 @@
'use client';
import { Display } from '@/components/display';
import Recharge from '@/components/subscribe/recharge';
import useGlobalStore from '@/config/use-global';
import { Icon } from '@iconify/react';
import { Button } from '@workspace/ui/components/button';
@ -16,7 +17,6 @@ import { isBrowser } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import CopyToClipboard from 'react-copy-to-clipboard';
import { toast } from 'sonner';
import Recharge from './order/recharge';
export function SidebarRight({ ...props }: React.ComponentProps<typeof Sidebar>) {
const { user } = useGlobalStore();

View File

@ -13,8 +13,8 @@ import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { Empty } from '@/components/empty';
import Purchase from '../order/purchase';
import { SubscribeDetail } from './detail';
import { SubscribeDetail } from '@/components/subscribe/detail';
import Purchase from '@/components/subscribe/purchase';
export default function Page() {
const t = useTranslations('subscribe');
@ -112,7 +112,7 @@ export default function Page() {
<SubscribeDetail
subscribe={{
...item,
name: null,
name: undefined,
}}
/>
</CardContent>

View File

@ -9,8 +9,8 @@ import { useTranslations } from 'next-intl';
import { useRef } from 'react';
import { Empty } from '@/components/empty';
import Recharge from '@/components/subscribe/recharge';
import { formatDate } from '@workspace/ui/utils';
import Recharge from '../order/recharge';
export default function Page() {
const t = useTranslations('wallet');

View File

@ -1,7 +1,7 @@
'use client';
import { SubscribeDetail } from '@/app/(main)/(user)/subscribe/detail';
import { Display } from '@/components/display';
import { SubscribeDetail } from '@/components/subscribe/detail';
import { getSubscription } from '@/services/common/common';
import { Icon } from '@iconify/react';
import { useQuery } from '@tanstack/react-query';
@ -112,7 +112,7 @@ export function ProductShowcase() {
<SubscribeDetail
subscribe={{
...item,
name: null,
name: undefined,
}}
/>
</CardContent>

View File

@ -4,22 +4,17 @@ import { Display } from '@/components/display';
import { Separator } from '@workspace/ui/components/separator';
import { useTranslations } from 'next-intl';
interface SubscribeBillingProps {
order?: {
type?: number;
subscribe_id?: number;
quantity?: number;
price?: number;
discount?: number;
coupon_discount?: number;
fee_amount?: number;
amount?: number;
unit_price?: number;
unit_time?: number;
};
}
export function SubscribeBilling({ order }: SubscribeBillingProps) {
export function SubscribeBilling({
order,
}: {
order?: Partial<
API.OrderDetail & {
unit_price: number;
unit_time: number;
subscribe_discount: number;
}
>;
}) {
const t = useTranslations('subscribe');
return (
@ -52,6 +47,14 @@ export function SubscribeBilling({ order }: SubscribeBillingProps) {
<Display type='currency' value={order?.coupon_discount} />
</span>
</li>
{order?.subscribe_discount && (
<li>
<span className='text-muted-foreground'>{t('subscriptionDiscount')}</span>
<span>
<Display type='currency' value={order?.subscribe_discount} />
</span>
</li>
)}
<li>
<span className='text-muted-foreground'>{t('billing.fee')}</span>
<span>

View File

@ -0,0 +1,27 @@
'use client';
import { Input } from '@workspace/ui/components/input';
import { useTranslations } from 'next-intl';
import React from 'react';
interface CouponInputProps {
coupon?: string;
onChange: (value: string) => void;
}
const CouponInput: React.FC<CouponInputProps> = ({ coupon, onChange }) => {
const t = useTranslations('subscribe');
return (
<>
<div className='font-semibold'>{t('coupon')}</div>
<Input
placeholder={t('enterCoupon')}
value={coupon}
onChange={(e) => onChange(e.target.value.trim())}
/>
</>
);
};
export default CouponInput;

View File

@ -3,18 +3,16 @@
import { Display } from '@/components/display';
import { useTranslations } from 'next-intl';
interface SubscribeDetailProps {
subscribe?: {
traffic?: number | null;
speed_limit?: number | null;
device_limit?: number | null;
name?: string | null;
quantity?: number | null;
unit_price?: number | null;
};
}
export function SubscribeDetail({ subscribe }: SubscribeDetailProps) {
export function SubscribeDetail({
subscribe,
}: {
subscribe?: Partial<
API.Subscribe & {
name: string;
quantity: number;
}
>;
}) {
const t = useTranslations('subscribe.detail');
return (

View File

@ -0,0 +1,69 @@
'use client';
import { Badge } from '@workspace/ui/components/badge';
import { Label } from '@workspace/ui/components/label';
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
import { useTranslations } from 'next-intl';
import React, { useCallback } from 'react';
interface DurationSelectorProps {
quantity: number;
unitTime?: string;
discounts?: Array<{ quantity: number; discount: number }>;
onChange: (value: number) => void;
}
const DurationSelector: React.FC<DurationSelectorProps> = ({
quantity,
unitTime = 'Month',
discounts = [],
onChange,
}) => {
const t = useTranslations('subscribe');
const handleChange = useCallback(
(value: string) => {
onChange(Number(value));
},
[onChange],
);
const DurationOption: React.FC<{ value: string; label: string; discount?: number }> = ({
value,
label,
discount,
}) => (
<div className='relative'>
<RadioGroupItem value={value} id={value} className='peer sr-only' />
<Label
htmlFor={value}
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary relative flex h-full flex-col items-center justify-center gap-2 rounded-md border-2 p-2'
>
{label}
{discount && <Badge variant='destructive'>-{discount}%</Badge>}
</Label>
</div>
);
return (
<>
<div className='font-semibold'>{t('purchaseDuration')}</div>
<RadioGroup
value={String(quantity)}
onValueChange={handleChange}
className='flex flex-wrap gap-3'
>
{unitTime !== 'Minute' && <DurationOption value='1' label={`1 / ${t(unitTime)}`} />}
{discounts?.map((item) => (
<DurationOption
key={item.quantity}
value={String(item.quantity)}
label={`${item.quantity} / ${t(unitTime)}`}
discount={100 - item.discount}
/>
))}
</RadioGroup>
</>
);
};
export default DurationSelector;

View File

@ -0,0 +1,56 @@
'use client';
import { getAvailablePaymentMethods } from '@/services/user/payment';
import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
import React, { memo } from 'react';
interface PaymentMethodsProps {
value: string;
onChange: (value: string) => void;
}
const PaymentMethods: React.FC<PaymentMethodsProps> = ({ value, onChange }) => {
const t = useTranslations('subscribe');
const { data } = useQuery({
queryKey: ['getAvailablePaymentMethods'],
queryFn: async () => {
const { data } = await getAvailablePaymentMethods();
return data.data?.list || [];
},
});
return (
<>
<div className='font-semibold'>{t('paymentMethod')}</div>
<RadioGroup className='mb-6 grid grid-cols-5 gap-2' value={value} onValueChange={onChange}>
{data?.map((item) => (
<div key={item.mark}>
<RadioGroupItem value={item.mark} id={item.mark} className='peer sr-only' />
<Label
htmlFor={item.mark}
className='border-muted bg-popover hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary flex flex-col items-center justify-between rounded-md border-2 py-2'
>
<div className='mb-3 size-12'>
<Image
src={item.icon || `/payment/${item.mark}.svg`}
width={48}
height={48}
alt={item.name || t(`methods.${item.mark}`)}
/>
</div>
<span className='w-full overflow-hidden text-ellipsis whitespace-nowrap text-center'>
{item.name || t(`methods.${item.mark}`)}
</span>
</Label>
</div>
))}
</RadioGroup>
</>
);
};
export default memo(PaymentMethods);

View File

@ -0,0 +1,170 @@
'use client';
import CouponInput from '@/components/subscribe/coupon-input';
import DurationSelector from '@/components/subscribe/duration-selector';
import PaymentMethods from '@/components/subscribe/payment-methods';
import SubscribeSelector from '@/components/subscribe/subscribe-selector';
import useGlobalStore from '@/config/use-global';
import { checkoutOrder, preCreateOrder, purchase } from '@/services/user/order';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { Card, CardContent } from '@workspace/ui/components/card';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@workspace/ui/components/dialog';
import { Separator } from '@workspace/ui/components/separator';
import { LoaderCircle } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect, useState, useTransition } from 'react';
import { SubscribeBilling } from './billing';
import { SubscribeDetail } from './detail';
export default function Purchase({
subscribe,
setSubscribe,
}: {
subscribe?: API.Subscribe;
setSubscribe: (subscribe?: API.Subscribe) => void;
}) {
const t = useTranslations('subscribe');
const { getUserInfo } = useGlobalStore();
const router = useRouter();
const [params, setParams] = useState<Partial<API.PurchaseOrderRequest>>({
quantity: 1,
subscribe_id: 0,
payment: 'balance',
coupon: '',
});
const [loading, startTransition] = useTransition();
const { data: order } = useQuery({
enabled: !!subscribe?.id,
queryKey: ['preCreateOrder', params],
queryFn: async () => {
const { data } = await preCreateOrder({
...params,
subscribe_id: subscribe?.id as number,
} as API.PurchaseOrderRequest);
return data.data;
},
});
useEffect(() => {
if (subscribe) {
setParams((prev) => ({
...prev,
quantity: 1,
subscribe_id: subscribe?.id,
}));
}
}, [subscribe]);
const handleChange = useCallback((field: keyof typeof params, value: string | number) => {
setParams((prev) => ({
...prev,
[field]: value,
}));
}, []);
const handleSubmit = useCallback(async () => {
startTransition(async () => {
try {
const response = await purchase(params as API.PurchaseOrderRequest);
const orderNo = response.data.data?.order_no;
if (orderNo) {
const { data } = await checkoutOrder({
orderNo,
});
const type = data.data?.type;
const checkout_url = data.data?.checkout_url;
if (type === 'link') {
const width = 600;
const height = 800;
const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2;
window.open(
checkout_url,
'newWindow',
`width=${width},height=${height},top=${top},left=${left},menubar=0,scrollbars=1,resizable=1,status=1,titlebar=0,toolbar=0,location=1`,
);
}
getUserInfo();
router.push(`/payment?order_no=${orderNo}`);
}
} catch (error) {
console.log(error);
}
});
}, [params, router]);
return (
<Dialog
open={!!subscribe?.id}
onOpenChange={(open) => {
if (!open) setSubscribe(undefined);
}}
>
<DialogContent className='flex h-full max-w-screen-lg flex-col overflow-hidden border-none p-0 md:h-auto'>
<DialogHeader className='p-6 pb-0'>
<DialogTitle>{t('buySubscription')}</DialogTitle>
</DialogHeader>
<div className='grid w-full flex-grow gap-3 overflow-auto p-6 pt-0 lg:grid-cols-2'>
<Card className='border-transparent shadow-none md:border-inherit md:shadow'>
<CardContent className='grid gap-3 p-0 text-sm md:p-6'>
<SubscribeDetail
subscribe={{
...subscribe,
quantity: params.quantity,
}}
/>
<Separator />
<SubscribeBilling
order={{
...order,
quantity: params.quantity,
unit_price: subscribe?.unit_price,
}}
/>
</CardContent>
</Card>
<div className='flex flex-col justify-between text-sm'>
<div className='grid gap-3'>
<DurationSelector
quantity={params.quantity!}
unitTime={subscribe?.unit_time}
discounts={subscribe?.discount}
onChange={(value) => {
handleChange('quantity', value);
}}
/>
<CouponInput
coupon={params.coupon}
onChange={(value) => handleChange('coupon', value)}
/>
<SubscribeSelector
value={params.discount_subscribe_id}
data={order?.discount_list || []}
onChange={(value) => {
handleChange('discount_subscribe_id', value);
}}
/>
<PaymentMethods
value={params.payment!}
onChange={(value) => {
handleChange('payment', value);
}}
/>
</div>
<Button
className='fixed bottom-0 left-0 w-full rounded-none md:relative md:mt-6'
disabled={loading}
onClick={handleSubmit}
>
{loading && <LoaderCircle className='mr-2 animate-spin' />}
{t('buyNow')}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}

View File

@ -24,7 +24,7 @@ import { useRouter } from 'next/navigation';
import { useEffect, useState, useTransition } from 'react';
export default function Recharge(props: ButtonProps) {
const t = useTranslations('order');
const t = useTranslations('subscribe');
const { common } = useGlobalStore();
const { currency } = common;
@ -62,7 +62,7 @@ export default function Recharge(props: ButtonProps) {
<DialogContent className='flex h-full flex-col overflow-hidden md:h-auto'>
<DialogHeader>
<DialogTitle>{t('balanceRecharge')}</DialogTitle>
<DialogDescription>{t('description')}</DialogDescription>
<DialogDescription>{t('rechargeDescription')}</DialogDescription>
</DialogHeader>
<div className='flex flex-col justify-between text-sm'>
<div className='grid gap-3'>

View File

@ -0,0 +1,171 @@
'use client';
import CouponInput from '@/components/subscribe/coupon-input';
import DurationSelector from '@/components/subscribe/duration-selector';
import PaymentMethods from '@/components/subscribe/payment-methods';
import SubscribeSelector from '@/components/subscribe/subscribe-selector';
import useGlobalStore from '@/config/use-global';
import { checkoutOrder, preCreateOrder, renewal } from '@/services/user/order';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { Card, CardContent } from '@workspace/ui/components/card';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@workspace/ui/components/dialog';
import { Separator } from '@workspace/ui/components/separator';
import { LoaderCircle } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect, useState, useTransition } from 'react';
import { SubscribeBilling } from './billing';
import { SubscribeDetail } from './detail';
export default function Renewal({ token, subscribe }: { token: string; subscribe: API.Subscribe }) {
const t = useTranslations('subscribe');
const { getUserInfo } = useGlobalStore();
const [open, setOpen] = useState<boolean>(false);
const router = useRouter();
const [params, setParams] = useState<Partial<API.RenewalOrderRequest>>({
quantity: 1,
subscribe_id: subscribe.id,
payment: 'balance',
coupon: '',
subscribe_token: token,
});
const [loading, startTransition] = useTransition();
const { data: order } = useQuery({
enabled: !!subscribe.id && open,
queryKey: ['preCreateOrder', params],
queryFn: async () => {
const { data } = await preCreateOrder({
...params,
subscribe_id: subscribe.id,
} as API.PurchaseOrderRequest);
return data.data;
},
});
useEffect(() => {
if (subscribe.id && token) {
setParams((prev) => ({
...prev,
quantity: 1,
subscribe_id: subscribe.id,
subscribe_token: token,
}));
}
}, [subscribe.id, token]);
const handleChange = useCallback((field: keyof typeof params, value: string | number) => {
setParams((prev) => ({
...prev,
[field]: value,
}));
}, []);
const handleSubmit = useCallback(async () => {
startTransition(async () => {
try {
const response = await renewal(params as API.RenewalOrderRequest);
const orderNo = response.data.data?.order_no;
if (orderNo) {
const { data } = await checkoutOrder({
orderNo,
});
const type = data.data?.type;
const checkout_url = data.data?.checkout_url;
if (type === 'link') {
const width = 600;
const height = 800;
const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2;
window.open(
checkout_url,
'newWindow',
`width=${width},height=${height},top=${top},left=${left},menubar=0,scrollbars=1,resizable=1,status=1,titlebar=0,toolbar=0,location=1`,
);
}
getUserInfo();
router.push(`/payment?order_no=${orderNo}`);
}
} catch (error) {
console.log(error);
}
});
}, [params, router]);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button size='sm'>{t('renew')}</Button>
</DialogTrigger>
<DialogContent className='flex h-full max-w-screen-lg flex-col overflow-hidden md:h-auto'>
<DialogHeader>
<DialogTitle>{t('renewSubscription')}</DialogTitle>
</DialogHeader>
<div className='grid w-full gap-3 lg:grid-cols-2'>
<Card className='border-transparent shadow-none md:border-inherit md:shadow'>
<CardContent className='grid gap-3 p-0 text-sm md:p-6'>
<SubscribeDetail
subscribe={{
...subscribe,
quantity: params.quantity,
}}
/>
<Separator />
<SubscribeBilling
order={{
...order,
quantity: params.quantity,
unit_price: subscribe?.unit_price,
}}
/>
</CardContent>
</Card>
<div className='flex flex-col justify-between text-sm'>
<div className='grid gap-3'>
<DurationSelector
quantity={params.quantity!}
unitTime={subscribe?.unit_time}
discounts={subscribe?.discount}
onChange={(value) => {
handleChange('quantity', value);
}}
/>
<CouponInput
coupon={params.coupon}
onChange={(value) => handleChange('coupon', value)}
/>
<SubscribeSelector
value={params.discount_subscribe_id}
data={order?.discount_list || []}
onChange={(value) => {
handleChange('discount_subscribe_id', value);
}}
/>
<PaymentMethods
value={params.payment!}
onChange={(value) => {
handleChange('payment', value);
}}
/>
</div>
<Button
className='fixed bottom-0 left-0 w-full rounded-none md:relative md:mt-6'
disabled={loading}
onClick={handleSubmit}
>
{loading && <LoaderCircle className='mr-2 animate-spin' />}
{t('buyNow')}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}

View File

@ -31,7 +31,7 @@ export default function ResetTraffic({
token: string;
replacement?: number;
}) {
const t = useTranslations('order');
const t = useTranslations('subscribe');
const { getUserInfo } = useGlobalStore();
const [open, setOpen] = useState<boolean>(false);
const router = useRouter();

View File

@ -0,0 +1,78 @@
'use client';
import { Display } from '@/components/display';
import useGlobalStore from '@/config/use-global';
import { Combobox } from '@workspace/ui/custom-components/combobox';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useCallback, useEffect, useMemo } from 'react';
interface SubscribeSelectorProps {
value?: number;
data: API.SubscribeDiscountInfo[];
onChange: (value: number) => void;
}
const SubscribeSelector: React.FC<SubscribeSelectorProps> = ({ value, data, onChange }) => {
const t = useTranslations('subscribe');
const { common } = useGlobalStore();
const singleModel = common.subscribe.single_model;
useEffect(() => {
if (singleModel && data.length > 0 && data[0]) {
onChange(data[0].id);
}
}, [data, singleModel, onChange, value]);
const handleChange = useCallback(
(selectedValue: number) => {
if (singleModel) {
if (selectedValue) {
onChange(selectedValue);
}
} else {
onChange(selectedValue);
}
},
[singleModel, onChange],
);
const options = useMemo(() => {
return data.map((item) => ({
children: (
<div className='flex w-full items-center justify-between px-2 py-1.5'>
<div className='mr-2 flex flex-col overflow-hidden'>
<span className='truncate text-sm font-medium'>{item.name}</span>
<time
className='text-muted-foreground truncate text-xs'
title={formatDate(new Date(item.expire_time))}
>
{formatDate(new Date(item.expire_time), false)}
</time>
</div>
<span className='text-muted-foreground flex-shrink-0 text-sm' title='Price'>
<Display value={item.price} type='currency' />
</span>
</div>
),
label: item.name,
value: item.id,
}));
}, [data]);
if (!data.length) return null;
return (
<>
<div className='font-semibold'>{t('subscriptionDiscount')}</div>
<Combobox<number, false>
placeholder={t('selectSubscription')}
options={options}
value={value}
onChange={handleChange}
/>
</>
);
};
export default SubscribeSelector;

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Tato aplikace momentálně nepodporuje spuštění, prosím importujte ručně, adresa předplatného byla automaticky zkopírována",
"mySubscriptions": "Moje předplatné",
"nextResetDays": "Příští reset/den",
"noLimit": "Bez omezení",
"prompt": "Výzva",
"purchaseSubscription": "Zakoupit předplatné",
"qrCode": "QR kód",

View File

@ -1,21 +1,10 @@
{
"Day": "Den",
"Hour": "Hodina",
"Minute": "Minuta",
"Month": "Měsíc",
"Year": "Rok",
"balanceRecharge": "Doplnění zůstatku",
"buyNow": "Koupit nyní",
"buySubscription": "Koupit předplatné",
"cancel": "Zrušit",
"createdAt": "Datum vytvoření",
"description": "Jedním kliknutím dobijete, snadno a rychle",
"detail": "Detail",
"enterAmount": "Zadejte částku k dobití",
"enterCoupon": "Zadejte slevový kód",
"goToPayment": "Přejít k platbě",
"methods": {
"alipay_f2f": "Alipay (tváří v tvář)",
"alipay_f2f": "Alipay (Tváří v tvář)",
"balance": "Zůstatek",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -31,16 +20,6 @@
"paymentMethod": "Platební metoda",
"paymentSuccess": "Platba úspěšná",
"productList": "Seznam produktů",
"purchaseDuration": "Doba nákupu",
"recharge": "dobít",
"rechargeAmount": "Částka dobití",
"rechargeNow": "Dobít nyní",
"renew": "Obnovit",
"renewSubscription": "Obnovit předplatné",
"resetPrice": "Obnovit cenu",
"resetTraffic": "Obnovit přenos dat",
"resetTrafficDescription": "Obnoví se pouze měsíční přenos dat",
"resetTrafficTitle": "Obnovit přenos dat",
"scanToPay": "Prosím, naskenujte kód pro platbu",
"status": {
"0": "Stav",

View File

@ -3,8 +3,10 @@
"Hour": "Hodina",
"Minute": "Minuta",
"Month": "Měsíc",
"NoLimit": "Bez omezení",
"Year": "Rok",
"all": "Vše",
"balanceRecharge": "Dobití zůstatku",
"billing": {
"billingTitle": "Faktura za zboží",
"couponDiscount": "Sleva z kupónu",
@ -15,13 +17,18 @@
"total": "Celková cena"
},
"buy": "Koupit",
"buyNow": "Koupit nyní",
"buySubscription": "Koupit předplatné",
"category": "Kategorie",
"coupon": "Kupón",
"detail": {
"availableTraffic": "Dostupný provoz",
"connectedDevices": "Počet současně připojených IP",
"connectionSpeed": "Rychlost připojení",
"productDetail": "Detaily produktu"
},
"enterAmount": "Zadejte částku dobití",
"enterCoupon": "Zadejte kód kupónu",
"methods": {
"alipay_f2f": "Alipay (tváří v tvář)",
"balance": "Zůstatek",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Platební metoda",
"productDescription": "Popis produktu",
"products": "Produkty"
"products": "Produkty",
"purchaseDuration": "Doba nákupu",
"recharge": "Dobít",
"rechargeAmount": "Částka dobití",
"rechargeDescription": "Jedním kliknutím dobijete, snadné ovládání",
"rechargeNow": "Dobít nyní",
"renew": "Obnovit",
"renewSubscription": "Obnovit předplatné",
"resetPrice": "Obnovit cenu",
"resetTraffic": "Obnovit provoz",
"resetTrafficDescription": "Obnovit provoz pouze pro aktuální měsíc",
"resetTrafficTitle": "Obnovit provoz",
"selectSubscription": "Vyberte předplatné",
"subscriptionDiscount": "Sleva na předplatné"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Diese App unterstützt derzeit keine Aktivierung. Bitte manuell importieren, die Abonnementadresse wurde automatisch kopiert.",
"mySubscriptions": "Meine Abonnements",
"nextResetDays": "Nächster Reset/Tage",
"noLimit": "Kein Limit",
"prompt": "Aufforderung",
"purchaseSubscription": "Abonnement kaufen",
"qrCode": "QR-Code",

View File

@ -1,23 +1,12 @@
{
"Day": "Tag",
"Hour": "Stunde",
"Minute": "Minute",
"Month": "Monat",
"Year": "Jahr",
"balanceRecharge": "Guthaben aufladen",
"buyNow": "Jetzt kaufen",
"buySubscription": "Abonnement kaufen",
"cancel": "Abbrechen",
"createdAt": "Erstellungszeitpunkt",
"description": "Mit einem Klick aufladen, ganz einfach erledigt",
"detail": "Einzelheiten",
"enterAmount": "Bitte geben Sie den Aufladebetrag ein",
"enterCoupon": "Bitte geben Sie den Rabattcode ein",
"goToPayment": "Zur Zahlung gehen",
"methods": {
"alipay_f2f": "Alipay (Face-to-Face)",
"alipay_f2f": "Alipay (Face to Face)",
"balance": "Guthaben",
"epay": "E-Pay",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
@ -31,16 +20,6 @@
"paymentMethod": "Zahlungsmethode",
"paymentSuccess": "Zahlung erfolgreich",
"productList": "Produktliste",
"purchaseDuration": "Kaufdauer",
"recharge": "Aufladen",
"rechargeAmount": "Aufladebetrag",
"rechargeNow": "Jetzt aufladen",
"renew": "Erneuern",
"renewSubscription": "Abonnement verlängern",
"resetPrice": "Preis zurücksetzen",
"resetTraffic": "Datenverkehr zurücksetzen",
"resetTrafficDescription": "Setzt nur den Datenverkehr des aktuellen Monats zurück",
"resetTrafficTitle": "Datenverkehr zurücksetzen",
"scanToPay": "Bitte scannen Sie zum Bezahlen",
"status": {
"0": "Status",

View File

@ -3,8 +3,10 @@
"Hour": "Stunde",
"Minute": "Minute",
"Month": "Monat",
"NoLimit": "Kein Limit",
"Year": "Jahr",
"all": "Alle",
"balanceRecharge": "Guthaben aufladen",
"billing": {
"billingTitle": "Produktrechnung",
"couponDiscount": "Rabattcode-Rabatt",
@ -15,13 +17,18 @@
"total": "Gesamtpreis"
},
"buy": "Kaufen",
"buyNow": "Jetzt kaufen",
"buySubscription": "Abonnement kaufen",
"category": "Kategorie",
"coupon": "Gutschein",
"detail": {
"availableTraffic": "Verfügbares Datenvolumen",
"connectedDevices": "Gleichzeitig verbundene IP-Anzahl",
"connectionSpeed": "Verbindungsgeschwindigkeit",
"productDetail": "Produktdetails"
},
"enterAmount": "Geben Sie den Aufladebetrag ein",
"enterCoupon": "Gutscheincode eingeben",
"methods": {
"alipay_f2f": "Alipay (Face-to-Face)",
"balance": "Guthaben",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Zahlungsmethode",
"productDescription": "Produktbeschreibung",
"products": "Produkte"
"products": "Produkte",
"purchaseDuration": "Kaufdauer",
"recharge": "Aufladen",
"rechargeAmount": "Aufladebetrag",
"rechargeDescription": "Ein-Klick-Aufladung, einfach zu handhaben",
"rechargeNow": "Jetzt aufladen",
"renew": "Erneuern",
"renewSubscription": "Abonnement erneuern",
"resetPrice": "Preis zurücksetzen",
"resetTraffic": "Datenverkehr zurücksetzen",
"resetTrafficDescription": "Verkehr nur für den aktuellen Monat zurücksetzen",
"resetTrafficTitle": "Datenverkehr zurücksetzen",
"selectSubscription": "Abonnement auswählen",
"subscriptionDiscount": "Abonnementrabatt"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "This app does not support activation. Please import manually. The subscription address has been copied.",
"mySubscriptions": "My Subscriptions",
"nextResetDays": "Next Reset in Days",
"noLimit": "No Limit",
"prompt": "Prompt",
"purchaseSubscription": "Purchase Subscription",
"qrCode": "QR Code",

View File

@ -1,18 +1,7 @@
{
"Day": "Day",
"Hour": "Hour",
"Minute": "Minute",
"Month": "Month",
"Year": "Year",
"balanceRecharge": "Balance Recharge",
"buyNow": "Buy Now",
"buySubscription": "Buy Subscription",
"cancel": "Cancel",
"createdAt": "Created At",
"description": "One-click recharge, easy to handle",
"detail": "Detail",
"enterAmount": "Enter recharge amount",
"enterCoupon": "Enter Coupon Code",
"goToPayment": "Go to Payment",
"methods": {
"alipay_f2f": "Alipay (Face to Face)",
@ -31,16 +20,6 @@
"paymentMethod": "Payment Method",
"paymentSuccess": "Payment Success",
"productList": "Product List",
"purchaseDuration": "Purchase Duration",
"recharge": "Recharge",
"rechargeAmount": "Recharge Amount",
"rechargeNow": "Recharge Now",
"renew": "Renew",
"renewSubscription": "Renew Subscription",
"resetPrice": "Reset Price",
"resetTraffic": "Reset Traffic",
"resetTrafficDescription": "Reset traffic for the current month only",
"resetTrafficTitle": "Reset Traffic",
"scanToPay": "Scan to Pay",
"status": {
"0": "Status",

View File

@ -3,8 +3,10 @@
"Hour": "Hour",
"Minute": "Minute",
"Month": "Month",
"NoLimit": "No Limit",
"Year": "Year",
"all": "All",
"balanceRecharge": "Balance Recharge",
"billing": {
"billingTitle": "Product Billing",
"couponDiscount": "Coupon Discount",
@ -15,13 +17,18 @@
"total": "Total"
},
"buy": "Buy",
"buyNow": "Buy Now",
"buySubscription": "Buy Subscription",
"category": "Category",
"coupon": "Coupon",
"detail": {
"availableTraffic": "Available Traffic",
"connectedDevices": "Connected Devices",
"connectionSpeed": "Connection Speed",
"productDetail": "Product Details"
},
"enterAmount": "Enter recharge amount",
"enterCoupon": "Enter Coupon Code",
"methods": {
"alipay_f2f": "Alipay (Face to Face)",
"balance": "Balance",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Payment Method",
"productDescription": "Product Description",
"products": "Products"
"products": "Products",
"purchaseDuration": "Purchase Duration",
"recharge": "Recharge",
"rechargeAmount": "Recharge Amount",
"rechargeDescription": "One-click recharge, easy to handle",
"rechargeNow": "Recharge Now",
"renew": "Renew",
"renewSubscription": "Renew Subscription",
"resetPrice": "Reset Price",
"resetTraffic": "Reset Traffic",
"resetTrafficDescription": "Reset traffic for the current month only",
"resetTrafficTitle": "Reset Traffic",
"selectSubscription": "Select Subscription",
"subscriptionDiscount": "Subscription Discount"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Esta aplicación no admite la activación por el momento. Por favor, importe manualmente. La dirección de suscripción ha sido copiada automáticamente.",
"mySubscriptions": "Mis suscripciones",
"nextResetDays": "Próximo reinicio/días",
"noLimit": "Sin límite",
"prompt": "sugerencia",
"purchaseSubscription": "Comprar suscripción",
"qrCode": "Código QR",

View File

@ -1,21 +1,10 @@
{
"Day": "Día",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"Year": "Año",
"balanceRecharge": "Recarga de saldo",
"buyNow": "Comprar ahora",
"buySubscription": "Comprar suscripción",
"cancel": "Cancelar",
"createdAt": "Fecha de creación",
"description": "Recarga con un clic, fácil y rápido",
"detail": "Detalles",
"enterAmount": "Por favor, introduzca el importe de recarga",
"enterCoupon": "Introduce el código de descuento",
"goToPayment": "Ir a pagar",
"methods": {
"alipay_f2f": "Alipay (cara a cara)",
"alipay_f2f": "Alipay (Cara a Cara)",
"balance": "Saldo",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -28,19 +17,9 @@
"orderNumber": "Número de pedido",
"payment": "Ir a pagar",
"paymentAmount": "Monto de pago",
"paymentMethod": "Método de pago",
"paymentMethod": "Método de Pago",
"paymentSuccess": "Pago exitoso",
"productList": "Lista de productos",
"purchaseDuration": "Duración de la compra",
"recharge": "recargar",
"rechargeAmount": "Monto de recarga",
"rechargeNow": "Recargar ahora",
"renew": "renovar",
"renewSubscription": "Renovar suscripción",
"resetPrice": "Restablecer precio",
"resetTraffic": "Restablecer tráfico",
"resetTrafficDescription": "Solo se restablece el tráfico del mes actual",
"resetTrafficTitle": "Restablecer tráfico",
"scanToPay": "Por favor, escanee para pagar",
"status": {
"0": "estado",

View File

@ -3,8 +3,10 @@
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"NoLimit": "Sin Límite",
"Year": "Año",
"all": "todo",
"balanceRecharge": "Recarga de Saldo",
"billing": {
"billingTitle": "Factura de productos",
"couponDiscount": "Descuento por cupón",
@ -15,13 +17,18 @@
"total": "Precio total"
},
"buy": "Comprar",
"buyNow": "Comprar ahora",
"buySubscription": "Comprar suscripción",
"category": "categoría",
"coupon": "Cupón",
"detail": {
"availableTraffic": "Tráfico disponible",
"connectedDevices": "Número de IPs conectadas simultáneamente",
"connectionSpeed": "Velocidad de conexión",
"productDetail": "Detalles del producto"
},
"enterAmount": "Ingrese el monto de recarga",
"enterCoupon": "Introduce el código de cupón",
"methods": {
"alipay_f2f": "Alipay (cara a cara)",
"balance": "Saldo",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Método de Pago",
"productDescription": "Descripción del producto",
"products": "productos"
"products": "productos",
"purchaseDuration": "Duración de la Compra",
"recharge": "Recargar",
"rechargeAmount": "Monto de Recarga",
"rechargeDescription": "Recarga con un clic, fácil de manejar",
"rechargeNow": "Recargar Ahora",
"renew": "Renovar",
"renewSubscription": "Renovar suscripción",
"resetPrice": "Restablecer Precio",
"resetTraffic": "Restablecer Tráfico",
"resetTrafficDescription": "Restablecer el tráfico solo para el mes actual",
"resetTrafficTitle": "Restablecer Tráfico",
"selectSubscription": "Seleccionar suscripción",
"subscriptionDiscount": "Descuento de Suscripción"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Esta aplicación no admite la activación por el momento, por favor importe manualmente, la dirección de suscripción se ha copiado automáticamente",
"mySubscriptions": "Mis suscripciones",
"nextResetDays": "Próximo reinicio/días",
"noLimit": "Sin Límite",
"prompt": "Sugerencia",
"purchaseSubscription": "Comprar suscripción",
"qrCode": "Código QR",

View File

@ -1,21 +1,10 @@
{
"Day": "Día",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"Year": "Año",
"balanceRecharge": "Recarga de saldo",
"buyNow": "Compra ahora",
"buySubscription": "Comprar suscripción",
"cancel": "Cancelar",
"createdAt": "Fecha de creación",
"description": "Recarga con un clic, fácil y rápido",
"detail": "Detalles",
"enterAmount": "Por favor, ingrese el monto a recargar",
"enterCoupon": "Ingrese el código de descuento",
"goToPayment": "Ir a pagar",
"methods": {
"alipay_f2f": "Alipay (cara a cara)",
"alipay_f2f": "Alipay (Cara a Cara)",
"balance": "Saldo",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -28,19 +17,9 @@
"orderNumber": "Número de pedido",
"payment": "Ir a pagar",
"paymentAmount": "Monto de pago",
"paymentMethod": "Método de pago",
"paymentMethod": "Método de Pago",
"paymentSuccess": "Pago exitoso",
"productList": "Lista de productos",
"purchaseDuration": "Duración de compra",
"recharge": "Recargar",
"rechargeAmount": "Monto de recarga",
"rechargeNow": "Recargar ahora",
"renew": "Renovar",
"renewSubscription": "Renovar suscripción",
"resetPrice": "Restablecer precio",
"resetTraffic": "Restablecer tráfico",
"resetTrafficDescription": "Solo se restablece el tráfico del mes actual",
"resetTrafficTitle": "Restablecer tráfico",
"scanToPay": "Por favor, escanee para pagar",
"status": {
"0": "Estado",

View File

@ -3,8 +3,10 @@
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"NoLimit": "Sin Límite",
"Year": "Año",
"all": "Todo",
"balanceRecharge": "Recarga de Saldo",
"billing": {
"billingTitle": "Factura de Producto",
"couponDiscount": "Descuento de Cupón",
@ -15,13 +17,18 @@
"total": "Total"
},
"buy": "Comprar",
"buyNow": "Comprar Ahora",
"buySubscription": "Comprar Suscripción",
"category": "Categoría",
"coupon": "Cupón",
"detail": {
"availableTraffic": "Tráfico disponible",
"connectedDevices": "Número de IPs conectadas simultáneamente",
"connectionSpeed": "Velocidad de conexión",
"productDetail": "Detalles del producto"
},
"enterAmount": "Ingresa el monto de recarga",
"enterCoupon": "Ingresa el código de cupón",
"methods": {
"alipay_f2f": "Alipay (cara a cara)",
"balance": "Saldo",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Método de Pago",
"productDescription": "Descripción del producto",
"products": "productos"
"products": "productos",
"purchaseDuration": "Duración de la Compra",
"recharge": "Recargar",
"rechargeAmount": "Monto de Recarga",
"rechargeDescription": "Recarga con un clic, fácil de manejar",
"rechargeNow": "Recargar Ahora",
"renew": "Renovar",
"renewSubscription": "Renovar Suscripción",
"resetPrice": "Restablecer Precio",
"resetTraffic": "Restablecer Tráfico",
"resetTrafficDescription": "Restablecer el tráfico solo para el mes actual",
"resetTrafficTitle": "Restablecer Tráfico",
"selectSubscription": "Seleccionar Suscripción",
"subscriptionDiscount": "Descuento por Suscripción"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "این برنامه از فعال‌سازی پشتیبانی نمی‌کند. لطفاً به صورت دستی وارد کنید. آدرس اشتراک کپی شده است.",
"mySubscriptions": "اشتراک‌های من",
"nextResetDays": "روزهای باقی‌مانده تا بازنشانی بعدی",
"noLimit": "بدون محدودیت",
"prompt": "پیشنهاد",
"purchaseSubscription": "خرید اشتراک",
"qrCode": "کد QR",

View File

@ -1,18 +1,7 @@
{
"Day": "روز",
"Hour": "ساعت",
"Minute": "دقیقه",
"Month": "ماه",
"Year": "سال",
"balanceRecharge": "شارژ موجودی",
"buyNow": "خرید کنید",
"buySubscription": "خرید اشتراک",
"cancel": "لغو",
"createdAt": "ایجاد شده در",
"description": "شارژ با یک کلیک، آسان برای استفاده",
"detail": "جزئیات",
"enterAmount": "مبلغ شارژ را وارد کنید",
"enterCoupon": "کد تخفیف را وارد کنید",
"goToPayment": "برو به پرداخت",
"methods": {
"alipay_f2f": "علی‌پی (رو در رو)",
@ -31,16 +20,6 @@
"paymentMethod": "روش پرداخت",
"paymentSuccess": "پرداخت موفق",
"productList": "فهرست محصولات",
"purchaseDuration": "مدت خرید",
"recharge": "شارژ مجدد",
"rechargeAmount": "مبلغ شارژ",
"rechargeNow": "اکنون شارژ کنید",
"renew": "تجدید",
"renewSubscription": "تمدید اشتراک",
"resetPrice": "بازنشانی قیمت",
"resetTraffic": "بازنشانی ترافیک",
"resetTrafficDescription": "بازنشانی ترافیک فقط برای ماه جاری",
"resetTrafficTitle": "بازنشانی ترافیک",
"scanToPay": "اسکن برای پرداخت",
"status": {
"0": "وضعیت",

View File

@ -3,8 +3,10 @@
"Hour": "ساعت",
"Minute": "دقیقه",
"Month": "ماه",
"NoLimit": "بدون محدودیت",
"Year": "سال",
"all": "همه",
"balanceRecharge": "شارژ موجودی",
"billing": {
"billingTitle": "صورتحساب محصول",
"couponDiscount": "تخفیف کوپن",
@ -15,13 +17,18 @@
"total": "جمع کل"
},
"buy": "خرید",
"buyNow": "خرید کنید",
"buySubscription": "خرید اشتراک",
"category": "دسته‌بندی",
"coupon": "کوپن",
"detail": {
"availableTraffic": "ترافیک موجود",
"connectedDevices": "دستگاه‌های متصل",
"connectionSpeed": "سرعت اتصال",
"productDetail": "جزئیات محصول"
},
"enterAmount": "مبلغ شارژ را وارد کنید",
"enterCoupon": "کد تخفیف را وارد کنید",
"methods": {
"alipay_f2f": "علی‌پی (رو در رو)",
"balance": "موجودی",
@ -29,6 +36,20 @@
"stripe_alipay": "استرایپ (علی‌پی)",
"stripe_wechat_pay": "استرایپ (وی‌چت)"
},
"paymentMethod": "روش پرداخت",
"productDescription": "توضیحات محصول",
"products": "محصولات"
"products": "محصولات",
"purchaseDuration": "مدت خرید",
"recharge": "شارژ مجدد",
"rechargeAmount": "مبلغ شارژ",
"rechargeDescription": "شارژ با یک کلیک، آسان و راحت",
"rechargeNow": "اکنون شارژ کنید",
"renew": "تجدید",
"renewSubscription": "تمدید اشتراک",
"resetPrice": "بازنشانی قیمت",
"resetTraffic": "بازنشانی ترافیک",
"resetTrafficDescription": "بازنشانی ترافیک فقط برای ماه جاری",
"resetTrafficTitle": "بازنشانی ترافیک",
"selectSubscription": "انتخاب اشتراک",
"subscriptionDiscount": "تخفیف اشتراک"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Tämä sovellus ei tue herätystä tällä hetkellä, tuo manuaalisesti, tilausosoite on kopioitu automaattisesti",
"mySubscriptions": "Omat tilaukset",
"nextResetDays": "Seuraava nollaus/päivää",
"noLimit": "Ei rajoitusta",
"prompt": "kehotus",
"purchaseSubscription": "Osta tilaus",
"qrCode": "QR-koodi",

View File

@ -1,23 +1,12 @@
{
"Day": "Päivä",
"Hour": "Tunti",
"Minute": "Minuutti",
"Month": "Kuukausi",
"Year": "Vuosi",
"balanceRecharge": "Saldon lataus",
"buyNow": "Osta nyt",
"buySubscription": "Osta tilaus",
"cancel": "Peruuta",
"createdAt": "Luontiaika",
"description": "Yhdellä painalluksella lataus, helppoa ja vaivatonta",
"detail": "Yksityiskohdat",
"enterAmount": "Syötä ladattava summa",
"enterCoupon": "Syötä alennuskoodi",
"goToPayment": "Siirry maksamaan",
"methods": {
"alipay_f2f": "Alipay (kasvokkain)",
"alipay_f2f": "Alipay (Kasvokkain)",
"balance": "Saldo",
"epay": "Helppo maksaminen",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
@ -31,16 +20,6 @@
"paymentMethod": "Maksutapa",
"paymentSuccess": "Maksu onnistui",
"productList": "Tuotelista",
"purchaseDuration": "Ostoajan kesto",
"recharge": "Lataa saldoa",
"rechargeAmount": "Lataussumma",
"rechargeNow": "Lataa nyt",
"renew": "uudista",
"renewSubscription": "Uudista tilaus",
"resetPrice": "Nollaa hinta",
"resetTraffic": "Nollaa liikenne",
"resetTrafficDescription": "Vain kuluvan kuukauden liikenne nollataan",
"resetTrafficTitle": "Nollaa liikenne",
"scanToPay": "Ole hyvä ja skannaa maksaaksesi",
"status": {
"0": "Tila",

View File

@ -3,8 +3,10 @@
"Hour": "Tunti",
"Minute": "Minuutti",
"Month": "Kuukausi",
"NoLimit": "Ei rajoitusta",
"Year": "Vuosi",
"all": "kaikki",
"balanceRecharge": "Saldon Lataus",
"billing": {
"billingTitle": "Tuotelasku",
"couponDiscount": "Alennuskoodin alennus",
@ -15,13 +17,18 @@
"total": "Kokonaishinta"
},
"buy": "Osta",
"buyNow": "Osta nyt",
"buySubscription": "Osta tilaus",
"category": "Kategoria",
"coupon": "Kuponki",
"detail": {
"availableTraffic": "Käytettävissä oleva liikenne",
"connectedDevices": "Samanaikaisesti yhdistetyt IP-osoitteet",
"connectionSpeed": "Yhteysnopeus",
"productDetail": "Tuotteen tiedot"
},
"enterAmount": "Syötä latausmäärä",
"enterCoupon": "Syötä alennuskoodi",
"methods": {
"alipay_f2f": "Alipay (kasvokkain)",
"balance": "Saldo",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Maksutapa",
"productDescription": "Tuotteen kuvaus",
"products": "tuotteet"
"products": "tuotteet",
"purchaseDuration": "Ostoajan kesto",
"recharge": "Lataa saldoa",
"rechargeAmount": "Latausmäärä",
"rechargeDescription": "Yhden klikkauksen lataus, helppo käsitellä",
"rechargeNow": "Lataa nyt",
"renew": "Uudista",
"renewSubscription": "Uudista tilaus",
"resetPrice": "Nollaa hinta",
"resetTraffic": "Nollaa liikenne",
"resetTrafficDescription": "Nollaa liikenne vain kuluvan kuukauden osalta",
"resetTrafficTitle": "Nollaa liikenne",
"selectSubscription": "Valitse tilaus",
"subscriptionDiscount": "Tilauksen alennus"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Cette application ne prend pas encore en charge l'activation, veuillez importer manuellement, l'adresse d'abonnement a été copiée automatiquement",
"mySubscriptions": "Mes abonnements",
"nextResetDays": "Prochain réinitialisation/jours",
"noLimit": "Pas de limite",
"prompt": "invite",
"purchaseSubscription": "Acheter un abonnement",
"qrCode": "Code QR",

View File

@ -1,21 +1,10 @@
{
"Day": "Jour",
"Hour": "Heure",
"Minute": "Minute",
"Month": "Mois",
"Year": "Année",
"balanceRecharge": "Recharge de solde",
"buyNow": "Acheter maintenant",
"buySubscription": "Acheter un abonnement",
"cancel": "Annuler",
"createdAt": "Date de création",
"description": "Recharge en un clic, facile et rapide",
"detail": "Détails",
"enterAmount": "Veuillez entrer le montant à recharger",
"enterCoupon": "Veuillez entrer le code de réduction",
"goToPayment": "Aller au paiement",
"methods": {
"alipay_f2f": "Alipay (face à face)",
"alipay_f2f": "Alipay (Face à Face)",
"balance": "Solde",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -28,19 +17,9 @@
"orderNumber": "Numéro de commande",
"payment": "Payer",
"paymentAmount": "Montant du paiement",
"paymentMethod": "Moyen de paiement",
"paymentMethod": "Méthode de paiement",
"paymentSuccess": "Paiement réussi",
"productList": "Liste des produits",
"purchaseDuration": "Durée d'achat",
"recharge": "Recharger",
"rechargeAmount": "Montant de la recharge",
"rechargeNow": "Rechargez maintenant",
"renew": "Renouveler",
"renewSubscription": "Renouveler l'abonnement",
"resetPrice": "Réinitialiser le prix",
"resetTraffic": "Réinitialiser le trafic",
"resetTrafficDescription": "Réinitialiser uniquement le trafic du mois en cours",
"resetTrafficTitle": "Réinitialiser le trafic",
"scanToPay": "Veuillez scanner pour payer",
"status": {
"0": "Statut",

View File

@ -3,8 +3,10 @@
"Hour": "Heure",
"Minute": "Minute",
"Month": "Mois",
"NoLimit": "Pas de limite",
"Year": "Année",
"all": "Tout",
"balanceRecharge": "Recharge de Solde",
"billing": {
"billingTitle": "Facture des produits",
"couponDiscount": "Réduction du code promo",
@ -15,13 +17,18 @@
"total": "Prix total"
},
"buy": "Acheter",
"buyNow": "Acheter maintenant",
"buySubscription": "Acheter un abonnement",
"category": "Catégorie",
"coupon": "Coupon",
"detail": {
"availableTraffic": "Trafic disponible",
"connectedDevices": "Nombre d'IP connectées simultanément",
"connectionSpeed": "Vitesse de connexion",
"productDetail": "Détails du produit"
},
"enterAmount": "Entrez le montant de la recharge",
"enterCoupon": "Entrez le code promo",
"methods": {
"alipay_f2f": "Alipay (face à face)",
"balance": "Solde",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Méthode de paiement",
"productDescription": "Description du produit",
"products": "produits"
"products": "produits",
"purchaseDuration": "Durée d'achat",
"recharge": "Recharger",
"rechargeAmount": "Montant de la Recharge",
"rechargeDescription": "Recharge en un clic, facile à gérer",
"rechargeNow": "Rechargez maintenant",
"renew": "Renouveler",
"renewSubscription": "Renouveler l'abonnement",
"resetPrice": "Réinitialiser le prix",
"resetTraffic": "Réinitialiser le trafic",
"resetTrafficDescription": "Réinitialiser le trafic pour le mois en cours uniquement",
"resetTrafficTitle": "Réinitialiser le trafic",
"selectSubscription": "Sélectionner l'abonnement",
"subscriptionDiscount": "Remise sur l'abonnement"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "यह ऐप फिलहाल जागृत करने का समर्थन नहीं करता है, कृपया मैन्युअल रूप से आयात करें, सदस्यता पता स्वचालित रूप से कॉपी कर लिया गया है।",
"mySubscriptions": "मेरी सदस्यताएँ",
"nextResetDays": "अगली रीसेट/दिन",
"noLimit": "कोई सीमा नहीं",
"prompt": "प्रॉम्प्ट",
"purchaseSubscription": "सदस्यता खरीदें",
"qrCode": "क्यूआर कोड",

View File

@ -1,23 +1,12 @@
{
"Day": "दिन",
"Hour": "घंटा",
"Minute": "मिनट",
"Month": "महीना",
"Year": "वर्ष",
"balanceRecharge": "शेष राशि रिचार्ज",
"buyNow": "अभी खरीदें",
"buySubscription": "सदस्यता खरीदें",
"cancel": "रद्द करें",
"createdAt": "निर्माण समय",
"description": "एक क्लिक में रिचार्ज, आसानी से पूरा करें",
"detail": "विवरण",
"enterAmount": "कृपया रिचार्ज राशि दर्ज करें",
"enterCoupon": "कृपया कूपन कोड दर्ज करें",
"goToPayment": "भुगतान के लिए जाएं",
"methods": {
"alipay_f2f": "अलीपे (सामना-सामना)",
"balance": "शेष राशि",
"epay": "ई-पे",
"balance": "शेष",
"epay": "ईपे",
"stripe_alipay": "स्ट्राइप (अलीपे)",
"stripe_wechat_pay": "स्ट्राइप (वीचैट)"
},
@ -31,16 +20,6 @@
"paymentMethod": "भुगतान विधि",
"paymentSuccess": "भुगतान सफल",
"productList": "उत्पाद सूची",
"purchaseDuration": "खरीद की अवधि",
"recharge": "रिचार्ज",
"rechargeAmount": "रिचार्ज राशि",
"rechargeNow": "अभी रिचार्ज करें",
"renew": "नवीनीकरण",
"renewSubscription": "सदस्यता नवीनीकरण",
"resetPrice": "मूल्य रीसेट करें",
"resetTraffic": "ट्रैफ़िक रीसेट करें",
"resetTrafficDescription": "केवल इस महीने की ट्रैफिक को रीसेट करें",
"resetTrafficTitle": "ट्रैफ़िक रीसेट करें",
"scanToPay": "कृपया स्कैन करके भुगतान करें",
"status": {
"0": "स्थिति",

View File

@ -3,8 +3,10 @@
"Hour": "घंटा",
"Minute": "मिनट",
"Month": "महीना",
"NoLimit": "कोई सीमा नहीं",
"Year": "वर्ष",
"all": "सभी",
"balanceRecharge": "बैलेंस रिचार्ज",
"billing": {
"billingTitle": "उत्पाद बिल",
"couponDiscount": "कूपन छूट",
@ -15,13 +17,18 @@
"total": "कुल मूल्य"
},
"buy": "खरीदें",
"buyNow": "अभी खरीदें",
"buySubscription": "सदस्यता खरीदें",
"category": "श्रेणी",
"coupon": "कूपन",
"detail": {
"availableTraffic": "उपलब्ध ट्रैफ़िक",
"connectedDevices": "समानांतर कनेक्टेड IP संख्या",
"connectionSpeed": "कनेक्शन गति",
"productDetail": "उत्पाद विवरण"
},
"enterAmount": "रिचार्ज राशि दर्ज करें",
"enterCoupon": "कूपन कोड दर्ज करें",
"methods": {
"alipay_f2f": "अलीपे (सामना-सामना)",
"balance": "शेष राशि",
@ -29,6 +36,20 @@
"stripe_alipay": "स्ट्राइप (अलीपे)",
"stripe_wechat_pay": "स्ट्राइप (वीचैट)"
},
"paymentMethod": "भुगतान विधि",
"productDescription": "उत्पाद विवरण",
"products": "उत्पाद"
"products": "उत्पाद",
"purchaseDuration": "खरीद अवधि",
"recharge": "रिचार्ज",
"rechargeAmount": "रिचार्ज राशि",
"rechargeDescription": "एक-क्लिक रिचार्ज, आसान प्रबंधन",
"rechargeNow": "अभी रिचार्ज करें",
"renew": "नवीनीकरण करें",
"renewSubscription": "सदस्यता नवीनीकरण करें",
"resetPrice": "मूल्य रीसेट करें",
"resetTraffic": "ट्रैफ़िक रीसेट करें",
"resetTrafficDescription": "केवल वर्तमान माह के लिए ट्रैफिक रीसेट करें",
"resetTrafficTitle": "ट्रैफ़िक रीसेट करें",
"selectSubscription": "सदस्यता चुनें",
"subscriptionDiscount": "सदस्यता छूट"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Ez az alkalmazás jelenleg nem támogatja az ébresztést, kérjük, importálja manuálisan, az előfizetési cím automatikusan másolva lett",
"mySubscriptions": "Előfizetéseim",
"nextResetDays": "Következő visszaállítás/nap",
"noLimit": "Nincs korlát",
"prompt": "figyelmeztetés",
"purchaseSubscription": "Előfizetés vásárlása",
"qrCode": "QR-kód",

View File

@ -1,21 +1,10 @@
{
"Day": "Nap",
"Hour": "Óra",
"Minute": "Perc",
"Month": "Hónap",
"Year": "Év",
"balanceRecharge": "Egyenleg feltöltése",
"buyNow": "Vásároljon most",
"buySubscription": "Előfizetés vásárlása",
"cancel": "Mégse",
"createdAt": "Létrehozás ideje",
"description": "Egy kattintásos feltöltés, könnyedén megoldva",
"detail": "Részletek",
"enterAmount": "Kérjük, adja meg a feltöltendő összeget",
"enterCoupon": "Kérjük, adja meg a kuponkódot",
"goToPayment": "Tovább a fizetéshez",
"methods": {
"alipay_f2f": "Alipay (szemtől szemben)",
"alipay_f2f": "Alipay (Személyes)",
"balance": "Egyenleg",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -31,16 +20,6 @@
"paymentMethod": "Fizetési mód",
"paymentSuccess": "Fizetés sikeres",
"productList": "Terméklista",
"purchaseDuration": "Vásárlási időtartam",
"recharge": "feltöltés",
"rechargeAmount": "Feltöltési összeg",
"rechargeNow": "Tölts fel most",
"renew": "megújítás",
"renewSubscription": "Előfizetés megújítása",
"resetPrice": "Ár visszaállítása",
"resetTraffic": "Forgalom visszaállítása",
"resetTrafficDescription": "Csak a havi forgalom lesz visszaállítva",
"resetTrafficTitle": "Forgalom visszaállítása",
"scanToPay": "Kérjük, olvassa be a kódot a fizetéshez",
"status": {
"0": "Állapot",

View File

@ -3,8 +3,10 @@
"Hour": "Óra",
"Minute": "Perc",
"Month": "Hónap",
"NoLimit": "Nincs korlát",
"Year": "Év",
"all": "Összes",
"balanceRecharge": "Egyenlegfeltöltés",
"billing": {
"billingTitle": "Termékszámla",
"couponDiscount": "Kuponkedvezmény",
@ -15,13 +17,18 @@
"total": "Teljes ár"
},
"buy": "vásárlás",
"buyNow": "Vásárolja meg most",
"buySubscription": "Előfizetés vásárlása",
"category": "kategória",
"coupon": "Kupon",
"detail": {
"availableTraffic": "Elérhető forgalom",
"connectedDevices": "Egyidejűleg csatlakoztatott IP-k száma",
"connectionSpeed": "Kapcsolati sebesség",
"productDetail": "Termék részletei"
},
"enterAmount": "Adja meg a feltöltési összeget",
"enterCoupon": "Adja meg a kuponkódot",
"methods": {
"alipay_f2f": "Alipay (szemtől szemben)",
"balance": "Egyenleg",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Fizetési mód",
"productDescription": "Termékleírás",
"products": "termékek"
"products": "termékek",
"purchaseDuration": "Vásárlási időtartam",
"recharge": "Feltöltés",
"rechargeAmount": "Feltöltési összeg",
"rechargeDescription": "Egy kattintásos feltöltés, könnyen kezelhető",
"rechargeNow": "Töltsd fel most",
"renew": "Megújít",
"renewSubscription": "Előfizetés megújítása",
"resetPrice": "Ár visszaállítása",
"resetTraffic": "Forgalom visszaállítása",
"resetTrafficDescription": "Forgalmi adatok visszaállítása csak az aktuális hónapra",
"resetTrafficTitle": "Forgalom visszaállítása",
"selectSubscription": "Előfizetés kiválasztása",
"subscriptionDiscount": "Előfizetési kedvezmény"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "このアプリは現在起動をサポートしていません。手動でインポートしてください。サブスクリプションアドレスは自動的にコピーされました。",
"mySubscriptions": "私の購読",
"nextResetDays": "次のリセット/日",
"noLimit": "無制限",
"prompt": "プロンプト",
"purchaseSubscription": "サブスクリプションを購入",
"qrCode": "QRコード",

View File

@ -1,25 +1,14 @@
{
"Day": "日",
"Hour": "時",
"Minute": "分",
"Month": "月",
"Year": "年",
"balanceRecharge": "残高チャージ",
"buyNow": "今すぐ購入",
"buySubscription": "サブスクリプションを購入",
"cancel": "キャンセル",
"createdAt": "作成日時",
"description": "ワンクリックでチャージ、簡単に完了",
"detail": "詳細",
"enterAmount": "チャージ金額を入力してください",
"enterCoupon": "クーポンコードを入力してください",
"goToPayment": "支払いに進む",
"methods": {
"alipay_f2f": "支付宝(対面)",
"alipay_f2f": "アリペイ(対面)",
"balance": "残高",
"epay": "イージーペイ",
"stripe_alipay": "Stripe(支付宝)",
"stripe_wechat_pay": "Stripe(微信)"
"epay": "Epay",
"stripe_alipay": "ストライプ(アリペイ)",
"stripe_wechat_pay": "ストライプWeChat"
},
"name": "名前",
"orderClosed": "注文は締め切られました",
@ -31,16 +20,6 @@
"paymentMethod": "支払い方法",
"paymentSuccess": "支払い成功",
"productList": "製品リスト",
"purchaseDuration": "購入期間",
"recharge": "チャージ",
"rechargeAmount": "チャージ金額",
"rechargeNow": "今すぐチャージ",
"renew": "更新",
"renewSubscription": "サブスクリプションを更新する",
"resetPrice": "リセット価格",
"resetTraffic": "トラフィックをリセット",
"resetTrafficDescription": "今月のトラフィックのみリセットされます",
"resetTrafficTitle": "トラフィックのリセット",
"scanToPay": "スキャンしてお支払いください",
"status": {
"0": "状態",

View File

@ -3,8 +3,10 @@
"Hour": "時",
"Minute": "分",
"Month": "月",
"NoLimit": "無制限",
"Year": "年",
"all": "すべて",
"balanceRecharge": "残高チャージ",
"billing": {
"billingTitle": "商品請求書",
"couponDiscount": "クーポン割引",
@ -15,13 +17,18 @@
"total": "合計"
},
"buy": "購入",
"buyNow": "今すぐ購入",
"buySubscription": "サブスクリプションを購入",
"category": "カテゴリー",
"coupon": "クーポン",
"detail": {
"availableTraffic": "利用可能なトラフィック",
"connectedDevices": "同時接続 IP 数",
"connectionSpeed": "接続速度",
"productDetail": "商品詳細"
},
"enterAmount": "リチャージ金額を入力してください",
"enterCoupon": "クーポンコードを入力",
"methods": {
"alipay_f2f": "支付宝(対面)",
"balance": "残高",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe(支付宝)",
"stripe_wechat_pay": "Stripe(微信)"
},
"paymentMethod": "支払い方法",
"productDescription": "商品説明",
"products": "商品"
"products": "商品",
"purchaseDuration": "購入期間",
"recharge": "リチャージ",
"rechargeAmount": "リチャージ金額",
"rechargeDescription": "ワンクリックでリチャージ、簡単に操作",
"rechargeNow": "今すぐリチャージ",
"renew": "更新",
"renewSubscription": "サブスクリプションを更新する",
"resetPrice": "価格をリセット",
"resetTraffic": "トラフィックをリセット",
"resetTrafficDescription": "今月のみのトラフィックをリセットする",
"resetTrafficTitle": "トラフィックをリセット",
"selectSubscription": "サブスクリプションを選択",
"subscriptionDiscount": "サブスクリプション割引"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "이 앱은 현재 호출을 지원하지 않습니다. 수동으로 가져오세요. 구독 주소가 자동으로 복사되었습니다.",
"mySubscriptions": "내 구독",
"nextResetDays": "다음 초기화/일",
"noLimit": "제한 없음",
"prompt": "프롬프트",
"purchaseSubscription": "구독 구매",
"qrCode": "QR코드",

View File

@ -1,25 +1,14 @@
{
"Day": "일",
"Hour": "시",
"Minute": "분",
"Month": "월",
"Year": "년",
"balanceRecharge": "잔액 충전",
"buyNow": "지금 구매",
"buySubscription": "구독 구매",
"cancel": "취소",
"createdAt": "생성 시간",
"description": "원클릭 충전, 간편하게 해결",
"detail": "세부사항",
"enterAmount": "충전 금액을 입력하세요",
"enterCoupon": "할인 코드를 입력하세요",
"goToPayment": "결제하기",
"methods": {
"alipay_f2f": "알리페이(대면)",
"alipay_f2f": "알리페이 (대면 결제)",
"balance": "잔액",
"epay": "이페이",
"stripe_alipay": "Stripe(알리페이)",
"stripe_wechat_pay": "Stripe(위챗)"
"stripe_alipay": "스트라이프 (알리페이)",
"stripe_wechat_pay": "스트라이프 (위챗페이)"
},
"name": "이름",
"orderClosed": "주문이 종료되었습니다",
@ -31,16 +20,6 @@
"paymentMethod": "결제 수단",
"paymentSuccess": "결제 성공",
"productList": "제품 목록",
"purchaseDuration": "구매 기간",
"recharge": "충전",
"rechargeAmount": "충전 금액",
"rechargeNow": "지금 충전하기",
"renew": "갱신",
"renewSubscription": "구독 갱신",
"resetPrice": "가격 재설정",
"resetTraffic": "트래픽 재설정",
"resetTrafficDescription": "이번 달의 트래픽만 초기화됩니다.",
"resetTrafficTitle": "트래픽 재설정",
"scanToPay": "스캔하여 결제하세요",
"status": {
"0": "상태",

View File

@ -3,8 +3,10 @@
"Hour": "시",
"Minute": "분",
"Month": "월",
"NoLimit": "제한 없음",
"Year": "년",
"all": "전체",
"balanceRecharge": "잔액 충전",
"billing": {
"billingTitle": "상품 청구서",
"couponDiscount": "할인 코드 혜택",
@ -15,13 +17,18 @@
"total": "총액"
},
"buy": "구매",
"buyNow": "지금 구매",
"buySubscription": "구독 구매",
"category": "카테고리",
"coupon": "쿠폰",
"detail": {
"availableTraffic": "사용 가능한 트래픽",
"connectedDevices": "동시 연결 IP 수",
"connectionSpeed": "연결 속도",
"productDetail": "제품 세부 정보"
},
"enterAmount": "충전 금액을 입력하세요",
"enterCoupon": "쿠폰 코드 입력",
"methods": {
"alipay_f2f": "알리페이(대면)",
"balance": "잔액",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe(알리페이)",
"stripe_wechat_pay": "Stripe(위챗)"
},
"paymentMethod": "결제 수단",
"productDescription": "제품 설명",
"products": "상품"
"products": "상품",
"purchaseDuration": "구매 기간",
"recharge": "충전",
"rechargeAmount": "충전 금액",
"rechargeDescription": "원클릭 충전, 간편하게 처리",
"rechargeNow": "지금 충전하기",
"renew": "갱신",
"renewSubscription": "구독 갱신",
"resetPrice": "가격 재설정",
"resetTraffic": "트래픽 재설정",
"resetTrafficDescription": "현재 월에 대한 트래픽만 재설정",
"resetTrafficTitle": "트래픽 재설정",
"selectSubscription": "구독 선택",
"subscriptionDiscount": "구독 할인"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Denne appen støtter foreløpig ikke oppstart, vennligst importer manuelt, abonnementsadressen er automatisk kopiert",
"mySubscriptions": "Mine abonnementer",
"nextResetDays": "Neste tilbakestilling/dager",
"noLimit": "Ingen grense",
"prompt": "Hint",
"purchaseSubscription": "Kjøp abonnement",
"qrCode": "QR-kode",

View File

@ -1,23 +1,12 @@
{
"Day": "Dag",
"Hour": "Time",
"Minute": "Minutt",
"Month": "Måned",
"Year": "År",
"balanceRecharge": "Saldoopplading",
"buyNow": "Kjøp nå",
"buySubscription": "Kjøp abonnement",
"cancel": "Avbryt",
"createdAt": "Opprettet",
"description": "Énkel påfylling med ett klikk",
"detail": "Detaljer",
"enterAmount": "Vennligst skriv inn beløpet for påfylling",
"enterCoupon": "Vennligst skriv inn rabattkoden",
"goToPayment": "Gå til betaling",
"methods": {
"alipay_f2f": "Alipay (ansikt til ansikt)",
"alipay_f2f": "Alipay (Ansikt til ansikt)",
"balance": "Balanse",
"epay": "Enkel betaling",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
@ -31,16 +20,6 @@
"paymentMethod": "Betalingsmetode",
"paymentSuccess": "Betaling vellykket",
"productList": "Produktliste",
"purchaseDuration": "Kjøpsvarighet",
"recharge": "lade opp",
"rechargeAmount": "Ladebeløp",
"rechargeNow": "Lad opp nå",
"renew": "fornye",
"renewSubscription": "Forny abonnement",
"resetPrice": "Tilbakestill pris",
"resetTraffic": "Tilbakestill trafikk",
"resetTrafficDescription": "Tilbakestiller kun trafikken for inneværende måned",
"resetTrafficTitle": "Tilbakestill trafikk",
"scanToPay": "Vennligst skann for å betale",
"status": {
"0": "Status",

View File

@ -3,8 +3,10 @@
"Hour": "Time",
"Minute": "Minutt",
"Month": "Måned",
"NoLimit": "Ingen grense",
"Year": "År",
"all": "Alle",
"balanceRecharge": "Saldoopplading",
"billing": {
"billingTitle": "Varefaktura",
"couponDiscount": "Rabattkode rabatt",
@ -15,13 +17,18 @@
"total": "Totalpris"
},
"buy": "Kjøp",
"buyNow": "Kjøp Nå",
"buySubscription": "Kjøp abonnement",
"category": "Kategori",
"coupon": "Kupong",
"detail": {
"availableTraffic": "Tilgjengelig trafikk",
"connectedDevices": "Samtidig tilkoblede IP-er",
"connectionSpeed": "Tilkoblingshastighet",
"productDetail": "Produktdetaljer"
},
"enterAmount": "Skriv inn påfyllingsbeløp",
"enterCoupon": "Skriv inn kupongkode",
"methods": {
"alipay_f2f": "Alipay (ansikt til ansikt)",
"balance": "Balanse",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Betalingsmetode",
"productDescription": "Produktbeskrivelse",
"products": "Produkter"
"products": "Produkter",
"purchaseDuration": "Kjøpsvarighet",
"recharge": "Lad opp",
"rechargeAmount": "Påfyllingsbeløp",
"rechargeDescription": "Ett-klikks opplading, enkelt å håndtere",
"rechargeNow": "Lad opp nå",
"renew": "Forny",
"renewSubscription": "Forny abonnement",
"resetPrice": "Tilbakestill pris",
"resetTraffic": "Tilbakestill trafikk",
"resetTrafficDescription": "Tilbakestill trafikk kun for inneværende måned",
"resetTrafficTitle": "Nullstill trafikk",
"selectSubscription": "Velg abonnement",
"subscriptionDiscount": "Abonnementsrabatt"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Ta aplikacja tymczasowo nie obsługuje wywoływania, proszę zaimportować ręcznie, adres subskrypcji został automatycznie skopiowany",
"mySubscriptions": "Moje subskrypcje",
"nextResetDays": "Następny reset/dni",
"noLimit": "Bez limitu",
"prompt": "Podpowiedź",
"purchaseSubscription": "Zakup subskrypcji",
"qrCode": "Kod QR",

View File

@ -1,21 +1,10 @@
{
"Day": "Dzień",
"Hour": "Godzina",
"Minute": "Minuta",
"Month": "Miesiąc",
"Year": "Rok",
"balanceRecharge": "Doładowanie salda",
"buyNow": "Kup teraz",
"buySubscription": "Kup subskrypcję",
"cancel": "Anuluj",
"createdAt": "Czas utworzenia",
"description": "Jedno kliknięcie doładowania, łatwe do załatwienia",
"detail": "Szczegóły",
"enterAmount": "Wprowadź kwotę doładowania",
"enterCoupon": "Wprowadź kod rabatowy",
"goToPayment": "Przejdź do płatności",
"methods": {
"alipay_f2f": "Alipay (twarzą w twarz)",
"alipay_f2f": "Alipay (Twarzą w twarz)",
"balance": "Saldo",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -31,16 +20,6 @@
"paymentMethod": "Metoda płatności",
"paymentSuccess": "Płatność zakończona sukcesem",
"productList": "Lista produktów",
"purchaseDuration": "Czas zakupu",
"recharge": "doładowanie",
"rechargeAmount": "Kwota doładowania",
"rechargeNow": "Doładuj teraz",
"renew": "odnów",
"renewSubscription": "Odnów subskrypcję",
"resetPrice": "Zresetuj cenę",
"resetTraffic": "Zresetuj ruch",
"resetTrafficDescription": "Resetuj tylko miesięczny transfer danych",
"resetTrafficTitle": "Zresetuj ruch",
"scanToPay": "Zeskanuj kod, aby zapłacić",
"status": {
"0": "Status",

View File

@ -3,8 +3,10 @@
"Hour": "Godzina",
"Minute": "Minuta",
"Month": "Miesiąc",
"NoLimit": "Bez limitu",
"Year": "Rok",
"all": "Wszystko",
"balanceRecharge": "Doładowanie salda",
"billing": {
"billingTitle": "Rachunek za produkt",
"couponDiscount": "Zniżka z kodu rabatowego",
@ -15,13 +17,18 @@
"total": "Suma"
},
"buy": "Kup",
"buyNow": "Kup Teraz",
"buySubscription": "Kup Subskrypcję",
"category": "kategoria",
"coupon": "Kupon",
"detail": {
"availableTraffic": "Dostępny ruch",
"connectedDevices": "Liczba jednocześnie podłączonych IP",
"connectionSpeed": "Prędkość połączenia",
"productDetail": "Szczegóły produktu"
},
"enterAmount": "Wprowadź kwotę doładowania",
"enterCoupon": "Wprowadź kod kuponu",
"methods": {
"alipay_f2f": "Alipay (twarzą w twarz)",
"balance": "Saldo",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Metoda płatności",
"productDescription": "Opis produktu",
"products": "Produkty"
"products": "Produkty",
"purchaseDuration": "Czas trwania zakupu",
"recharge": "Doładowanie",
"rechargeAmount": "Kwota doładowania",
"rechargeDescription": "Jedno kliknięcie doładowania, łatwe w obsłudze",
"rechargeNow": "Doładuj teraz",
"renew": "Odnów",
"renewSubscription": "Odnów subskrypcję",
"resetPrice": "Zresetuj cenę",
"resetTraffic": "Zresetuj ruch",
"resetTrafficDescription": "Zresetuj ruch tylko na bieżący miesiąc",
"resetTrafficTitle": "Zresetuj Ruch",
"selectSubscription": "Wybierz subskrypcję",
"subscriptionDiscount": "Zniżka na subskrypcję"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Este aplicativo não suporta ativação no momento, por favor, importe manualmente. O endereço de assinatura foi copiado automaticamente.",
"mySubscriptions": "Minhas assinaturas",
"nextResetDays": "Próxima redefinição/dias",
"noLimit": "Sem Limite",
"prompt": "Sugestão",
"purchaseSubscription": "Comprar Assinatura",
"qrCode": "Código QR",

View File

@ -1,21 +1,10 @@
{
"Day": "Dia",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mês",
"Year": "Ano",
"balanceRecharge": "Recarga de Saldo",
"buyNow": "Compre Agora",
"buySubscription": "Comprar Assinatura",
"cancel": "Cancelar",
"createdAt": "Data de Criação",
"description": "Recarga com um clique, fácil e rápido",
"detail": "Detalhes",
"enterAmount": "Por favor, insira o valor de recarga",
"enterCoupon": "Insira o código de desconto",
"goToPayment": "Ir para o pagamento",
"methods": {
"alipay_f2f": "Alipay (face a face)",
"alipay_f2f": "Alipay (Face a Face)",
"balance": "Saldo",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -31,16 +20,6 @@
"paymentMethod": "Método de Pagamento",
"paymentSuccess": "Pagamento bem-sucedido",
"productList": "Lista de Produtos",
"purchaseDuration": "Duração da compra",
"recharge": "recarregar",
"rechargeAmount": "Valor de recarga",
"rechargeNow": "Recarregar agora",
"renew": "renovar",
"renewSubscription": "Renovar Assinatura",
"resetPrice": "Redefinir Preço",
"resetTraffic": "Redefinir Tráfego",
"resetTrafficDescription": "Apenas redefine o tráfego do mês atual, ok?",
"resetTrafficTitle": "Redefinir Tráfego",
"scanToPay": "Por favor, escaneie para pagar",
"status": {
"0": "status",

View File

@ -3,8 +3,10 @@
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mês",
"NoLimit": "Sem Limite",
"Year": "Ano",
"all": "todos",
"balanceRecharge": "Recarga de Saldo",
"billing": {
"billingTitle": "Fatura do Produto",
"couponDiscount": "Desconto do Cupom",
@ -15,13 +17,18 @@
"total": "Preço Total"
},
"buy": "Comprar",
"buyNow": "Compre Agora",
"buySubscription": "Comprar Assinatura",
"category": "categoria",
"coupon": "Cupom",
"detail": {
"availableTraffic": "Tráfego disponível",
"connectedDevices": "Dispositivos conectados simultaneamente",
"connectionSpeed": "Velocidade de conexão",
"productDetail": "Detalhes do produto"
},
"enterAmount": "Digite o valor da recarga",
"enterCoupon": "Insira o Código do Cupom",
"methods": {
"alipay_f2f": "Alipay (cara a cara)",
"balance": "Saldo",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Método de Pagamento",
"productDescription": "Descrição do produto",
"products": "produtos"
"products": "produtos",
"purchaseDuration": "Duração da Compra",
"recharge": "Recarregar",
"rechargeAmount": "Valor de Recarga",
"rechargeDescription": "Recarga com um clique, fácil de manusear",
"rechargeNow": "Recarregar Agora",
"renew": "Renovar",
"renewSubscription": "Renovar Assinatura",
"resetPrice": "Redefinir Preço",
"resetTraffic": "Redefinir Tráfego",
"resetTrafficDescription": "Redefinir o tráfego apenas para o mês atual",
"resetTrafficTitle": "Redefinir Tráfego",
"selectSubscription": "Selecionar Assinatura",
"subscriptionDiscount": "Desconto na Assinatura"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Această aplicație nu suportă momentan activarea, vă rugăm să importați manual, adresa de abonament a fost copiată automat",
"mySubscriptions": "Abonamentele mele",
"nextResetDays": "Următoarea resetare/zile",
"noLimit": "Fără limită",
"prompt": "Sfat",
"purchaseSubscription": "Achiziționează abonament",
"qrCode": "cod QR",

View File

@ -1,21 +1,10 @@
{
"Day": "Zi",
"Hour": "Oră",
"Minute": "Minută",
"Month": "Lună",
"Year": "An",
"balanceRecharge": "Reîncărcare sold",
"buyNow": "Cumpără acum",
"buySubscription": "Cumpără abonament",
"cancel": "Anulare",
"createdAt": "Data creării",
"description": "Reîncărcare cu un singur clic, ușor de realizat",
"detail": "Detalii",
"enterAmount": "Introduceți suma de reîncărcare",
"enterCoupon": "Introduceți codul de reducere",
"goToPayment": "Mergi la plată",
"methods": {
"alipay_f2f": "Alipay (față în față)",
"alipay_f2f": "Alipay (Față în Față)",
"balance": "Sold",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -31,16 +20,6 @@
"paymentMethod": "Metodă de plată",
"paymentSuccess": "Plata a fost efectuată cu succes",
"productList": "Listă de produse",
"purchaseDuration": "Durata achiziției",
"recharge": "reîncărcare",
"rechargeAmount": "Suma de reîncărcare",
"rechargeNow": "Reîncarcă acum",
"renew": "reînnoire",
"renewSubscription": "Reînnoiește abonamentul",
"resetPrice": "Resetează prețul",
"resetTraffic": "Resetează traficul",
"resetTrafficDescription": "Resetează doar traficul din această lună",
"resetTrafficTitle": "Resetează traficul",
"scanToPay": "Vă rugăm să scanați pentru a plăti",
"status": {
"0": "stare",

View File

@ -3,8 +3,10 @@
"Hour": "Oră",
"Minute": "Minut",
"Month": "Lună",
"NoLimit": "Fără limită",
"Year": "An",
"all": "Toate",
"balanceRecharge": "Reîncărcare Sold",
"billing": {
"billingTitle": "Factură produs",
"couponDiscount": "Reducere cupon",
@ -15,13 +17,18 @@
"total": "Total"
},
"buy": "Cumpără",
"buyNow": "Cumpără acum",
"buySubscription": "Cumpără Abonament",
"category": "categorie",
"coupon": "Cupon",
"detail": {
"availableTraffic": "Trafic disponibil",
"connectedDevices": "Număr de IP-uri conectate simultan",
"connectionSpeed": "Viteza de conectare",
"productDetail": "Detalii produs"
},
"enterAmount": "Introduceți suma de reîncărcare",
"enterCoupon": "Introduceți codul cuponului",
"methods": {
"alipay_f2f": "Alipay (față în față)",
"balance": "Sold",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Metodă de plată",
"productDescription": "Descrierea produsului",
"products": "produse"
"products": "produse",
"purchaseDuration": "Durata Achiziției",
"recharge": "Reîncărcare",
"rechargeAmount": "Sumă Reîncărcare",
"rechargeDescription": "Reîncărcare cu un singur clic, ușor de gestionat",
"rechargeNow": "Reîncarcă acum",
"renew": "Reînnoiește",
"renewSubscription": "Reînnoiește Abonamentul",
"resetPrice": "Resetează Prețul",
"resetTraffic": "Resetează Traficul",
"resetTrafficDescription": "Resetează traficul doar pentru luna curentă",
"resetTrafficTitle": "Resetează Traficul",
"selectSubscription": "Selectați Abonamentul",
"subscriptionDiscount": "Reducere la abonament"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Это приложение временно не поддерживает вызов, пожалуйста, импортируйте вручную, адрес подписки уже скопирован",
"mySubscriptions": "Мои подписки",
"nextResetDays": "Следующее сброс/дней",
"noLimit": "Без ограничений",
"prompt": "Подсказка",
"purchaseSubscription": "Купить подписку",
"qrCode": "QR-код",

View File

@ -1,21 +1,10 @@
{
"Day": "День",
"Hour": "Час",
"Minute": "минута",
"Month": "Месяц",
"Year": "Год",
"balanceRecharge": "Пополнение баланса",
"buyNow": "Купить сейчас",
"buySubscription": "Купить подписку",
"cancel": "Отмена",
"createdAt": "Время создания",
"description": "Одним нажатием пополните баланс, легко и просто",
"detail": "Подробности",
"enterAmount": "Введите сумму пополнения",
"enterCoupon": "Введите промокод",
"goToPayment": "Перейти к оплате",
"methods": {
"alipay_f2f": "Alipay (лицом к лицу)",
"alipay_f2f": "Alipay (Лицом к лицу)",
"balance": "Баланс",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
@ -31,16 +20,6 @@
"paymentMethod": "Способ оплаты",
"paymentSuccess": "Оплата успешно завершена",
"productList": "Список продуктов",
"purchaseDuration": "Продолжительность покупки",
"recharge": "Пополнение",
"rechargeAmount": "Сумма пополнения",
"rechargeNow": "Пополнить сейчас",
"renew": "обновить",
"renewSubscription": "Продлить подписку",
"resetPrice": "Сбросить цену",
"resetTraffic": "Сбросить трафик",
"resetTrafficDescription": "Сбросить только месячный трафик",
"resetTrafficTitle": "Сброс трафика",
"scanToPay": "Пожалуйста, отсканируйте для оплаты",
"status": {
"0": "Статус",

View File

@ -3,8 +3,10 @@
"Hour": "Час",
"Minute": "минута",
"Month": "Месяц",
"NoLimit": "Без ограничений",
"Year": "Год",
"all": "все",
"balanceRecharge": "Пополнение баланса",
"billing": {
"billingTitle": "Счет за товар",
"couponDiscount": "Скидка по промокоду",
@ -15,13 +17,18 @@
"total": "Итоговая цена"
},
"buy": "Купить",
"buyNow": "Купить сейчас",
"buySubscription": "Купить подписку",
"category": "категория",
"coupon": "Купон",
"detail": {
"availableTraffic": "Доступный трафик",
"connectedDevices": "Количество одновременно подключенных IP",
"connectionSpeed": "Скорость соединения",
"productDetail": "Детали продукта"
},
"enterAmount": "Введите сумму пополнения",
"enterCoupon": "Введите промокод",
"methods": {
"alipay_f2f": "Alipay(лицом к лицу)",
"balance": "Баланс",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe(Alipay)",
"stripe_wechat_pay": "Stripe(WeChat)"
},
"paymentMethod": "Способ оплаты",
"productDescription": "Описание товара",
"products": "товары"
"products": "товары",
"purchaseDuration": "Продолжительность покупки",
"recharge": "Пополнение",
"rechargeAmount": "Сумма пополнения",
"rechargeDescription": "Одним нажатием пополните баланс, легко и удобно",
"rechargeNow": "Пополнить сейчас",
"renew": "Обновить",
"renewSubscription": "Продлить подписку",
"resetPrice": "Сбросить цену",
"resetTraffic": "Сбросить трафик",
"resetTrafficDescription": "Сбросить трафик только за текущий месяц",
"resetTrafficTitle": "Сбросить трафик",
"selectSubscription": "Выберите подписку",
"subscriptionDiscount": "Скидка на подписку"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "แอปนี้ยังไม่รองรับการเปิดใช้งาน กรุณานำเข้าด้วยตนเอง ที่อยู่การสมัครสมาชิกได้ถูกคัดลอกอัตโนมัติแล้ว",
"mySubscriptions": "การสมัครสมาชิกของฉัน",
"nextResetDays": "รีเซ็ตครั้งถัดไป/วัน",
"noLimit": "ไม่จำกัด",
"prompt": "คำแนะนำ",
"purchaseSubscription": "ซื้อการสมัครสมาชิก",
"qrCode": "คิวอาร์โค้ด",

View File

@ -1,25 +1,14 @@
{
"Day": "วัน",
"Hour": "ชั่วโมง",
"Minute": "นาที",
"Month": "เดือน",
"Year": "ปี",
"balanceRecharge": "เติมเงินยอดคงเหลือ",
"buyNow": "ซื้อทันที",
"buySubscription": "ซื้อการสมัครสมาชิก",
"cancel": "ยกเลิก",
"createdAt": "เวลาที่สร้าง",
"description": "เติมเงินง่าย ๆ เพียงคลิกเดียว",
"detail": "รายละเอียด",
"enterAmount": "กรุณาใส่จำนวนเงินที่ต้องการเติม",
"enterCoupon": "กรุณาใส่รหัสส่วนลด",
"goToPayment": "ไปที่การชำระเงิน",
"methods": {
"alipay_f2f": "อาลีเพย์ (เผชิญหน้า)",
"balance": "ยอดคงเหลือ",
"epay": "อีเพย์",
"stripe_alipay": "Stripe (อาลีเพย์)",
"stripe_wechat_pay": "Stripe (วีแชท)"
"stripe_alipay": "สไตรป์ (อาลีเพย์)",
"stripe_wechat_pay": "สไตรป์ (วีแชท)"
},
"name": "ชื่อ",
"orderClosed": "คำสั่งซื้อถูกปิดแล้ว",
@ -31,16 +20,6 @@
"paymentMethod": "วิธีการชำระเงิน",
"paymentSuccess": "ชำระเงินสำเร็จ",
"productList": "รายการสินค้า",
"purchaseDuration": "ระยะเวลาการซื้อ",
"recharge": "เติมเงิน",
"rechargeAmount": "จำนวนเงินที่เติม",
"rechargeNow": "เติมเงินทันที",
"renew": "ต่ออายุ",
"renewSubscription": "ต่ออายุการสมัครสมาชิก",
"resetPrice": "รีเซ็ตราคา",
"resetTraffic": "รีเซ็ตการใช้งานข้อมูล",
"resetTrafficDescription": "รีเซ็ตเฉพาะปริมาณข้อมูลของเดือนนี้เท่านั้น",
"resetTrafficTitle": "รีเซ็ตการใช้งานข้อมูล",
"scanToPay": "กรุณาสแกนเพื่อชำระเงิน",
"status": {
"0": "สถานะ",

View File

@ -3,8 +3,10 @@
"Hour": "ชั่วโมง",
"Minute": "นาที",
"Month": "เดือน",
"NoLimit": "ไม่จำกัด",
"Year": "ปี",
"all": "ทั้งหมด",
"balanceRecharge": "เติมเงินยอดคงเหลือ",
"billing": {
"billingTitle": "ใบแจ้งหนี้สินค้า",
"couponDiscount": "ส่วนลดคูปอง",
@ -15,13 +17,18 @@
"total": "ราคารวม"
},
"buy": "ซื้อ",
"buyNow": "ซื้อเลย",
"buySubscription": "ซื้อการสมัครสมาชิก",
"category": "หมวดหมู่",
"coupon": "คูปอง",
"detail": {
"availableTraffic": "ปริมาณข้อมูลที่ใช้ได้",
"connectedDevices": "จำนวนอุปกรณ์ที่เชื่อมต่อพร้อมกัน",
"connectionSpeed": "ความเร็วในการเชื่อมต่อ",
"productDetail": "รายละเอียดสินค้า"
},
"enterAmount": "กรอกจำนวนเงินที่ต้องการเติม",
"enterCoupon": "กรอกรหัสคูปอง",
"methods": {
"alipay_f2f": "อาลีเพย์ (เผชิญหน้า)",
"balance": "ยอดคงเหลือ",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (อาลีเพย์)",
"stripe_wechat_pay": "Stripe (วีแชท)"
},
"paymentMethod": "วิธีการชำระเงิน",
"productDescription": "รายละเอียดสินค้า",
"products": "สินค้า"
"products": "สินค้า",
"purchaseDuration": "ระยะเวลาการซื้อ",
"recharge": "เติมเงิน",
"rechargeAmount": "จำนวนเงินเติม",
"rechargeDescription": "เติมเงินง่าย ๆ เพียงคลิกเดียว สะดวกสบาย",
"rechargeNow": "เติมเงินทันที",
"renew": "ต่ออายุ",
"renewSubscription": "ต่ออายุการสมัครสมาชิก",
"resetPrice": "รีเซ็ตราคา",
"resetTraffic": "รีเซ็ตการจราจร",
"resetTrafficDescription": "รีเซ็ตการใช้งานข้อมูลสำหรับเดือนปัจจุบันเท่านั้น",
"resetTrafficTitle": "รีเซ็ตการจราจร",
"selectSubscription": "เลือกการสมัครสมาชิก",
"subscriptionDiscount": "ส่วนลดการสมัครสมาชิก"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Bu uygulama şu anda uyandırmayı desteklemiyor, lütfen elle içe aktarın, abone adresi otomatik olarak kopyalandı",
"mySubscriptions": "Aboneliklerim",
"nextResetDays": "Sonraki Sıfırlama/Gün",
"noLimit": "Sınırsız",
"prompt": "istem",
"purchaseSubscription": "Abonelik Satın Al",
"qrCode": "QR kodu",

View File

@ -1,25 +1,14 @@
{
"Day": "Gün",
"Hour": "Saat",
"Minute": "Dakika",
"Month": "Ay",
"Year": "Yıl",
"balanceRecharge": "Bakiye Yükleme",
"buyNow": "Şimdi Satın Al",
"buySubscription": "Abonelik Satın Al",
"cancel": "İptal",
"createdAt": "Oluşturulma Zamanı",
"description": "Tek tıkla yükleme, kolayca halledin",
"detail": "Detaylar",
"enterAmount": "Lütfen yükleme miktarını girin",
"enterCoupon": "Lütfen indirim kodunu girin",
"goToPayment": "Ödemeye Git",
"methods": {
"alipay_f2f": "Alipay(Yüz Yüze)",
"alipay_f2f": "Alipay (Yüz Yüze)",
"balance": "Bakiye",
"epay": "Kolay Ödeme",
"stripe_alipay": "Stripe(Alipay)",
"stripe_wechat_pay": "Stripe(WeChat)"
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"name": "Adı",
"orderClosed": "Sipariş kapatıldı",
@ -31,16 +20,6 @@
"paymentMethod": "Ödeme Yöntemi",
"paymentSuccess": "Ödeme Başarılı",
"productList": "Ürün Listesi",
"purchaseDuration": "Satın Alma Süresi",
"recharge": "şarj et",
"rechargeAmount": "Yükleme Tutarı",
"rechargeNow": "Şimdi Yükle",
"renew": "yenile",
"renewSubscription": "Aboneliği Yenile",
"resetPrice": "Fiyatı Sıfırla",
"resetTraffic": "Trafiği Sıfırla",
"resetTrafficDescription": "Sadece bu ayın trafiğini sıfırlayın",
"resetTrafficTitle": "Trafiği Sıfırla",
"scanToPay": "Lütfen tarayıcı ile ödeme yapın",
"status": {
"0": "Durum",

View File

@ -3,8 +3,10 @@
"Hour": "Saat",
"Minute": "Dakika",
"Month": "Ay",
"NoLimit": "Sınır Yok",
"Year": "Yıl",
"all": "Tümü",
"balanceRecharge": "Bakiye Yükleme",
"billing": {
"billingTitle": "Ürün Faturası",
"couponDiscount": "Kupon İndirimi",
@ -15,13 +17,18 @@
"total": "Toplam Fiyat"
},
"buy": "satın al",
"buyNow": "Şimdi Satın Al",
"buySubscription": "Abonelik Satın Al",
"category": "kategori",
"coupon": "Kupon",
"detail": {
"availableTraffic": "Kullanılabilir Trafik",
"connectedDevices": "Eşzamanlı Bağlı IP Sayısı",
"connectionSpeed": "Bağlantı Hızı",
"productDetail": "Ürün Detayları"
},
"enterAmount": "Yükleme tutarını girin",
"enterCoupon": "Kupon Kodunu Girin",
"methods": {
"alipay_f2f": "Alipay(Yüz Yüze)",
"balance": "Bakiye",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe(Alipay)",
"stripe_wechat_pay": "Stripe(WeChat)"
},
"paymentMethod": "Ödeme Yöntemi",
"productDescription": "Ürün Açıklaması",
"products": "ürünler"
"products": "ürünler",
"purchaseDuration": "Satın Alma Süresi",
"recharge": "Yeniden Yükle",
"rechargeAmount": "Yükleme Tutarı",
"rechargeDescription": "Tek tıkla şarj, kolay kullanım",
"rechargeNow": "Şimdi Yükle",
"renew": "Yenile",
"renewSubscription": "Aboneliği Yenile",
"resetPrice": "Fiyatı Sıfırla",
"resetTraffic": "Trafiği Sıfırla",
"resetTrafficDescription": "Yalnızca mevcut ay için trafiği sıfırla",
"resetTrafficTitle": "Trafiği Sıfırla",
"selectSubscription": "Abonelik Seç",
"subscriptionDiscount": "Abonelik İndirimi"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Цей додаток тимчасово не підтримує виклик, будь ласка, імпортуйте вручну, адресу підписки вже скопійовано",
"mySubscriptions": "Мої підписки",
"nextResetDays": "Наступне скидання/днів",
"noLimit": "Без обмежень",
"prompt": "підказка",
"purchaseSubscription": "Придбати підписку",
"qrCode": "QR-код",

View File

@ -1,25 +1,14 @@
{
"Day": "День",
"Hour": "Година",
"Minute": "Хвилина",
"Month": "Місяць",
"Year": "Рік",
"balanceRecharge": "Поповнення балансу",
"buyNow": "Купити зараз",
"buySubscription": "Придбати підписку",
"cancel": "Скасувати",
"createdAt": "Час створення",
"description": "Одним натисканням поповнити рахунок, легко та швидко",
"detail": "Деталі",
"enterAmount": "Введіть суму поповнення",
"enterCoupon": "Введіть код знижки",
"goToPayment": "Перейти до оплати",
"methods": {
"alipay_f2f": "Alipay(обличчям до обличчя)",
"alipay_f2f": "Alipay (Обличчям до обличчя)",
"balance": "Баланс",
"epay": "Epay",
"stripe_alipay": "Stripe(Alipay)",
"stripe_wechat_pay": "Stripe(WeChat)"
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"name": "Назва",
"orderClosed": "Замовлення закрито",
@ -31,16 +20,6 @@
"paymentMethod": "Спосіб оплати",
"paymentSuccess": "Оплата успішна",
"productList": "Список продуктів",
"purchaseDuration": "Тривалість покупки",
"recharge": "Поповнення",
"rechargeAmount": "Сума поповнення",
"rechargeNow": "Поповнити зараз",
"renew": "продовжити",
"renewSubscription": "Поновити підписку",
"resetPrice": "Скинути ціну",
"resetTraffic": "Скинути трафік",
"resetTrafficDescription": "Скидання лише місячного трафіку",
"resetTrafficTitle": "Скинути трафік",
"scanToPay": "Будь ласка, відскануйте для оплати",
"status": {
"0": "Статус",

View File

@ -3,8 +3,10 @@
"Hour": "Година",
"Minute": "хвилина",
"Month": "Місяць",
"NoLimit": "Без обмежень",
"Year": "Рік",
"all": "всі",
"balanceRecharge": "Поповнення балансу",
"billing": {
"billingTitle": "Рахунок за товар",
"couponDiscount": "Знижка за промокодом",
@ -15,13 +17,18 @@
"total": "Загальна сума"
},
"buy": "Купити",
"buyNow": "Купити зараз",
"buySubscription": "Купити підписку",
"category": "категорія",
"coupon": "Купон",
"detail": {
"availableTraffic": "Доступний трафік",
"connectedDevices": "Кількість одночасно підключених IP",
"connectionSpeed": "Швидкість з'єднання",
"productDetail": "Деталі товару"
},
"enterAmount": "Введіть суму поповнення",
"enterCoupon": "Введіть код купона",
"methods": {
"alipay_f2f": "Alipay (обличчям до обличчя)",
"balance": "Баланс",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Спосіб оплати",
"productDescription": "Опис товару",
"products": "товари"
"products": "товари",
"purchaseDuration": "Тривалість покупки",
"recharge": "Поповнення",
"rechargeAmount": "Сума поповнення",
"rechargeDescription": "Одним натисканням поповнити рахунок, легко впоратися",
"rechargeNow": "Поповнити зараз",
"renew": "Оновити",
"renewSubscription": "Поновити підписку",
"resetPrice": "Скинути ціну",
"resetTraffic": "Скинути трафік",
"resetTrafficDescription": "Скинути трафік лише для поточного місяця",
"resetTrafficTitle": "Скинути трафік",
"selectSubscription": "Виберіть підписку",
"subscriptionDiscount": "Знижка на підписку"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "Ứng dụng này hiện không hỗ trợ kích hoạt, vui lòng nhập thủ công, địa chỉ đăng ký đã được sao chép tự động",
"mySubscriptions": "Đăng ký của tôi",
"nextResetDays": "Lần đặt lại tiếp theo/ngày",
"noLimit": "Không Giới Hạn",
"prompt": "gợi ý",
"purchaseSubscription": "Mua đăng ký",
"qrCode": "Mã QR",

View File

@ -1,23 +1,12 @@
{
"Day": "Ngày",
"Hour": "Giờ",
"Minute": "Phút",
"Month": "Tháng",
"Year": "Năm",
"balanceRecharge": "Nạp tiền số dư",
"buyNow": "Mua ngay",
"buySubscription": "Mua đăng ký",
"cancel": "Hủy",
"createdAt": "Thời gian tạo",
"description": "Nạp tiền chỉ với một cú nhấp, dễ dàng hoàn tất",
"detail": "Chi tiết",
"enterAmount": "Vui lòng nhập số tiền nạp",
"enterCoupon": "Vui lòng nhập mã giảm giá",
"goToPayment": "Đi đến thanh toán",
"methods": {
"alipay_f2f": "Alipay (mặt đối mặt)",
"alipay_f2f": "Alipay (Giao dịch trực tiếp)",
"balance": "Số dư",
"epay": "Thanh toán dễ dàng",
"epay": "Epay",
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
@ -28,19 +17,9 @@
"orderNumber": "Số đơn hàng",
"payment": "Thanh toán",
"paymentAmount": "Số tiền thanh toán",
"paymentMethod": "Phương thức thanh toán",
"paymentMethod": "Phương Thức Thanh Toán",
"paymentSuccess": "Thanh toán thành công",
"productList": "Danh sách sản phẩm",
"purchaseDuration": "Thời gian mua",
"recharge": "Nạp tiền",
"rechargeAmount": "Số tiền nạp",
"rechargeNow": "Nạp tiền ngay",
"renew": "Gia hạn",
"renewSubscription": "Gia hạn đăng ký",
"resetPrice": "Đặt lại giá",
"resetTraffic": "Đặt lại lưu lượng",
"resetTrafficDescription": "Chỉ đặt lại lưu lượng tháng này thôi nhé",
"resetTrafficTitle": "Đặt lại lưu lượng",
"scanToPay": "Vui lòng quét mã để thanh toán",
"status": {
"0": "Trạng thái",

View File

@ -3,8 +3,10 @@
"Hour": "Giờ",
"Minute": "Phút",
"Month": "Tháng",
"NoLimit": "Không Giới Hạn",
"Year": "Năm",
"all": "Tất cả",
"balanceRecharge": "Nạp Tiền Số Dư",
"billing": {
"billingTitle": "Hóa đơn sản phẩm",
"couponDiscount": "Ưu đãi mã giảm giá",
@ -15,13 +17,18 @@
"total": "Tổng giá"
},
"buy": "Mua",
"buyNow": "Mua Ngay",
"buySubscription": "Mua Gói Đăng Ký",
"category": "thể loại",
"coupon": "Phiếu giảm giá",
"detail": {
"availableTraffic": "Lưu lượng khả dụng",
"connectedDevices": "Số IP kết nối đồng thời",
"connectionSpeed": "Tốc độ kết nối",
"productDetail": "Chi tiết sản phẩm"
},
"enterAmount": "Nhập số tiền nạp",
"enterCoupon": "Nhập Mã Phiếu Giảm Giá",
"methods": {
"alipay_f2f": "Alipay (mặt đối mặt)",
"balance": "Số dư",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe (Alipay)",
"stripe_wechat_pay": "Stripe (WeChat)"
},
"paymentMethod": "Phương thức thanh toán",
"productDescription": "Mô tả sản phẩm",
"products": "Sản phẩm"
"products": "Sản phẩm",
"purchaseDuration": "Thời Gian Mua Hàng",
"recharge": "Nạp tiền",
"rechargeAmount": "Số Tiền Nạp",
"rechargeDescription": "Nạp tiền chỉ với một cú nhấp, dễ dàng xử lý",
"rechargeNow": "Nạp Ngay",
"renew": "Gia hạn",
"renewSubscription": "Gia hạn đăng ký",
"resetPrice": "Đặt lại giá",
"resetTraffic": "Đặt lại Lưu lượng",
"resetTrafficDescription": "Đặt lại lưu lượng truy cập chỉ cho tháng hiện tại",
"resetTrafficTitle": "Đặt lại Lưu lượng",
"selectSubscription": "Chọn Gói Đăng Ký",
"subscriptionDiscount": "Giảm giá Đăng ký"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "该应用暂不支持唤起,请手动导入,已自动复制订阅地址",
"mySubscriptions": "我的订阅",
"nextResetDays": "下次重置/天",
"noLimit": "无限制",
"prompt": "提示",
"purchaseSubscription": "购买订阅",
"qrCode": "二维码",

View File

@ -1,25 +1,14 @@
{
"Day": "天",
"Hour": "时",
"Minute": "分",
"Month": "月",
"Year": "年",
"balanceRecharge": "余额充值",
"buyNow": "立即购买",
"buySubscription": "购买订阅",
"cancel": "取消",
"createdAt": "创建时间",
"description": "一键充值,轻松搞定",
"detail": "详情",
"enterAmount": "请输入充值金额",
"enterCoupon": "请输入折扣码",
"goToPayment": "前往支付",
"methods": {
"alipay_f2f": "支付宝(面对面)",
"alipay_f2f": "支付宝(面对面)",
"balance": "余额",
"epay": "支付",
"stripe_alipay": "Stripe(支付宝)",
"stripe_wechat_pay": "Stripe(微信)"
"epay": "电子支付",
"stripe_alipay": "Stripe(支付宝)",
"stripe_wechat_pay": "Stripe(微信支付)"
},
"name": "名称",
"orderClosed": "订单已关闭",
@ -31,16 +20,6 @@
"paymentMethod": "支付方式",
"paymentSuccess": "支付成功",
"productList": "产品列表",
"purchaseDuration": "购买时长",
"recharge": "充值",
"rechargeAmount": "充值金额",
"rechargeNow": "立即充值",
"renew": "续费",
"renewSubscription": "续费订阅",
"resetPrice": "重置价格",
"resetTraffic": "重置流量",
"resetTrafficDescription": "仅重置当月流量哦",
"resetTrafficTitle": "重置流量",
"scanToPay": "请扫码支付",
"status": {
"0": "状态",

View File

@ -3,8 +3,10 @@
"Hour": "时",
"Minute": "分",
"Month": "月",
"NoLimit": "无限制",
"Year": "年",
"all": "全部",
"balanceRecharge": "余额充值",
"billing": {
"billingTitle": "商品账单",
"couponDiscount": "折扣码优惠",
@ -15,13 +17,18 @@
"total": "总价"
},
"buy": "购买",
"buyNow": "立即购买",
"buySubscription": "购买订阅",
"category": "类别",
"coupon": "优惠券",
"detail": {
"availableTraffic": "可用流量",
"connectedDevices": "同时连接 IP 数",
"connectionSpeed": "连接速度",
"productDetail": "商品详情"
},
"enterAmount": "输入充值金额",
"enterCoupon": "输入优惠券代码",
"methods": {
"alipay_f2f": "支付宝(面对面)",
"balance": "余额",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe(支付宝)",
"stripe_wechat_pay": "Stripe(微信)"
},
"paymentMethod": "支付方式",
"productDescription": "商品描述",
"products": "商品"
"products": "商品",
"purchaseDuration": "购买时长",
"recharge": "充值",
"rechargeAmount": "充值金额",
"rechargeDescription": "一键充值,轻松处理",
"rechargeNow": "立即充值",
"renew": "续订",
"renewSubscription": "续订",
"resetPrice": "重置价格",
"resetTraffic": "重置流量",
"resetTrafficDescription": "仅重置本月的流量",
"resetTrafficTitle": "重置流量",
"selectSubscription": "选择订阅",
"subscriptionDiscount": "订阅折扣"
}

View File

@ -12,6 +12,7 @@
"manualImportMessage": "該應用暫不支援喚起,請手動導入,已自動複製訂閱地址",
"mySubscriptions": "我的訂閱",
"nextResetDays": "下次重置/天",
"noLimit": "無限制",
"prompt": "提示",
"purchaseSubscription": "購買訂閱",
"qrCode": "QR碼",

View File

@ -1,25 +1,14 @@
{
"Day": "日",
"Hour": "時",
"Minute": "分鐘",
"Month": "月",
"Year": "年",
"balanceRecharge": "餘額儲值",
"buyNow": "立即購買",
"buySubscription": "購買訂閱",
"cancel": "取消",
"createdAt": "建立時間",
"description": "一鍵充值,輕鬆搞定",
"detail": "詳情",
"enterAmount": "請輸入充值金額",
"enterCoupon": "請輸入折扣碼",
"goToPayment": "前往付款",
"methods": {
"alipay_f2f": "支付寶(面對面)",
"alipay_f2f": "支付寶(面對面)",
"balance": "餘額",
"epay": "支付",
"stripe_alipay": "Stripe(支付寶)",
"stripe_wechat_pay": "Stripe(微信)"
"epay": "電子支付",
"stripe_alipay": "Stripe(支付寶)",
"stripe_wechat_pay": "Stripe(微信支付)"
},
"name": "名稱",
"orderClosed": "訂單已關閉",
@ -31,16 +20,6 @@
"paymentMethod": "付款方式",
"paymentSuccess": "付款成功",
"productList": "產品列表",
"purchaseDuration": "購買時長",
"recharge": "儲值",
"rechargeAmount": "儲值金額",
"rechargeNow": "立即儲值",
"renew": "續費",
"renewSubscription": "續費訂閱",
"resetPrice": "重設價格",
"resetTraffic": "重設流量",
"resetTrafficDescription": "僅重置當月流量哦",
"resetTrafficTitle": "重設流量",
"scanToPay": "請掃碼支付",
"status": {
"0": "狀態",

View File

@ -3,8 +3,10 @@
"Hour": "時",
"Minute": "分鐘",
"Month": "月",
"NoLimit": "無限制",
"Year": "年",
"all": "全部",
"balanceRecharge": "餘額充值",
"billing": {
"billingTitle": "商品帳單",
"couponDiscount": "折扣碼優惠",
@ -15,13 +17,18 @@
"total": "總價"
},
"buy": "購買",
"buyNow": "立即購買",
"buySubscription": "購買訂閱",
"category": "類別",
"coupon": "優惠券",
"detail": {
"availableTraffic": "可用流量",
"connectedDevices": "同時連接 IP 數",
"connectionSpeed": "連接速度",
"productDetail": "商品詳情"
},
"enterAmount": "輸入充值金額",
"enterCoupon": "輸入優惠券代碼",
"methods": {
"alipay_f2f": "支付寶(面對面)",
"balance": "餘額",
@ -29,6 +36,20 @@
"stripe_alipay": "Stripe(支付寶)",
"stripe_wechat_pay": "Stripe(微信)"
},
"paymentMethod": "付款方式",
"productDescription": "商品描述",
"products": "產品"
"products": "產品",
"purchaseDuration": "購買期限",
"recharge": "充值",
"rechargeAmount": "充值金額",
"rechargeDescription": "一鍵充值,輕鬆處理",
"rechargeNow": "立即充值",
"renew": "續期",
"renewSubscription": "續訂",
"resetPrice": "重設價格",
"resetTraffic": "重設流量",
"resetTrafficDescription": "僅重設本月的流量",
"resetTrafficTitle": "重設流量",
"selectSubscription": "選擇訂閱",
"subscriptionDiscount": "訂閱折扣"
}

View File

@ -173,6 +173,8 @@ declare namespace API {
trade_no: string;
status: number;
subscribe_id: number;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
@ -194,6 +196,8 @@ declare namespace API {
status: number;
subscribe_id: number;
subscribe: Subscribe;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};

View File

@ -195,6 +195,8 @@ declare namespace API {
trade_no: string;
status: number;
subscribe_id: number;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
@ -216,6 +218,8 @@ declare namespace API {
status: number;
subscribe_id: number;
subscribe: Subscribe;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
@ -240,6 +244,7 @@ declare namespace API {
coupon: string;
coupon_discount: number;
fee_amount: number;
discount_list: SubscribeDiscountInfo[];
};
type PreRenewalOrderResponse = {
@ -251,6 +256,7 @@ declare namespace API {
quantity: number;
payment: string;
coupon?: string;
discount_subscribe_id: number;
};
type PurchaseOrderResponse = {
@ -364,6 +370,7 @@ declare namespace API {
payment: string;
coupon?: string;
subscribe_token: string;
discount_subscribe_id: number;
};
type RenewalOrderResponse = {
@ -496,6 +503,13 @@ declare namespace API {
discount: number;
};
type SubscribeDiscountInfo = {
id: number;
name: string;
price: number;
expire_time: string;
};
type SubscribeGroup = {
id: number;
name: string;

View File

@ -17,6 +17,7 @@ import * as React from 'react';
export type Option<T = string> = {
value: T;
label: string;
children?: React.ReactNode;
};
// Conditional types to determine the value type for onChange
@ -98,11 +99,11 @@ export function Combobox<T, M extends boolean = false>({
<CommandList>
{options.map((option) => (
<CommandItem
key={String(option.label)}
key={String(option.label + option.value)}
value={option.label}
onSelect={() => handleSelect(option.value)}
>
{option.label}
{option.children || option.label}
<CheckIcon
className={cn(
'ml-auto h-4 w-4',

View File

@ -1,32 +1,9 @@
import { startOfMonth } from 'date-fns';
export * from '@workspace/ui/utils/countries';
export * from '@workspace/ui/utils/formatting';
export * from '@workspace/ui/utils/unit-conversions';
export const isBrowser = () => typeof window !== 'undefined';
export function getNextResetDate(startDate: Date | number) {
const time = new Date(startDate);
const resetDay = time.getDate();
const currentDate = new Date();
if (isNaN(time.getTime())) {
throw new Error('Invalid start date');
}
if (currentDate.getDate() >= resetDay) {
const startOfMonthNextReset = startOfMonth(currentDate);
startOfMonthNextReset.setMonth(startOfMonthNextReset.getMonth() + 1);
startOfMonthNextReset.setDate(resetDay);
startOfMonthNextReset.setHours(time.getHours());
startOfMonthNextReset.setMinutes(time.getMinutes());
startOfMonthNextReset.setSeconds(time.getSeconds());
return startOfMonthNextReset;
} else {
time.setMonth(currentDate.getMonth());
return time;
}
}
/**
* Extracts the full domain or root domain from a URL.
*