Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa1d42651d | |||
| 0c8f0911c7 | |||
| db0d9e003e | |||
| f219c52306 | |||
| 3f7b6d16ed | |||
| 6dbebd152d | |||
| bb3bd7b50c | |||
| fbad3b0e51 | |||
| e551232564 | |||
| bf58f25072 | |||
| 85f55def2e | |||
| 29bc3c7722 | |||
| f72df3a5e8 | |||
| 48a1b97051 | |||
| 786ba0e41c | |||
| ce3197298d | |||
| 092477b2d3 | |||
| b8316bba33 | |||
| dddc21c686 | |||
| d10ecc9fdf | |||
| 94822d902f | |||
| 85fdc36c14 | |||
| cfa3fc024d | |||
| c06ea49d6f | |||
| c3138a863d | |||
| 7fa3a57df4 | |||
| 70d6a38a29 | |||
| 5c710e1add | |||
| 6752420ba5 | |||
| 710947209a | |||
| fc0da761b5 | |||
| 136a1abd8b | |||
| a5e2079ddc | |||
| 35f92c9329 | |||
| f5d8fd3b65 | |||
| 0c907337e1 | |||
| e4630f8ca9 | |||
| 2215c7f2b9 | |||
| 3222016799 | |||
| d0a04679ce | |||
| d2732e650b | |||
| 79edea7973 | |||
| f17bf8db6e | |||
| 047a69886e | |||
| 71bf002370 | |||
| d0e6df044e | |||
| 8e16ef17ed | |||
| 2b80496637 | |||
| 01a3aa02ec | |||
| 35210fe8cf | |||
| d5847faeda | |||
| 0130e02ffd | |||
| c2b858e3fe | |||
| e11f18c034 | |||
| 2ca299224d |
+184
-14
@@ -1,33 +1,203 @@
|
||||
<a name="readme-top"></a>
|
||||
# Changelog
|
||||
|
||||
# [1.0.0-beta.23](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.22...v1.0.0-beta.23) (2025-02-24)
|
||||
# [1.0.0-beta.31](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.30...v1.0.0-beta.31) (2025-03-15)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
* **auth**: Update email verification logic to use domain suffix check ([62662bb](https://github.com/perfect-panel/ppanel-web/commit/62662bb))
|
||||
* **site**: Se ref to store site configuration for updates ([0c8f091](https://github.com/perfect-panel/ppanel-web/commit/0c8f091))
|
||||
|
||||
# [1.0.0-beta.22](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.21...v1.0.0-beta.22) (2025-02-23)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
* **locales**: Removed language file import to clean up unnecessary language support ([68f6ab2](https://github.com/perfect-panel/ppanel-web/commit/68f6ab2))
|
||||
|
||||
# [1.0.0-beta.21](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.20...v1.0.0-beta.21) (2025-02-23)
|
||||
# [1.0.0-beta.30](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.29...v1.0.0-beta.30) (2025-03-15)
|
||||
|
||||
|
||||
### ✨ Features
|
||||
|
||||
* **privacy-policy**: Add privacy policy related text and links ([baa68f0](https://github.com/perfect-panel/ppanel-web/commit/baa68f0))
|
||||
* **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([48a1b97](https://github.com/perfect-panel/ppanel-web/commit/48a1b97))
|
||||
* **email**: Add traffic exhaustion template ([bb3bd7b](https://github.com/perfect-panel/ppanel-web/commit/bb3bd7b))
|
||||
* **formatting**: Update differenceInDays function to return whole days or two decimal places ([bf58f25](https://github.com/perfect-panel/ppanel-web/commit/bf58f25))
|
||||
* **global**: Add custom data ([6dbebd1](https://github.com/perfect-panel/ppanel-web/commit/6dbebd1))
|
||||
* **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([ce31972](https://github.com/perfect-panel/ppanel-web/commit/ce31972))
|
||||
* **loading**: Replace loading animation with a simpler spinner and loading text ([f72df3a](https://github.com/perfect-panel/ppanel-web/commit/f72df3a))
|
||||
* **node-form**: Update number input fields to enforce step, min, and max values ([3f7b6d1](https://github.com/perfect-panel/ppanel-web/commit/3f7b6d1))
|
||||
* **payment**: Add isEdit prop to PaymentForm and disable fields when editing ([85f55de](https://github.com/perfect-panel/ppanel-web/commit/85f55de))
|
||||
* **timeline**: Simplify timeline component layout and remove commented-out code ([fbad3b0](https://github.com/perfect-panel/ppanel-web/commit/fbad3b0))
|
||||
|
||||
|
||||
### 🎫 Chores
|
||||
|
||||
* **release**: V1.0.0-beta.27 [skip ci] ([092477b](https://github.com/perfect-panel/ppanel-web/commit/092477b))
|
||||
* **release**: V1.0.0-beta.28 [skip ci] ([786ba0e](https://github.com/perfect-panel/ppanel-web/commit/786ba0e))
|
||||
* Merge branch 'beta' into develop ([f219c52](https://github.com/perfect-panel/ppanel-web/commit/f219c52))
|
||||
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
* **locales**: Removed multilingual files to clean up unnecessary language support ([5b151cd](https://github.com/perfect-panel/ppanel-web/commit/5b151cd))
|
||||
* **locales**: Update custom HTML description in language file, ([87381da](https://github.com/perfect-panel/ppanel-web/commit/87381da))
|
||||
* **table**: Update privacy policy tab translation key and remove unnecessary requestType from OAuth callback ([14b3af5](https://github.com/perfect-panel/ppanel-web/commit/14b3af5))
|
||||
* **dashboard**: Update date display to use start_time if available ([e551232](https://github.com/perfect-panel/ppanel-web/commit/e551232))
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
# Changelog
|
||||
|
||||
# [1.0.0-beta.29](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.28...v1.0.0-beta.29) (2025-03-14)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([dddc21c](https://github.com/perfect-panel/ppanel-web/commit/dddc21c))
|
||||
- **loading**: Replace loading animation with a simpler spinner and loading text ([b8316bb](https://github.com/perfect-panel/ppanel-web/commit/b8316bb))
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
# Changelog
|
||||
|
||||
# [1.0.0-beta.28](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.27...v1.0.0-beta.28) (2025-03-13)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([94822d9](https://github.com/perfect-panel/ppanel-web/commit/94822d9))
|
||||
|
||||
# [1.0.0-beta.27](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.26...v1.0.0-beta.27) (2025-03-13)
|
||||
|
||||
### ♻ Code Refactoring
|
||||
|
||||
- **payment**: Reconstruct the payment page ([7109472](https://github.com/perfect-panel/ppanel-web/commit/7109472))
|
||||
- Enhance user navigation dropdown ui and styling ([d2732e6](https://github.com/perfect-panel/ppanel-web/commit/d2732e6))
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **cdn**: Add CDN URL configuration and update related references ([0c90733](https://github.com/perfect-panel/ppanel-web/commit/0c90733))
|
||||
- **payment**: Add bank card payment ([7fa3a57](https://github.com/perfect-panel/ppanel-web/commit/7fa3a57))
|
||||
- **subscription**: Improve layout and organization of subscription detail tabs ([e4630f8](https://github.com/perfect-panel/ppanel-web/commit/e4630f8))
|
||||
- **subscription**: Refactor subscription handling and update imports for better organization ([2215c7f](https://github.com/perfect-panel/ppanel-web/commit/2215c7f))
|
||||
|
||||
### 🎫 Chores
|
||||
|
||||
- **merge**: Bump version to 1.0.0-beta.26 and update changelog ([3222016](https://github.com/perfect-panel/ppanel-web/commit/3222016))
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **affiliate**: Update user identifier ([35f92c9](https://github.com/perfect-panel/ppanel-web/commit/35f92c9))
|
||||
- **changelog**: Update change log style ([cfa3fc0](https://github.com/perfect-panel/ppanel-web/commit/cfa3fc0))
|
||||
- **payment**: Add notification URL field to payment management interface ([5c710e1](https://github.com/perfect-panel/ppanel-web/commit/5c710e1))
|
||||
- **payment**: Fix payment related type definitions and update payment method references ([c3138a8](https://github.com/perfect-panel/ppanel-web/commit/c3138a8))
|
||||
- **payment**: Refactor purchaseCheckout usage and remove redundant code ([a5e2079](https://github.com/perfect-panel/ppanel-web/commit/a5e2079))
|
||||
- **payment**: Update checkout type from 'link' to 'url' for consistency ([136a1ab](https://github.com/perfect-panel/ppanel-web/commit/136a1ab))
|
||||
- **payment**: Update payment information ([70d6a38](https://github.com/perfect-panel/ppanel-web/commit/70d6a38))
|
||||
- **payment**: Update payment method update logic to include row data ([6752420](https://github.com/perfect-panel/ppanel-web/commit/6752420))
|
||||
- **purchasing**: Update payment type to lowercase and add optional chaining for discounts ([c06ea49](https://github.com/perfect-panel/ppanel-web/commit/c06ea49))
|
||||
- **ui**: Improve dashboard layout and enhance button functionality; open checkout URLs in a new tab ([fc0da76](https://github.com/perfect-panel/ppanel-web/commit/fc0da76))
|
||||
- **ui**: Multiple display bugs ([f5d8fd3](https://github.com/perfect-panel/ppanel-web/commit/f5d8fd3))
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
# Changelog
|
||||
|
||||
# [1.0.0-beta.28](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.27...v1.0.0-beta.28) (2025-03-13)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([94822d9](https://github.com/perfect-panel/ppanel-web/commit/94822d9))
|
||||
|
||||
# [1.0.0-beta.27](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.26...v1.0.0-beta.27) (2025-03-13)
|
||||
|
||||
### ♻ Code Refactoring
|
||||
|
||||
- **payment**: Reconstruct the payment page ([7109472](https://github.com/perfect-panel/ppanel-web/commit/7109472))
|
||||
- Enhance user navigation dropdown ui and styling ([d2732e6](https://github.com/perfect-panel/ppanel-web/commit/d2732e6))
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **cdn**: Add CDN URL configuration and update related references ([0c90733](https://github.com/perfect-panel/ppanel-web/commit/0c90733))
|
||||
- **payment**: Add bank card payment ([7fa3a57](https://github.com/perfect-panel/ppanel-web/commit/7fa3a57))
|
||||
- **subscription**: Improve layout and organization of subscription detail tabs ([e4630f8](https://github.com/perfect-panel/ppanel-web/commit/e4630f8))
|
||||
- **subscription**: Refactor subscription handling and update imports for better organization ([2215c7f](https://github.com/perfect-panel/ppanel-web/commit/2215c7f))
|
||||
|
||||
### 🎫 Chores
|
||||
|
||||
- **merge**: Bump version to 1.0.0-beta.26 and update changelog ([3222016](https://github.com/perfect-panel/ppanel-web/commit/3222016))
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **affiliate**: Update user identifier ([35f92c9](https://github.com/perfect-panel/ppanel-web/commit/35f92c9))
|
||||
- **changelog**: Update change log style ([cfa3fc0](https://github.com/perfect-panel/ppanel-web/commit/cfa3fc0))
|
||||
- **payment**: Add notification URL field to payment management interface ([5c710e1](https://github.com/perfect-panel/ppanel-web/commit/5c710e1))
|
||||
- **payment**: Fix payment related type definitions and update payment method references ([c3138a8](https://github.com/perfect-panel/ppanel-web/commit/c3138a8))
|
||||
- **payment**: Refactor purchaseCheckout usage and remove redundant code ([a5e2079](https://github.com/perfect-panel/ppanel-web/commit/a5e2079))
|
||||
- **payment**: Update checkout type from 'link' to 'url' for consistency ([136a1ab](https://github.com/perfect-panel/ppanel-web/commit/136a1ab))
|
||||
- **payment**: Update payment information ([70d6a38](https://github.com/perfect-panel/ppanel-web/commit/70d6a38))
|
||||
- **payment**: Update payment method update logic to include row data ([6752420](https://github.com/perfect-panel/ppanel-web/commit/6752420))
|
||||
- **purchasing**: Update payment type to lowercase and add optional chaining for discounts ([c06ea49](https://github.com/perfect-panel/ppanel-web/commit/c06ea49))
|
||||
- **ui**: Improve dashboard layout and enhance button functionality; open checkout URLs in a new tab ([fc0da76](https://github.com/perfect-panel/ppanel-web/commit/fc0da76))
|
||||
- **ui**: Multiple display bugs ([f5d8fd3](https://github.com/perfect-panel/ppanel-web/commit/f5d8fd3))
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
# Changelog
|
||||
|
||||
# [1.0.0-beta.26](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.25...v1.0.0-beta.26) (2025-03-02)
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **icon**: Comment out unused icon collection imports ([f17bf8d](https://github.com/perfect-panel/ppanel-web/commit/f17bf8d))
|
||||
|
||||
# [1.0.0-beta.25](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.24...v1.0.0-beta.25) (2025-03-01)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **auth**: Add privacy policy link to the footer ([8e16ef1](https://github.com/perfect-panel/ppanel-web/commit/8e16ef1))
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **dashboard**: Display subscription creation date in user dashboard ([d0e6df0](https://github.com/perfect-panel/ppanel-web/commit/d0e6df0))
|
||||
- **request**: Add error code 40005 to trigger logout ([71bf002](https://github.com/perfect-panel/ppanel-web/commit/71bf002))
|
||||
- **subscribe**: Update payment return URL ([2b80496](https://github.com/perfect-panel/ppanel-web/commit/2b80496))
|
||||
|
||||
# [1.0.0-beta.24](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.23...v1.0.0-beta.24) (2025-02-27)
|
||||
|
||||
### ♻ Code Refactoring
|
||||
|
||||
- **ui**: Optimize document display ([2ca2992](https://github.com/perfect-panel/ppanel-web/commit/2ca2992))
|
||||
- Reduce code complexity and improve readability ([e11f18c](https://github.com/perfect-panel/ppanel-web/commit/e11f18c))
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **loading**: Add loading components and integrate them in Providers ([d5847fa](https://github.com/perfect-panel/ppanel-web/commit/d5847fa))
|
||||
|
||||
### 🎫 Chores
|
||||
|
||||
- **merge**: Add advertising module and device settings ([0130e02](https://github.com/perfect-panel/ppanel-web/commit/0130e02))
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **locales**: Order recharge related fields ([35210fe](https://github.com/perfect-panel/ppanel-web/commit/35210fe))
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
# Changelog
|
||||
|
||||
# [1.0.0-beta.23](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.22...v1.0.0-beta.23) (2025-02-24)
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **auth**: Update email verification logic to use domain suffix check ([62662bb](https://github.com/perfect-panel/ppanel-web/commit/62662bb))
|
||||
|
||||
# [1.0.0-beta.22](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.21...v1.0.0-beta.22) (2025-02-23)
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **locales**: Removed language file import to clean up unnecessary language support ([68f6ab2](https://github.com/perfect-panel/ppanel-web/commit/68f6ab2))
|
||||
|
||||
# [1.0.0-beta.21](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.20...v1.0.0-beta.21) (2025-02-23)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **privacy-policy**: Add privacy policy related text and links ([baa68f0](https://github.com/perfect-panel/ppanel-web/commit/baa68f0))
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **locales**: Removed multilingual files to clean up unnecessary language support ([5b151cd](https://github.com/perfect-panel/ppanel-web/commit/5b151cd))
|
||||
- **locales**: Update custom HTML description in language file, ([87381da](https://github.com/perfect-panel/ppanel-web/commit/87381da))
|
||||
- **table**: Update privacy policy tab translation key and remove unnecessary requestType from OAuth callback ([14b3af5](https://github.com/perfect-panel/ppanel-web/commit/14b3af5))
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@workspace/ui/components/form';
|
||||
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
|
||||
import { ScrollArea } from '@workspace/ui/components/scroll-area';
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetFooter,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from '@workspace/ui/components/sheet';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { Icon } from '@workspace/ui/custom-components/icon';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
const formSchema = z.object({
|
||||
title: z.string(),
|
||||
type: z.enum(['image', 'video']),
|
||||
content: z.string(),
|
||||
description: z.string(),
|
||||
target_url: z.string().url(),
|
||||
start_time: z.number(),
|
||||
end_time: z.number(),
|
||||
});
|
||||
|
||||
interface AdsFormProps<T> {
|
||||
onSubmit: (data: T) => Promise<boolean> | boolean;
|
||||
initialValues?: T;
|
||||
loading?: boolean;
|
||||
trigger: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export default function AdsForm<T extends Record<string, any>>({
|
||||
onSubmit,
|
||||
initialValues,
|
||||
loading,
|
||||
trigger,
|
||||
title,
|
||||
}: AdsFormProps<T>) {
|
||||
const t = useTranslations('ads');
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const form = useForm({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
...initialValues,
|
||||
} as any,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
form?.reset(initialValues);
|
||||
}, [form, initialValues]);
|
||||
|
||||
const type = form.watch('type');
|
||||
const startTime = form.watch('start_time');
|
||||
|
||||
const renderContentField = () => {
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='content'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.content')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={
|
||||
type === 'image'
|
||||
? 'https://example.com/image.jpg'
|
||||
: 'https://example.com/video.mp4'
|
||||
}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue('content', value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
async function handleSubmit(data: { [x: string]: any }) {
|
||||
const bool = await onSubmit(data as T);
|
||||
if (bool) setOpen(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={setOpen}>
|
||||
<SheetTrigger asChild>
|
||||
<Button
|
||||
onClick={() => {
|
||||
form.reset();
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
{trigger}
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent className='w-[500px] max-w-full md:max-w-screen-md'>
|
||||
<SheetHeader>
|
||||
<SheetTitle>{title}</SheetTitle>
|
||||
</SheetHeader>
|
||||
<ScrollArea className='-mx-6 h-[calc(100vh-48px-36px-36px-env(safe-area-inset-top))]'>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(handleSubmit)} className='space-y-4 px-6 pt-4'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='title'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.title')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('form.enterTitle')}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue(field.name, value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='type'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.type')}</FormLabel>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
defaultValue={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue(field.name, value);
|
||||
}}
|
||||
className='flex gap-4'
|
||||
>
|
||||
<FormItem className='flex items-center space-x-3 space-y-0'>
|
||||
<FormControl>
|
||||
<RadioGroupItem value='image' />
|
||||
</FormControl>
|
||||
<FormLabel className='font-normal'>{t('form.typeImage')}</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className='flex items-center space-x-3 space-y-0'>
|
||||
<FormControl>
|
||||
<RadioGroupItem value='video' />
|
||||
</FormControl>
|
||||
<FormLabel className='font-normal'>{t('form.typeVideo')}</FormLabel>
|
||||
</FormItem>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{renderContentField()}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='description'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.description')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('form.enterDescription')}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue(field.name, value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='target_url'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.targetUrl')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('form.enterTargetUrl')}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue(field.name, value);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='start_time'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.startTime')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='datetime-local'
|
||||
placeholder={t('form.enterStartTime')}
|
||||
value={field.value ? new Date(field.value).toISOString().slice(0, 16) : ''}
|
||||
min={Number(new Date().toISOString().slice(0, 16))}
|
||||
onValueChange={(value) => {
|
||||
const timestamp = value ? new Date(value).getTime() : 0;
|
||||
form.setValue(field.name, timestamp);
|
||||
const endTime = form.getValues('end_time');
|
||||
if (endTime && timestamp > endTime) {
|
||||
form.setValue('end_time', '');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='end_time'
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>{t('form.endTime')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='datetime-local'
|
||||
placeholder={t('form.enterEndTime')}
|
||||
value={
|
||||
field.value ? new Date(field.value).toISOString().slice(0, 16) : ''
|
||||
}
|
||||
min={Number(
|
||||
startTime
|
||||
? new Date(startTime).toISOString().slice(0, 16)
|
||||
: new Date().toISOString().slice(0, 16),
|
||||
)}
|
||||
disabled={!startTime}
|
||||
onValueChange={(value) => {
|
||||
const timestamp = value ? new Date(value).getTime() : 0;
|
||||
if (!startTime || timestamp < startTime) return;
|
||||
form.setValue(field.name, timestamp);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
</ScrollArea>
|
||||
<SheetFooter className='flex-row justify-end gap-2 pt-3'>
|
||||
<Button
|
||||
variant='outline'
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{t('form.cancel')}
|
||||
</Button>
|
||||
<Button disabled={loading} onClick={form.handleSubmit(handleSubmit)}>
|
||||
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
|
||||
{t('form.confirm')}
|
||||
</Button>
|
||||
</SheetFooter>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
'use client';
|
||||
|
||||
import { ProTable, ProTableActions } from '@/components/pro-table';
|
||||
import { createAds, deleteAds, getAdsList, updateAds } from '@/services/admin/ads';
|
||||
import { Badge } from '@workspace/ui/components/badge';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRef, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import AdsForm from './ads-form';
|
||||
|
||||
export default function Page() {
|
||||
const t = useTranslations('ads');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const ref = useRef<ProTableActions>(null);
|
||||
|
||||
return (
|
||||
<ProTable<API.Ads, Record<string, unknown>>
|
||||
action={ref}
|
||||
header={{
|
||||
toolbar: (
|
||||
<AdsForm<API.CreateAdsRequest>
|
||||
trigger={t('create')}
|
||||
title={t('createAds')}
|
||||
loading={loading}
|
||||
onSubmit={async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await createAds({
|
||||
...values,
|
||||
status: 0,
|
||||
});
|
||||
toast.success(t('createSuccess'));
|
||||
ref.current?.refresh();
|
||||
setLoading(false);
|
||||
return true;
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
params={[
|
||||
{
|
||||
key: 'search',
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
placeholder: t('status'),
|
||||
options: [
|
||||
{ label: t('enabled'), value: '1' },
|
||||
{ label: t('disabled'), value: '0' },
|
||||
],
|
||||
},
|
||||
]}
|
||||
request={async (pagination, filters) => {
|
||||
const { data } = await getAdsList({
|
||||
...pagination,
|
||||
...filters,
|
||||
});
|
||||
return {
|
||||
list: data.data?.list || [],
|
||||
total: data.data?.total || 0,
|
||||
};
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
accessorKey: 'status',
|
||||
header: t('status'),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Switch
|
||||
defaultChecked={row.getValue('status') === 1}
|
||||
onCheckedChange={async (checked) => {
|
||||
await updateAds({
|
||||
...row.original,
|
||||
status: checked ? 1 : 0,
|
||||
});
|
||||
ref.current?.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'title',
|
||||
header: t('title'),
|
||||
},
|
||||
{
|
||||
accessorKey: 'type',
|
||||
header: t('type'),
|
||||
cell: ({ row }) => {
|
||||
const type = row.original.type;
|
||||
return <Badge>{type}</Badge>;
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'target_url',
|
||||
header: t('targetUrl'),
|
||||
},
|
||||
{
|
||||
accessorKey: 'description',
|
||||
header: t('form.description'),
|
||||
},
|
||||
{
|
||||
accessorKey: 'period',
|
||||
header: t('validityPeriod'),
|
||||
cell: ({ row }) => {
|
||||
const { start_time, end_time } = row.original;
|
||||
return (
|
||||
<>
|
||||
{formatDate(start_time)} - {formatDate(end_time)}
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
actions={{
|
||||
render: (row) => [
|
||||
<AdsForm<API.UpdateAdsRequest>
|
||||
key='edit'
|
||||
trigger={t('edit')}
|
||||
title={t('editAds')}
|
||||
loading={loading}
|
||||
initialValues={row}
|
||||
onSubmit={async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await updateAds({ ...row, ...values });
|
||||
toast.success(t('updateSuccess'));
|
||||
ref.current?.refresh();
|
||||
setLoading(false);
|
||||
return true;
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
}}
|
||||
/>,
|
||||
<ConfirmButton
|
||||
key='delete'
|
||||
trigger={<Button variant='destructive'>{t('delete')}</Button>}
|
||||
title={t('confirmDelete')}
|
||||
description={t('deleteWarning')}
|
||||
onConfirm={async () => {
|
||||
await deleteAds({ id: row.id });
|
||||
toast.success(t('deleteSuccess'));
|
||||
ref.current?.refresh();
|
||||
}}
|
||||
cancelText={t('cancel')}
|
||||
confirmText={t('confirm')}
|
||||
/>,
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -5,7 +5,10 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { DicesIcon } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { uid } from 'radash';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function Page() {
|
||||
@@ -49,6 +52,89 @@ export default function Page() {
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('showAds')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('showAdsDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.config?.show_ads}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
show_ads: checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('blockVirtualMachine')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('blockVirtualMachineDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.config?.only_real_device}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
only_real_device: checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('enableSecurity')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('enableSecurityDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.config?.enable_security}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
enable_security: checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('communicationKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('communicationKeyDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
value={data?.config?.security_secret}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
security_secret: value,
|
||||
});
|
||||
}}
|
||||
suffix={
|
||||
<div className='bg-muted flex h-9 items-center text-nowrap px-3'>
|
||||
<DicesIcon
|
||||
onClick={() => {
|
||||
const id = uid(32).toLowerCase();
|
||||
const formatted = `${id.slice(0, 8)}-${id.slice(8, 12)}-${id.slice(12, 16)}-${id.slice(16, 20)}-${id.slice(20)}`;
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
security_secret: formatted,
|
||||
});
|
||||
}}
|
||||
className='cursor-pointer'
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
|
||||
@@ -286,9 +286,13 @@ export default function Page() {
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value='template'>
|
||||
<div className='grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'>
|
||||
{['verify_email_template', 'expiration_email_template', 'maintenance_email_template'].map(
|
||||
(templateKey) => (
|
||||
<div className='grid grid-cols-1 gap-4 md:grid-cols-2'>
|
||||
{[
|
||||
'verify_email_template',
|
||||
'expiration_email_template',
|
||||
'maintenance_email_template',
|
||||
'traffic_exceed_email_template',
|
||||
].map((templateKey) => (
|
||||
<Card key={templateKey}>
|
||||
<CardHeader>
|
||||
<CardTitle>{t(`${templateKey}`)}</CardTitle>
|
||||
@@ -309,8 +313,7 @@ export default function Page() {
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
),
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ export default function Page(props: any) {
|
||||
<ul className='grid gap-3'>
|
||||
<li className='flex items-center justify-between'>
|
||||
<span className='text-muted-foreground'>{t('method')}</span>
|
||||
<span>{t(`methods.${row.original.method}`)}</span>
|
||||
<span>{row.original?.payment?.name || row.original?.payment?.platform}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</HoverCardContent>
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { getAlipayF2FPaymentConfig, updateAlipayF2FPaymentConfig } from '@/services/admin/payment';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@workspace/ui/components/select';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
|
||||
import { Textarea } from '@workspace/ui/components/textarea';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { unitConversion } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function AlipayF2F() {
|
||||
const t = useTranslations('payment');
|
||||
|
||||
const { data, refetch } = useQuery({
|
||||
queryKey: ['getAlipayF2FPaymentConfig'],
|
||||
queryFn: async () => {
|
||||
const { data } = await getAlipayF2FPaymentConfig();
|
||||
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
|
||||
async function updateConfig(key: string, value: unknown) {
|
||||
if (data?.[key] === value) return;
|
||||
try {
|
||||
await updateAlipayF2FPaymentConfig({
|
||||
...data,
|
||||
[key]: value,
|
||||
} as API.UpdateAlipayF2fRequest);
|
||||
toast.success(t('saveSuccess'));
|
||||
refetch();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('enable')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('enableDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.enable}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig('enable', checked);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('alipayf2f.sandbox')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('alipayf2f.sandboxDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.config.sandbox}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
sandbox: checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('showName')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('showNameDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.name}
|
||||
onValueBlur={(value) => updateConfig('name', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('iconUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('iconUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.icon_url}
|
||||
onValueBlur={(value) => updateConfig('icon', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('notifyUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('notifyUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.domain}
|
||||
onValueBlur={(value) => updateConfig('domain', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feeMode')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feeModeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Select
|
||||
value={String(data?.fee_mode)}
|
||||
onValueChange={(value) => {
|
||||
updateConfig('fee_mode', Number(value));
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='请选择' />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value='0'>{t('feeModeItems.0')}</SelectItem>
|
||||
<SelectItem value='1'>{t('feeModeItems.1')}</SelectItem>
|
||||
<SelectItem value='2'>{t('feeModeItems.2')}</SelectItem>
|
||||
<SelectItem value='3'>{t('feeModeItems.3')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feePercent')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feePercentDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
max={100}
|
||||
maxLength={3}
|
||||
value={data?.fee_percent}
|
||||
onValueBlur={(value) => updateConfig('fee_percent', value)}
|
||||
suffix='%'
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('fixedFee')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('fixedFeeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
min={0}
|
||||
value={data?.fee_amount}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
formatOutput={(value) => unitConversion('dollarsToCents', value)}
|
||||
onValueBlur={(value) => updateConfig('fee_amount', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('alipayf2f.appId')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.app_id}
|
||||
onValueBlur={(value) =>
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
app_id: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('alipayf2f.privateKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Textarea
|
||||
placeholder={t('inputPlaceholder')}
|
||||
defaultValue={data?.config.private_key}
|
||||
onBlur={(e) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
private_key: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('alipayf2f.publicKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Textarea
|
||||
placeholder={t('inputPlaceholder')}
|
||||
defaultValue={data?.config.public_key}
|
||||
onBlur={(e) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
public_key: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('alipayf2f.invoiceName')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('alipayf2f.invoiceNameDescription')}
|
||||
value={data?.config.invoice_name}
|
||||
onValueBlur={(value) =>
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
invoice_name: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { getEpayPaymentConfig, updateEpayPaymentConfig } from '@/services/admin/payment';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@workspace/ui/components/select';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { unitConversion } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function Epay() {
|
||||
const t = useTranslations('payment');
|
||||
|
||||
const { data, refetch } = useQuery({
|
||||
queryKey: ['getEpayPaymentConfig'],
|
||||
queryFn: async () => {
|
||||
const { data } = await getEpayPaymentConfig();
|
||||
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
|
||||
async function updateConfig(key: string, value: unknown) {
|
||||
if (data?.[key] === value) return;
|
||||
try {
|
||||
await updateEpayPaymentConfig({
|
||||
...data,
|
||||
[key]: value,
|
||||
} as API.UpdateEpayRequest);
|
||||
toast.success(t('saveSuccess'));
|
||||
refetch();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('enable')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('enableDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.enable}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig('enable', checked);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('showName')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('showNameDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.name}
|
||||
onValueBlur={(value) => updateConfig('name', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('iconUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('iconUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.icon}
|
||||
onValueBlur={(value) => updateConfig('icon', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('notifyUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('notifyUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.domain}
|
||||
onValueBlur={(value) => updateConfig('domain', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feeMode')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feeModeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Select
|
||||
value={String(data?.fee_mode)}
|
||||
onValueChange={(value) => {
|
||||
updateConfig('fee_mode', Number(value));
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='请选择' />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value='0'>{t('feeModeItems.0')}</SelectItem>
|
||||
<SelectItem value='1'>{t('feeModeItems.1')}</SelectItem>
|
||||
<SelectItem value='2'>{t('feeModeItems.2')}</SelectItem>
|
||||
<SelectItem value='3'>{t('feeModeItems.3')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feePercent')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feePercentDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
max={100}
|
||||
maxLength={3}
|
||||
value={data?.fee_percent}
|
||||
onValueBlur={(value) => updateConfig('fee_percent', value)}
|
||||
suffix='%'
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('fixedFee')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('fixedFeeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
value={data?.fee_amount}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
formatOutput={(value) => unitConversion('dollarsToCents', value)}
|
||||
onValueBlur={(value) => updateConfig('fee_amount', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('epay.url')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.url}
|
||||
onValueBlur={(value) =>
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
url: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('epay.pid')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.pid}
|
||||
onValueBlur={(value) =>
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
pid: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('epay.key')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.key}
|
||||
onValueBlur={(value) =>
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
key: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -1,34 +1,11 @@
|
||||
import Billing from '@/components/billing';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
|
||||
import AlipayF2F from './alipayf2f';
|
||||
import Epay from './epay';
|
||||
import StripeAlipay from './stripe-alipay';
|
||||
import StripeWeChatPay from './stripe-wechat-pay';
|
||||
import PaymentTable from './payment-table';
|
||||
|
||||
export default async function Page() {
|
||||
return (
|
||||
<>
|
||||
<Tabs defaultValue='Epay'>
|
||||
<TabsList className='h-full flex-wrap'>
|
||||
<TabsTrigger value='Epay'>Epay</TabsTrigger>
|
||||
<TabsTrigger value='Stripe-Alipay'>Stripe(AliPay)</TabsTrigger>
|
||||
<TabsTrigger value='Strip-WeChatPay'>Stripe(WeChatPay)</TabsTrigger>
|
||||
<TabsTrigger value='AlipayF2F'>AlipayF2F</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value='Epay'>
|
||||
<Epay />
|
||||
</TabsContent>
|
||||
<TabsContent value='Stripe-Alipay'>
|
||||
<StripeAlipay />
|
||||
</TabsContent>
|
||||
<TabsContent value='Strip-WeChatPay'>
|
||||
<StripeWeChatPay />
|
||||
</TabsContent>
|
||||
<TabsContent value='AlipayF2F'>
|
||||
<AlipayF2F />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
<div className='flex flex-col gap-3'>
|
||||
<PaymentTable />
|
||||
<div className='mt-5 flex flex-col gap-3'>
|
||||
<Billing type='payment' />
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
'use client';
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { getPaymentPlatform } from '@/services/admin/payment';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@workspace/ui/components/form';
|
||||
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
|
||||
import { ScrollArea } from '@workspace/ui/components/scroll-area';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@workspace/ui/components/select';
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetFooter,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from '@workspace/ui/components/sheet';
|
||||
import { MarkdownEditor } from '@workspace/ui/custom-components/editor';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { Icon } from '@workspace/ui/custom-components/icon';
|
||||
import { unitConversion } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import * as z from 'zod';
|
||||
|
||||
interface PaymentFormProps<T> {
|
||||
trigger: React.ReactNode;
|
||||
title: string;
|
||||
loading?: boolean;
|
||||
initialValues?: T;
|
||||
onSubmit: (values: T) => Promise<boolean>;
|
||||
isEdit?: boolean;
|
||||
}
|
||||
|
||||
export default function PaymentForm<T>({
|
||||
trigger,
|
||||
title,
|
||||
loading,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
isEdit,
|
||||
}: PaymentFormProps<T>) {
|
||||
const t = useTranslations('payment');
|
||||
const { common } = useGlobalStore();
|
||||
const { currency } = common;
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { data: platformData } = useQuery({
|
||||
queryKey: ['getPaymentPlatform'],
|
||||
queryFn: async () => {
|
||||
const { data } = await getPaymentPlatform();
|
||||
return data?.data?.list || [];
|
||||
},
|
||||
});
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(1, { message: t('nameRequired') }),
|
||||
platform: z.string().optional(),
|
||||
icon: z.string().optional(),
|
||||
domain: z.string().optional(),
|
||||
config: z.any(),
|
||||
fee_mode: z.coerce.number().min(0).max(2),
|
||||
fee_percent: z.coerce.number().optional(),
|
||||
fee_amount: z.coerce.number().optional(),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: '',
|
||||
platform: '',
|
||||
icon: '',
|
||||
domain: '',
|
||||
config: {},
|
||||
fee_mode: 0,
|
||||
fee_percent: 0,
|
||||
fee_amount: 0,
|
||||
...(initialValues as any),
|
||||
},
|
||||
});
|
||||
|
||||
const feeMode = form.watch('fee_mode');
|
||||
const platformValue = form.watch('platform');
|
||||
const configValues = form.watch('config');
|
||||
|
||||
const currentPlatform = platformData?.find((p) => p.platform === platformValue);
|
||||
const currentFieldDescriptions = currentPlatform?.platform_field_description || {};
|
||||
const configFields = Object.keys(currentFieldDescriptions) || [];
|
||||
const platformUrl = currentPlatform?.platform_url || '';
|
||||
|
||||
useEffect(() => {
|
||||
if (feeMode === 0) {
|
||||
form.setValue('fee_amount', 0);
|
||||
form.setValue('fee_percent', 0);
|
||||
} else if (feeMode === 1) {
|
||||
form.setValue('fee_amount', 0);
|
||||
} else if (feeMode === 2) {
|
||||
form.setValue('fee_percent', 0);
|
||||
}
|
||||
}, [feeMode, form]);
|
||||
|
||||
const handleClose = () => {
|
||||
form.reset();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleSubmit = async (values: z.infer<typeof formSchema>) => {
|
||||
const cleanedValues = { ...values };
|
||||
|
||||
if (values.fee_mode === 0) {
|
||||
cleanedValues.fee_amount = undefined;
|
||||
cleanedValues.fee_percent = undefined;
|
||||
} else if (values.fee_mode === 1) {
|
||||
cleanedValues.fee_amount = undefined;
|
||||
} else if (values.fee_mode === 2) {
|
||||
cleanedValues.fee_percent = undefined;
|
||||
}
|
||||
|
||||
const success = await onSubmit(cleanedValues as unknown as T);
|
||||
if (success) {
|
||||
handleClose();
|
||||
}
|
||||
};
|
||||
|
||||
const openPlatformUrl = () => {
|
||||
if (platformUrl) {
|
||||
window.open(platformUrl, '_blank');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={setOpen}>
|
||||
<SheetTrigger asChild>{trigger}</SheetTrigger>
|
||||
<SheetContent className='w-[550px] max-w-full md:max-w-screen-md'>
|
||||
<SheetHeader>
|
||||
<SheetTitle>{title}</SheetTitle>
|
||||
</SheetHeader>
|
||||
<ScrollArea className='-mx-6 h-[calc(100vh-48px-36px-36px-env(safe-area-inset-top))]'>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(handleSubmit)} className='space-y-6 px-6 pt-4'>
|
||||
{/* 基本信息分组 */}
|
||||
<div className='space-y-4'>
|
||||
<div className='grid grid-cols-1 gap-4 sm:grid-cols-2'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='name'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('name')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('namePlaceholder')}
|
||||
value={field.value}
|
||||
onValueChange={(value) => form.setValue('name', value as string)}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='icon'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('icon')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('iconPlaceholder')}
|
||||
value={field.value}
|
||||
onValueChange={(value) => form.setValue('icon', value as string)}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='domain'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('domain')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('domainPlaceholder', { example: 'http(s)://example.com' })}
|
||||
value={field.value}
|
||||
onValueChange={(value) => form.setValue('domain', value as string)}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='space-y-4'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='fee_mode'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('handlingFee')}</FormLabel>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
onValueChange={(value) => field.onChange(parseInt(value))}
|
||||
value={field.value.toString()}
|
||||
className='flex flex-wrap gap-4'
|
||||
>
|
||||
<FormItem className='flex items-center space-x-2'>
|
||||
<FormControl>
|
||||
<RadioGroupItem value='0' />
|
||||
</FormControl>
|
||||
<FormLabel className='!mt-0 cursor-pointer'>{t('noFee')}</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className='flex items-center space-x-2'>
|
||||
<FormControl>
|
||||
<RadioGroupItem value='1' />
|
||||
</FormControl>
|
||||
<FormLabel className='!mt-0 cursor-pointer'>
|
||||
{t('percentFee')}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className='flex items-center space-x-2'>
|
||||
<FormControl>
|
||||
<RadioGroupItem value='2' />
|
||||
</FormControl>
|
||||
<FormLabel className='!mt-0 cursor-pointer'>{t('fixedFee')}</FormLabel>
|
||||
</FormItem>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{feeMode === 1 && (
|
||||
<div className='grid grid-cols-1 sm:w-1/2'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='fee_percent'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('feePercent')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='number'
|
||||
step='0.01'
|
||||
suffix='%'
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{feeMode === 2 && (
|
||||
<div className='grid grid-cols-1 sm:w-1/2'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='fee_amount'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('feeAmount')}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='number'
|
||||
step='0.01'
|
||||
prefix={currency.currency_symbol}
|
||||
suffix={currency.currency_unit}
|
||||
value={unitConversion('centsToDollars', field.value)}
|
||||
onValueChange={(value) =>
|
||||
field.onChange(unitConversion('dollarsToCents', value))
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='space-y-4'>
|
||||
{(!platformValue || platformData?.find((p) => p.platform === platformValue)) && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='platform'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('platform')}</FormLabel>
|
||||
<Select
|
||||
onValueChange={(value) => {
|
||||
form.setValue('platform', value as string);
|
||||
form.setValue('config', {});
|
||||
}}
|
||||
defaultValue={field.value}
|
||||
value={field.value}
|
||||
disabled={isEdit}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t('selectPlatform')} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{platformData?.map((platform) => (
|
||||
<SelectItem key={platform.platform} value={platform.platform}>
|
||||
{platform.platform}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{platformUrl ? (
|
||||
<div className='mt-1 flex justify-end'>
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='sm'
|
||||
className='h-6 px-2 text-xs'
|
||||
onClick={openPlatformUrl}
|
||||
>
|
||||
<Icon icon='tabler:external-link' className='mr-1 h-3 w-3' />
|
||||
{t('applyForPayment')}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className='mt-1 h-6'></div>
|
||||
)}
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{configFields.length > 0 && (
|
||||
<div className='mt-4 space-y-4'>
|
||||
{configFields.map((fieldKey) => (
|
||||
<FormItem key={fieldKey}>
|
||||
<FormLabel>{currentFieldDescriptions[fieldKey]}</FormLabel>
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
placeholder={t('configPlaceholder', {
|
||||
field: currentFieldDescriptions[fieldKey],
|
||||
})}
|
||||
value={
|
||||
configValues && configValues[fieldKey] !== undefined
|
||||
? configValues[fieldKey]
|
||||
: ''
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
const newConfig = { ...configValues };
|
||||
newConfig[fieldKey] = value;
|
||||
form.setValue('config', newConfig);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='description'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('description')}</FormLabel>
|
||||
<FormControl>
|
||||
<MarkdownEditor
|
||||
value={field.value}
|
||||
onChange={(value) => form.setValue(field.name, value as string)}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</ScrollArea>
|
||||
|
||||
<SheetFooter className='flex-row justify-end gap-2 pt-3'>
|
||||
<Button variant='outline' disabled={loading} onClick={handleClose}>
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
<Button disabled={loading} onClick={form.handleSubmit(handleSubmit)}>
|
||||
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
|
||||
{t('submit')}
|
||||
</Button>
|
||||
</SheetFooter>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
'use client';
|
||||
|
||||
import { Display } from '@/components/display';
|
||||
import { ProTable, ProTableActions } from '@/components/pro-table';
|
||||
import {
|
||||
createPaymentMethod,
|
||||
deletePaymentMethod,
|
||||
getPaymentMethodList,
|
||||
updatePaymentMethod,
|
||||
} from '@/services/admin/payment';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@workspace/ui/components/avatar';
|
||||
import { Badge } from '@workspace/ui/components/badge';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRef, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import PaymentForm from './payment-form';
|
||||
|
||||
export default function PaymentTable() {
|
||||
const t = useTranslations('payment');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const ref = useRef<ProTableActions>(null);
|
||||
|
||||
return (
|
||||
<ProTable<API.PaymentConfig, { search: string }>
|
||||
action={ref}
|
||||
header={{
|
||||
title: t('paymentManagement'),
|
||||
toolbar: (
|
||||
<PaymentForm<API.CreatePaymentMethodRequest>
|
||||
trigger={<Button>{t('create')}</Button>}
|
||||
title={t('createPayment')}
|
||||
loading={loading}
|
||||
onSubmit={async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await createPaymentMethod({
|
||||
...values,
|
||||
enable: false,
|
||||
});
|
||||
toast.success(t('createSuccess'));
|
||||
ref.current?.refresh();
|
||||
setLoading(false);
|
||||
return true;
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
accessorKey: 'enable',
|
||||
header: t('enable'),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Switch
|
||||
checked={Boolean(row.getValue('enable'))}
|
||||
onCheckedChange={async (checked) => {
|
||||
await updatePaymentMethod({
|
||||
...row.original,
|
||||
enable: checked,
|
||||
});
|
||||
ref.current?.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'icon',
|
||||
header: t('icon'),
|
||||
cell: ({ row }) => {
|
||||
const icon = row.getValue('icon') as string;
|
||||
return (
|
||||
<Avatar className='h-8 w-8'>
|
||||
{icon ? <AvatarImage src={icon} alt={row.getValue('name')} /> : null}
|
||||
<AvatarFallback>
|
||||
{(row.getValue('name') as string)?.charAt(0) || '?'}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'name',
|
||||
header: t('name'),
|
||||
},
|
||||
{
|
||||
accessorKey: 'platform',
|
||||
header: t('platform'),
|
||||
cell: ({ row }) => <Badge>{t(row.getValue('platform'))}</Badge>,
|
||||
},
|
||||
{
|
||||
accessorKey: 'notify_url',
|
||||
header: t('notify_url'),
|
||||
},
|
||||
{
|
||||
accessorKey: 'fee',
|
||||
header: t('handlingFee'),
|
||||
cell: ({ row }) => {
|
||||
const feeMode = row.original.fee_mode;
|
||||
if (feeMode === 1) {
|
||||
return <Badge>{row.original.fee_percent}%</Badge>;
|
||||
} else if (feeMode === 2) {
|
||||
return (
|
||||
<Badge>
|
||||
<Display value={row.original.fee_amount} type='currency' />
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
return '--';
|
||||
},
|
||||
},
|
||||
]}
|
||||
params={[
|
||||
{
|
||||
key: 'search',
|
||||
placeholder: t('searchPlaceholder'),
|
||||
},
|
||||
]}
|
||||
request={async (pagination, filter) => {
|
||||
const { data } = await getPaymentMethodList({
|
||||
...pagination,
|
||||
...filter,
|
||||
});
|
||||
return {
|
||||
list: data?.data?.list || [],
|
||||
total: data?.data?.total || 0,
|
||||
};
|
||||
}}
|
||||
actions={{
|
||||
render: (row) => [
|
||||
<PaymentForm<API.UpdatePaymentMethodRequest>
|
||||
isEdit
|
||||
key='edit'
|
||||
trigger={<Button>{t('edit')}</Button>}
|
||||
title={t('editPayment')}
|
||||
loading={loading}
|
||||
initialValues={row}
|
||||
onSubmit={async (values) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await updatePaymentMethod({
|
||||
...row,
|
||||
...values,
|
||||
});
|
||||
toast.success(t('updateSuccess'));
|
||||
ref.current?.refresh();
|
||||
setLoading(false);
|
||||
return true;
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
}}
|
||||
/>,
|
||||
<ConfirmButton
|
||||
key='delete'
|
||||
trigger={<Button variant='destructive'>{t('delete')}</Button>}
|
||||
title={t('confirmDelete')}
|
||||
description={t('deleteWarning')}
|
||||
onConfirm={async () => {
|
||||
await deletePaymentMethod({
|
||||
id: row.id,
|
||||
});
|
||||
toast.success(t('deleteSuccess'));
|
||||
ref.current?.refresh();
|
||||
}}
|
||||
cancelText={t('cancel')}
|
||||
confirmText={t('confirm')}
|
||||
/>,
|
||||
<Button
|
||||
key='copy'
|
||||
variant='outline'
|
||||
onClick={async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const { id, ...params } = row;
|
||||
await createPaymentMethod({
|
||||
...params,
|
||||
enable: false,
|
||||
});
|
||||
toast.success(t('copySuccess'));
|
||||
ref.current?.refresh();
|
||||
setLoading(false);
|
||||
return true;
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
return false;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{t('copy')}
|
||||
</Button>,
|
||||
],
|
||||
batchRender(rows) {
|
||||
return [
|
||||
<ConfirmButton
|
||||
key='delete'
|
||||
trigger={<Button variant='destructive'>{t('batchDelete')}</Button>}
|
||||
title={t('confirmDelete')}
|
||||
description={t('deleteWarning')}
|
||||
onConfirm={async () => {
|
||||
for (const row of rows) {
|
||||
await deletePaymentMethod({ id: row.id });
|
||||
}
|
||||
toast.success(t('deleteSuccess'));
|
||||
ref.current?.refresh();
|
||||
}}
|
||||
cancelText={t('cancel')}
|
||||
confirmText={t('confirm')}
|
||||
/>,
|
||||
];
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
getStripeAlipayPaymentConfig,
|
||||
updateStripeAlipayPaymentConfig,
|
||||
} from '@/services/admin/payment';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@workspace/ui/components/select';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { unitConversion } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function Stripe() {
|
||||
const t = useTranslations('payment');
|
||||
|
||||
const { data, refetch } = useQuery({
|
||||
queryKey: ['getStripeAlipayPaymentConfig'],
|
||||
queryFn: async () => {
|
||||
const { data } = await getStripeAlipayPaymentConfig();
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
|
||||
async function updateConfig(key: string, value: unknown) {
|
||||
if (data?.[key] === value) return;
|
||||
try {
|
||||
await updateStripeAlipayPaymentConfig({
|
||||
...data,
|
||||
mark: 'stripe_alipay',
|
||||
[key]: value,
|
||||
} as any);
|
||||
toast.success(t('saveSuccess'));
|
||||
refetch();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('aliPay')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('enableDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.enable}
|
||||
onCheckedChange={async (checked) => {
|
||||
updateConfig('enable', checked);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('showName')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('showNameDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.name}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('name', value);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('iconUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('iconUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.icon}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('icon', value);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('notifyUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('notifyUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.domain}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('domain', value);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feeMode')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feeModeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Select
|
||||
value={String(data?.fee_mode)}
|
||||
onValueChange={(value) => {
|
||||
updateConfig('fee_mode', Number(value));
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='请选择' />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value='0'>{t('feeModeItems.0')}</SelectItem>
|
||||
<SelectItem value='1'>{t('feeModeItems.1')}</SelectItem>
|
||||
<SelectItem value='2'>{t('feeModeItems.2')}</SelectItem>
|
||||
<SelectItem value='3'>{t('feeModeItems.3')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feePercent')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feePercentDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
max={100}
|
||||
value={data?.fee_percent}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('fee_percent', value);
|
||||
}}
|
||||
suffix='%'
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('fixedFee')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('fixedFeeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
value={data?.fee_amount}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
formatOutput={(value) => unitConversion('dollarsToCents', value)}
|
||||
onValueBlur={(value) => updateConfig('fee_amount', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('stripe.publicKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.public_key}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
public_key: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('stripe.secretKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.secret_key}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
secret_key: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('stripe.webhookSecret')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.webhook_secret}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
webhook_secret: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
getStripeWeChatPayPaymentConfig,
|
||||
updateStripeWeChatPayPaymentConfig,
|
||||
} from '@/services/admin/payment';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@workspace/ui/components/select';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { unitConversion } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function StripeWeChatPay() {
|
||||
const t = useTranslations('payment');
|
||||
|
||||
const { data, refetch } = useQuery({
|
||||
queryKey: ['getStripeWeChatPayPaymentConfig'],
|
||||
queryFn: async () => {
|
||||
const { data } = await getStripeWeChatPayPaymentConfig();
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
|
||||
async function updateConfig(key: string, value: unknown) {
|
||||
if (data?.[key] === value) return;
|
||||
try {
|
||||
await updateStripeWeChatPayPaymentConfig({
|
||||
...data,
|
||||
mark: 'stripe_wechat_pay',
|
||||
[key]: value,
|
||||
} as any);
|
||||
toast.success(t('saveSuccess'));
|
||||
refetch();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('wechatPay')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('enableDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Switch
|
||||
checked={data?.enable}
|
||||
onCheckedChange={async (checked) => {
|
||||
updateConfig('enable', checked);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('showName')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('showNameDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.name}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('name', value);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('iconUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('iconUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.icon}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('icon', value);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('notifyUrl')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('notifyUrlDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.domain}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('domain', value);
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feeMode')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feeModeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<Select
|
||||
value={String(data?.fee_mode)}
|
||||
onValueChange={(value) => {
|
||||
updateConfig('fee_mode', Number(value));
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='请选择' />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value='0'>{t('feeModeItems.0')}</SelectItem>
|
||||
<SelectItem value='1'>{t('feeModeItems.1')}</SelectItem>
|
||||
<SelectItem value='2'>{t('feeModeItems.2')}</SelectItem>
|
||||
<SelectItem value='3'>{t('feeModeItems.3')}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('feePercent')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('feePercentDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
max={100}
|
||||
value={data?.fee_percent}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('fee_percent', value);
|
||||
}}
|
||||
suffix='%'
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('fixedFee')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('fixedFeeDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
type='number'
|
||||
min={0}
|
||||
value={data?.fee_amount}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
formatOutput={(value) => unitConversion('dollarsToCents', value)}
|
||||
onValueBlur={(value) => updateConfig('fee_amount', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('stripe.publicKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.public_key}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
public_key: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('stripe.secretKey')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.secret_key}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
secret_key: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('stripe.webhookSecret')}</Label>
|
||||
<p className='text-muted-foreground text-xs' />
|
||||
</TableCell>
|
||||
<TableCell className='text-right'>
|
||||
<EnhancedInput
|
||||
placeholder={t('inputPlaceholder')}
|
||||
value={data?.config.webhook_secret}
|
||||
onValueBlur={(value) => {
|
||||
updateConfig('config', {
|
||||
...data?.config,
|
||||
webhook_secret: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
@@ -362,9 +362,10 @@ export default function NodeForm<T extends { [x: string]: any }>({
|
||||
<EnhancedInput
|
||||
{...field}
|
||||
type='number'
|
||||
placeholder='1-65535'
|
||||
step={1}
|
||||
min={1}
|
||||
max={65535}
|
||||
placeholder='1-65535'
|
||||
onValueChange={(value) => {
|
||||
form.setValue(field.name, value);
|
||||
}}
|
||||
@@ -418,6 +419,9 @@ export default function NodeForm<T extends { [x: string]: any }>({
|
||||
<EnhancedInput
|
||||
{...field}
|
||||
type='number'
|
||||
step={1}
|
||||
min={1}
|
||||
max={65535}
|
||||
placeholder='1-65535'
|
||||
onValueChange={(value) => {
|
||||
form.setValue(field.name, value);
|
||||
@@ -899,6 +903,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
|
||||
{
|
||||
name: 'port',
|
||||
type: 'number',
|
||||
step: 1,
|
||||
min: 1,
|
||||
max: 65535,
|
||||
placeholder: t('form.relayPort'),
|
||||
|
||||
@@ -5,18 +5,21 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
|
||||
import { Textarea } from '@workspace/ui/components/textarea';
|
||||
import { JSONEditor } from '@workspace/ui/custom-components/editor';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { UploadImage } from '@workspace/ui/custom-components/upload-image';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRef } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function Site() {
|
||||
const t = useTranslations('system.site');
|
||||
|
||||
const ref = useRef<API.SiteConfig | undefined>(undefined);
|
||||
const { data, refetch } = useQuery({
|
||||
queryKey: ['getSiteConfig'],
|
||||
queryFn: async () => {
|
||||
const { data } = await getSiteConfig();
|
||||
ref.current = data.data;
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
@@ -25,7 +28,7 @@ export default function Site() {
|
||||
if (data?.[key] === value) return;
|
||||
try {
|
||||
await updateSiteConfig({
|
||||
...data,
|
||||
...ref.current,
|
||||
[key]: value,
|
||||
} as API.SiteConfig);
|
||||
toast.success(t('saveSuccess'));
|
||||
@@ -130,6 +133,49 @@ export default function Site() {
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Label>{t('customData')}</Label>
|
||||
<p className='text-muted-foreground text-xs'>{t('customDataDescription')}</p>
|
||||
</TableCell>
|
||||
<TableCell className='w-1/2 text-right'>
|
||||
<JSONEditor
|
||||
schema={{
|
||||
type: 'object',
|
||||
additionalProperties: true,
|
||||
properties: {
|
||||
website: { type: 'string', title: 'Website' },
|
||||
contacts: {
|
||||
type: 'object',
|
||||
title: 'Contacts',
|
||||
additionalProperties: true,
|
||||
properties: {
|
||||
email: { type: 'string', title: 'Email' },
|
||||
telephone: { type: 'string', title: 'Telephone' },
|
||||
address: { type: 'string', title: 'Address' },
|
||||
},
|
||||
},
|
||||
community: {
|
||||
type: 'object',
|
||||
title: 'Community',
|
||||
additionalProperties: true,
|
||||
properties: {
|
||||
telegram: { type: 'string', title: 'Telegram' },
|
||||
twitter: { type: 'string', title: 'Twitter' },
|
||||
discord: { type: 'string', title: 'Discord' },
|
||||
instagram: { type: 'string', title: 'Instagram' },
|
||||
linkedin: { type: 'string', title: 'Linkedin' },
|
||||
facebook: { type: 'string', title: 'Facebook' },
|
||||
github: { type: 'string', title: 'Github' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
value={data?.custom_data}
|
||||
onBlur={(value) => updateConfig('custom_data', value)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
|
||||
@@ -113,6 +113,7 @@ export function BasicInfoForm({ user, refetch }: { user: API.User; refetch: () =
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='number'
|
||||
min={0}
|
||||
value={field.value}
|
||||
prefix={currency?.currency_symbol ?? '$'}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
@@ -136,6 +137,7 @@ export function BasicInfoForm({ user, refetch }: { user: API.User; refetch: () =
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='number'
|
||||
min={0}
|
||||
value={field.value}
|
||||
prefix={currency?.currency_symbol ?? '$'}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
@@ -159,6 +161,7 @@ export function BasicInfoForm({ user, refetch }: { user: API.User; refetch: () =
|
||||
<FormControl>
|
||||
<EnhancedInput
|
||||
type='number'
|
||||
min={0}
|
||||
value={field.value}
|
||||
prefix={currency?.currency_symbol ?? '$'}
|
||||
formatInput={(value) => unitConversion('centsToDollars', value)}
|
||||
|
||||
@@ -57,6 +57,7 @@ export function SubscriptionDetail({
|
||||
{t('onlineDevices')}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className='mt-4 max-h-[60dvh] overflow-y-auto'>
|
||||
<TabsContent value='logs'>
|
||||
<ProTable<API.UserSubscribeLog, Record<string, unknown>>
|
||||
columns={[
|
||||
@@ -97,7 +98,9 @@ export function SubscriptionDetail({
|
||||
{
|
||||
accessorKey: 'download',
|
||||
header: t('download'),
|
||||
cell: ({ row }) => <Display type='traffic' value={row.getValue('download')} />,
|
||||
cell: ({ row }) => (
|
||||
<Display type='traffic' value={row.getValue('download')} />
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: 'upload',
|
||||
@@ -115,7 +118,7 @@ export function SubscriptionDetail({
|
||||
user_id: userId,
|
||||
subscribe_id: subscriptionId,
|
||||
...pagination,
|
||||
});
|
||||
} as API.GetUserSubscribeTrafficLogsParams);
|
||||
return {
|
||||
list: data.data?.list || [],
|
||||
total: data.data?.total || 0,
|
||||
@@ -201,6 +204,7 @@ export function SubscriptionDetail({
|
||||
}}
|
||||
/>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
||||
@@ -58,8 +58,21 @@ export default function Page() {
|
||||
<Switch
|
||||
defaultChecked={row.getValue('enable')}
|
||||
onCheckedChange={async (checked) => {
|
||||
const {
|
||||
auth_methods,
|
||||
user_devices,
|
||||
enable_balance_notify,
|
||||
enable_login_notify,
|
||||
enable_subscribe_notify,
|
||||
enable_trade_notify,
|
||||
updated_at,
|
||||
created_at,
|
||||
id,
|
||||
...rest
|
||||
} = row.original;
|
||||
await updateUserBasicInfo({
|
||||
...row.original,
|
||||
user_id: id,
|
||||
...rest,
|
||||
enable: checked,
|
||||
} as unknown as API.UpdateUserBasiceInfoRequest);
|
||||
toast.success(t('updateSuccess'));
|
||||
|
||||
@@ -61,6 +61,11 @@ export const navs = [
|
||||
icon: 'flat-color-icons:lock-portrait',
|
||||
items: AuthControl,
|
||||
},
|
||||
{
|
||||
title: 'ADS Config',
|
||||
url: '/dashboard/ads',
|
||||
icon: 'flat-color-icons:electrical-sensor',
|
||||
},
|
||||
{
|
||||
title: 'Payment Config',
|
||||
url: '/dashboard/payment',
|
||||
@@ -115,7 +120,7 @@ export const navs = [
|
||||
{
|
||||
title: 'Announcement Management',
|
||||
url: '/dashboard/announcement',
|
||||
icon: 'flat-color-icons:news',
|
||||
icon: 'flat-color-icons:advertising',
|
||||
},
|
||||
{
|
||||
title: 'Ticket Management',
|
||||
|
||||
@@ -16,6 +16,7 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
|
||||
site_logo: '',
|
||||
keywords: '',
|
||||
custom_html: '',
|
||||
custom_data: '',
|
||||
},
|
||||
verify: {
|
||||
turnstile_site_key: '',
|
||||
@@ -63,6 +64,7 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
|
||||
verify_code_interval: 60,
|
||||
},
|
||||
oauth_methods: [],
|
||||
web_ad: false,
|
||||
},
|
||||
user: undefined,
|
||||
setCommon: (common) =>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Zrušit",
|
||||
"confirm": "Potvrdit",
|
||||
"confirmDelete": "Potvrdit smazání",
|
||||
"create": "Vytvořit inzerát",
|
||||
"createAds": "Vytvořit reklamu",
|
||||
"createSuccess": "Úspěšně vytvořeno",
|
||||
"delete": "Smazat",
|
||||
"deleteSuccess": "Úspěšně smazáno",
|
||||
"deleteWarning": "Opravdu chcete smazat tento inzerát?",
|
||||
"disabled": "Deaktivováno",
|
||||
"edit": "Upravit",
|
||||
"editAds": "Upravit reklamu",
|
||||
"enabled": "Aktivováno",
|
||||
"form": {
|
||||
"cancel": "Zrušit",
|
||||
"confirm": "Potvrdit",
|
||||
"content": "Obsah",
|
||||
"description": "Popis",
|
||||
"endTime": "Čas ukončení",
|
||||
"enterContent": "Prosím zadejte obsah inzerátu",
|
||||
"enterDescription": "Prosím zadejte popis inzerátu",
|
||||
"enterEndTime": "Prosím vyberte čas ukončení",
|
||||
"enterStartTime": "Prosím vyberte čas zahájení",
|
||||
"enterTargetUrl": "Prosím zadejte cílovou URL",
|
||||
"enterTitle": "Prosím zadejte název inzerátu",
|
||||
"startTime": "Čas zahájení",
|
||||
"targetUrl": "Cílová URL",
|
||||
"title": "Název",
|
||||
"type": "Typ inzerátu",
|
||||
"typeImage": "Obrázek",
|
||||
"typeVideo": "Video"
|
||||
},
|
||||
"status": "Stav",
|
||||
"targetUrl": "Cílová URL",
|
||||
"title": "Název",
|
||||
"type": "Typ",
|
||||
"updateSuccess": "Úspěšně aktualizováno",
|
||||
"validityPeriod": "Doba platnosti"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Blokovat virtuální stroj",
|
||||
"blockVirtualMachineDescription": "Pokud je povoleno, zařízení nebudou moci běžet na virtuálních strojích nebo emulátorech",
|
||||
"communicationKey": "Komunikační klíč",
|
||||
"communicationKeyDescription": "Komunikační klíč se používá pro bezpečnou komunikaci mezi zařízeními a servery",
|
||||
"enable": "Povolit",
|
||||
"enableDescription": "Po povolení jsou podporovány různé identifikátory zařízení, jako jsou IMEI/IDFA/IDFV/AndroidID/Mac adresa pro přihlášení a registraci"
|
||||
"enableDescription": "Po povolení jsou podporovány různé identifikátory zařízení, jako jsou IMEI/IDFA/IDFV/AndroidID/Mac adresa pro přihlášení a registraci",
|
||||
"enableSecurity": "Povolit šifrování komunikace",
|
||||
"enableSecurityDescription": "Pokud je povoleno, komunikace mezi zařízeními a servery bude šifrována",
|
||||
"saveFailed": "Uložení se nezdařilo",
|
||||
"saveSuccess": "Uložení bylo úspěšné",
|
||||
"showAds": "Zobrazit reklamy",
|
||||
"showAdsDescription": "Pokud je povoleno, na zařízeních se budou zobrazovat reklamy"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Stav",
|
||||
"subject": "Předmět",
|
||||
"template": "Šablona",
|
||||
"traffic_exceed_email_template": "Šablona oznámení o překročení provozu",
|
||||
"traffic_exceed_email_templateDescription": "Zástupné symboly {after}.variable{before} budou nahrazeny skutečnými daty. Ujistěte se, že tyto proměnné zachováte.",
|
||||
"verify_email_template": "Šablona ověřovacího e-mailu",
|
||||
"verify_email_templateDescription": "Zástupné symboly {after}.variable{before} budou nahrazeny skutečnými daty. Ujistěte se, že tyto proměnné zachováte.",
|
||||
"whitelistSuffixes": "Povolené přípony",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "Konfigurace ADS",
|
||||
"Announcement Management": "Správa oznámení",
|
||||
"Apple": "Apple ID",
|
||||
"Auth Control": "Řízení ověřování",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Platba Alipay",
|
||||
"alipayf2f": {
|
||||
"appId": "ID aplikace Alipay",
|
||||
"invoiceName": "Název vlastního produktu",
|
||||
"invoiceNameDescription": "Bude zobrazeno na faktuře Alipay",
|
||||
"privateKey": "Soukromý klíč Alipay",
|
||||
"publicKey": "Veřejný klíč Alipay",
|
||||
"sandbox": "Režim sandbox",
|
||||
"sandboxDescription": "Povolte režim sandbox pro testování plateb"
|
||||
},
|
||||
"AlipayF2F": "Alipay Osobně",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Žádat o platbu",
|
||||
"balance": "Zůstatek",
|
||||
"batchDelete": "Hromadné smazání",
|
||||
"cancel": "Zrušit",
|
||||
"config": "Nastavení",
|
||||
"configInfo": "Informace o nastavení",
|
||||
"configPlaceholder": "Vyplňte prosím poskytnutou konfiguraci {field}",
|
||||
"confirm": "Potvrdit",
|
||||
"confirmDelete": "Potvrdit smazání",
|
||||
"copy": "Kopírovat",
|
||||
"copySuccess": "Úspěšně zkopírováno",
|
||||
"create": "Přidat platební metodu",
|
||||
"createPayment": "Přidat platební metodu",
|
||||
"createSuccess": "Úspěšně vytvořeno",
|
||||
"delete": "Smazat",
|
||||
"deleteSuccess": "Úspěšně smazáno",
|
||||
"deleteWarning": "Opravdu chcete smazat tuto platební metodu? Tuto akci nelze vrátit zpět.",
|
||||
"description": "Popis",
|
||||
"descriptionPlaceholder": "Zadejte popis platební metody",
|
||||
"domain": "Doména",
|
||||
"domainPlaceholder": "volitelné, např. {example}",
|
||||
"edit": "Upravit",
|
||||
"editPayment": "Upravit platební metodu",
|
||||
"enable": "Povolit",
|
||||
"enableDescription": "Povolit tento způsob platby",
|
||||
"epay": {
|
||||
"key": "KLÍČ",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Pevná částka",
|
||||
"feeMode": "Způsob účtování",
|
||||
"feeModeDescription": "Způsob účtování dodatečných poplatků",
|
||||
"feeModeItems": ["Bez poplatku", "Procento", "Pevná částka", "Obojí výše uvedené"],
|
||||
"feePercent": "Procentuální poplatek (volitelně)",
|
||||
"feePercentDescription": "Přidání poplatku k částce objednávky",
|
||||
"fixedFee": "Pevný poplatek (volitelný)",
|
||||
"fixedFeeDescription": "Přidání pevného poplatku k částce objednávky",
|
||||
"iconUrl": "URL ikony (volitelné)",
|
||||
"iconUrlDescription": "Používá se pro zobrazení na frontendu",
|
||||
"inputPlaceholder": "Prosím zadejte",
|
||||
"key": "KLÍČ",
|
||||
"notifyUrl": "Vlastní oznámení URL (volitelné)",
|
||||
"notifyUrlDescription": "Oznámení brány budou odeslána na tuto doménu",
|
||||
"payForRecommendations": "Zaplatit za doporučení",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Uložení bylo úspěšné",
|
||||
"showName": "Zobrazit název",
|
||||
"showNameDescription": "Používá se pro zobrazení na frontendu",
|
||||
"stripe": {
|
||||
"publicKey": "VEŘEJNÝ KLÍČ",
|
||||
"secretKey": "TAJNÝ KLÍČ",
|
||||
"webhookSecret": "PODPIS WEBHOOK KLÍČE"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat Pay"
|
||||
"handlingFee": "Poplatek za zpracování",
|
||||
"icon": "Ikona",
|
||||
"iconPlaceholder": "Zadejte URL ikony",
|
||||
"mark": "Identifikátor",
|
||||
"markPlaceholder": "Zadejte identifikátor platební metody",
|
||||
"name": "Název",
|
||||
"namePlaceholder": "Zadejte název platební metody",
|
||||
"nameRequired": "Název je povinný",
|
||||
"noFee": "Žádný poplatek",
|
||||
"notify_url": "URL pro oznámení",
|
||||
"paymentManagement": "Správa plateb",
|
||||
"percentFee": "Procento",
|
||||
"platform": "Platforma",
|
||||
"searchPlaceholder": "Zadejte hledané výrazy",
|
||||
"selectPlatform": "Vyberte platformu",
|
||||
"selectType": "Vyberte typ platby",
|
||||
"submit": "Odeslat",
|
||||
"type": "Typ",
|
||||
"updateSuccess": "Úspěšně aktualizováno"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Zásady ochrany osobních údajů"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Vlastní data",
|
||||
"customDataDescription": "Vlastní data, používaná pro vlastní data webu",
|
||||
"customHtml": "Vlastní HTML",
|
||||
"customHtmlDescription": "Vlastní HTML kód, který bude vložen na konec tagu body na stránce.",
|
||||
"keywords": "Klíčová slova",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Abbrechen",
|
||||
"confirm": "Bestätigen",
|
||||
"confirmDelete": "Löschen bestätigen",
|
||||
"create": "Anzeige erstellen",
|
||||
"createAds": "Anzeige erstellen",
|
||||
"createSuccess": "Erfolgreich erstellt",
|
||||
"delete": "Löschen",
|
||||
"deleteSuccess": "Erfolgreich gelöscht",
|
||||
"deleteWarning": "Sind Sie sicher, dass Sie diese Anzeige löschen möchten?",
|
||||
"disabled": "Deaktiviert",
|
||||
"edit": "Bearbeiten",
|
||||
"editAds": "Anzeige bearbeiten",
|
||||
"enabled": "Aktiviert",
|
||||
"form": {
|
||||
"cancel": "Abbrechen",
|
||||
"confirm": "Bestätigen",
|
||||
"content": "Inhalt",
|
||||
"description": "Beschreibung",
|
||||
"endTime": "Endzeit",
|
||||
"enterContent": "Bitte geben Sie den Anzeigeninhalt ein",
|
||||
"enterDescription": "Bitte geben Sie die Anzeigenbeschreibung ein",
|
||||
"enterEndTime": "Bitte wählen Sie die Endzeit aus",
|
||||
"enterStartTime": "Bitte wählen Sie die Startzeit aus",
|
||||
"enterTargetUrl": "Bitte geben Sie die Ziel-URL ein",
|
||||
"enterTitle": "Bitte geben Sie den Anzeigentitel ein",
|
||||
"startTime": "Startzeit",
|
||||
"targetUrl": "Ziel-URL",
|
||||
"title": "Titel",
|
||||
"type": "Anzeigentyp",
|
||||
"typeImage": "Bild",
|
||||
"typeVideo": "Video"
|
||||
},
|
||||
"status": "Status",
|
||||
"targetUrl": "Ziel-URL",
|
||||
"title": "Titel",
|
||||
"type": "Typ",
|
||||
"updateSuccess": "Erfolgreich aktualisiert",
|
||||
"validityPeriod": "Gültigkeitsdauer"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Virtuelle Maschine blockieren",
|
||||
"blockVirtualMachineDescription": "Wenn aktiviert, wird verhindert, dass Geräte auf virtuellen Maschinen oder Emulatoren ausgeführt werden.",
|
||||
"communicationKey": "Kommunikationsschlüssel",
|
||||
"communicationKeyDescription": "Der Kommunikationsschlüssel wird für die sichere Kommunikation zwischen Geräten und Servern verwendet.",
|
||||
"enable": "Aktivieren",
|
||||
"enableDescription": "Nach der Aktivierung werden mehrere Geräteidentifikatoren wie IMEI/IDFA/IDFV/AndroidID/Mac-Adresse für die Anmeldung und Registrierung unterstützt."
|
||||
"enableDescription": "Nach der Aktivierung werden mehrere Geräteidentifikatoren wie IMEI/IDFA/IDFV/AndroidID/Mac-Adresse für die Anmeldung und Registrierung unterstützt.",
|
||||
"enableSecurity": "Kommunikationsverschlüsselung aktivieren",
|
||||
"enableSecurityDescription": "Wenn aktiviert, wird die Kommunikation zwischen Geräten und Servern verschlüsselt.",
|
||||
"saveFailed": "Speichern fehlgeschlagen",
|
||||
"saveSuccess": "Speichern erfolgreich",
|
||||
"showAds": "Werbung anzeigen",
|
||||
"showAdsDescription": "Wenn aktiviert, werden auf den Geräten Anzeigen angezeigt."
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Status",
|
||||
"subject": "Betreff",
|
||||
"template": "Vorlage",
|
||||
"traffic_exceed_email_template": "Benachrichtigung über überschreitenden Verkehr",
|
||||
"traffic_exceed_email_templateDescription": "Die Platzhalter {after}.variable{before} werden durch tatsächliche Daten ersetzt. Stellen Sie sicher, dass Sie diese Variablen beibehalten.",
|
||||
"verify_email_template": "E-Mail-Bestätigungsvorlage",
|
||||
"verify_email_templateDescription": "Die Platzhalter {after}.variable{before} werden durch tatsächliche Daten ersetzt. Stellen Sie sicher, dass diese Variablen beibehalten werden.",
|
||||
"whitelistSuffixes": "Whitelist-Suffixe",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS-Konfiguration",
|
||||
"Announcement Management": "Ankündigungsverwaltung",
|
||||
"Apple": "Apple-ID",
|
||||
"Auth Control": "Authentifizierungskontrolle",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Alipay-Zahlung",
|
||||
"alipayf2f": {
|
||||
"appId": "Alipay Anwendungs-ID",
|
||||
"invoiceName": "Benutzerdefinierter Produktname",
|
||||
"invoiceNameDescription": "Wird in der Alipay-Rechnung angezeigt",
|
||||
"privateKey": "Alipay Privatschlüssel",
|
||||
"publicKey": "Alipay Öffentlicher Schlüssel",
|
||||
"sandbox": "Sandbox-Modus",
|
||||
"sandboxDescription": "Aktivieren Sie den Sandbox-Modus, um Zahlungen zu testen"
|
||||
},
|
||||
"AlipayF2F": "Alipay Gesicht zu Gesicht",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Zahlung beantragen",
|
||||
"balance": "Guthaben",
|
||||
"batchDelete": "Massenlöschung",
|
||||
"cancel": "Abbrechen",
|
||||
"config": "Konfiguration",
|
||||
"configInfo": "Konfigurationsinformationen",
|
||||
"configPlaceholder": "Bitte füllen Sie die bereitgestellte {field} Konfiguration aus",
|
||||
"confirm": "Bestätigen",
|
||||
"confirmDelete": "Löschen bestätigen",
|
||||
"copy": "Kopieren",
|
||||
"copySuccess": "Erfolgreich kopiert",
|
||||
"create": "Zahlungsmethode hinzufügen",
|
||||
"createPayment": "Zahlungsmethode hinzufügen",
|
||||
"createSuccess": "Erfolgreich erstellt",
|
||||
"delete": "Löschen",
|
||||
"deleteSuccess": "Erfolgreich gelöscht",
|
||||
"deleteWarning": "Sind Sie sicher, dass Sie diese Zahlungsmethode löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"description": "Beschreibung",
|
||||
"descriptionPlaceholder": "Geben Sie die Beschreibung der Zahlungsmethode ein",
|
||||
"domain": "Domain",
|
||||
"domainPlaceholder": "optional, z.B. {example}",
|
||||
"edit": "Bearbeiten",
|
||||
"editPayment": "Zahlungsmethode bearbeiten",
|
||||
"enable": "Aktivieren",
|
||||
"enableDescription": "Diese Zahlungsmethode aktivieren",
|
||||
"epay": {
|
||||
"key": "SCHLÜSSEL",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Fester Betrag",
|
||||
"feeMode": "Gebührenmodus",
|
||||
"feeModeDescription": "Gebührenmodus für zusätzliche Gebühren",
|
||||
"feeModeItems": ["Keine Gebühr", "Prozentsatz", "Fester Betrag", "Beides"],
|
||||
"feePercent": "Prozentgebühr (optional)",
|
||||
"feePercentDescription": "Gebühren werden zusätzlich zum Bestellbetrag hinzugefügt",
|
||||
"fixedFee": "Feste Gebühr (optional)",
|
||||
"fixedFeeDescription": "Feste Gebühr zusätzlich zum Bestellbetrag hinzufügen",
|
||||
"iconUrl": "Symbol-URL (optional)",
|
||||
"iconUrlDescription": "Zur Anzeige im Frontend verwendet",
|
||||
"inputPlaceholder": "Bitte eingeben",
|
||||
"key": "SCHLÜSSEL",
|
||||
"notifyUrl": "Benutzerdefinierte Benachrichtigungs-URL (optional)",
|
||||
"notifyUrlDescription": "Gateway-Benachrichtigungen werden an diese Domain gesendet",
|
||||
"payForRecommendations": "Für Empfehlungen bezahlen",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Erfolgreich gespeichert",
|
||||
"showName": "Anzeigename",
|
||||
"showNameDescription": "Zur Anzeige im Frontend verwendet",
|
||||
"stripe": {
|
||||
"publicKey": "ÖFFENTLICHER SCHLÜSSEL",
|
||||
"secretKey": "GEHEIMER SCHLÜSSEL",
|
||||
"webhookSecret": "WEBHOOK-SCHLÜSSEL-SIGNATUR"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat Pay"
|
||||
"handlingFee": "Bearbeitungsgebühr",
|
||||
"icon": "Symbol",
|
||||
"iconPlaceholder": "Geben Sie die URL des Symbols ein",
|
||||
"mark": "Kennung",
|
||||
"markPlaceholder": "Geben Sie die Kennung der Zahlungsmethode ein",
|
||||
"name": "Name",
|
||||
"namePlaceholder": "Geben Sie den Namen der Zahlungsmethode ein",
|
||||
"nameRequired": "Name ist erforderlich",
|
||||
"noFee": "Keine Gebühr",
|
||||
"notify_url": "Benachrichtigungs-URL",
|
||||
"paymentManagement": "Zahlungsverwaltung",
|
||||
"percentFee": "Prozentsatz",
|
||||
"platform": "Plattform",
|
||||
"searchPlaceholder": "Suchbegriffe eingeben",
|
||||
"selectPlatform": "Plattform auswählen",
|
||||
"selectType": "Zahlungsart auswählen",
|
||||
"submit": "Einreichen",
|
||||
"type": "Typ",
|
||||
"updateSuccess": "Erfolgreich aktualisiert"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Datenschutzrichtlinie"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Benutzerdefinierte Daten",
|
||||
"customDataDescription": "Benutzerdefinierte Daten, die für benutzerdefinierte Daten der Website verwendet werden",
|
||||
"customHtml": "Benutzerdefiniertes HTML",
|
||||
"customHtmlDescription": "Benutzerdefinierter HTML-Code, der am Ende des body-Tags der Seite eingefügt werden soll.",
|
||||
"keywords": "Schlüsselwörter",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"confirmDelete": "Confirm Delete",
|
||||
"create": "Create Ad",
|
||||
"createAds": "Create Advertisement",
|
||||
"createSuccess": "Successfully created",
|
||||
"delete": "Delete",
|
||||
"deleteSuccess": "Successfully deleted",
|
||||
"deleteWarning": "Are you sure you want to delete this ad?",
|
||||
"disabled": "Disabled",
|
||||
"edit": "Edit",
|
||||
"editAds": "Edit Advertisement",
|
||||
"enabled": "Enabled",
|
||||
"form": {
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"content": "Content",
|
||||
"description": "Description",
|
||||
"endTime": "End Time",
|
||||
"enterContent": "Please enter ad content",
|
||||
"enterDescription": "Please enter ad description",
|
||||
"enterEndTime": "Please select end time",
|
||||
"enterStartTime": "Please select start time",
|
||||
"enterTargetUrl": "Please enter target URL",
|
||||
"enterTitle": "Please enter ad title",
|
||||
"startTime": "Start Time",
|
||||
"targetUrl": "Target URL",
|
||||
"title": "Title",
|
||||
"type": "Ad Type",
|
||||
"typeImage": "Image",
|
||||
"typeVideo": "Video"
|
||||
},
|
||||
"status": "Status",
|
||||
"targetUrl": "Target URL",
|
||||
"title": "Title",
|
||||
"type": "Type",
|
||||
"updateSuccess": "Successfully updated",
|
||||
"validityPeriod": "Validity Period"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Block Virtual Machine",
|
||||
"blockVirtualMachineDescription": "When enabled, devices will be prevented from running on virtual machines or emulators",
|
||||
"communicationKey": "Communication Key",
|
||||
"communicationKeyDescription": "Communication key is used for secure communication between devices and servers",
|
||||
"enable": "Enable",
|
||||
"enableDescription": "After enabling, multiple device identifiers such as IMEI/IDFA/IDFV/AndroidID/Mac address are supported for login and registration"
|
||||
"enableDescription": "After enabling, multiple device identifiers such as IMEI/IDFA/IDFV/AndroidID/Mac address are supported for login and registration",
|
||||
"enableSecurity": "Enable Communication Encryption",
|
||||
"enableSecurityDescription": "When enabled, the communication between devices and servers will be encrypted",
|
||||
"saveFailed": "Save failed",
|
||||
"saveSuccess": "Save successful",
|
||||
"showAds": "Show Advertisements",
|
||||
"showAdsDescription": "When enabled, advertisements will be displayed on devices"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Status",
|
||||
"subject": "Subject",
|
||||
"template": "Template",
|
||||
"traffic_exceed_email_template": "Traffic Exceed Notice Template",
|
||||
"traffic_exceed_email_templateDescription": "The {after}.variable{before} placeholders will be replaced with actual data. Ensure to keep these variables.",
|
||||
"verify_email_template": "Verification Email Template",
|
||||
"verify_email_templateDescription": "The {after}.variable{before} placeholders will be replaced with actual data. Ensure to keep these variables.",
|
||||
"whitelistSuffixes": "Whitelist Suffixes",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS Config",
|
||||
"Announcement Management": "Announcement Management",
|
||||
"Apple": "Apple ID",
|
||||
"Auth Control": "Auth Control",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Alipay payment",
|
||||
"alipayf2f": {
|
||||
"appId": "Alipay App ID",
|
||||
"invoiceName": "Custom Product Name",
|
||||
"invoiceNameDescription": "Will be displayed on Alipay bill",
|
||||
"privateKey": "Alipay Private Key",
|
||||
"publicKey": "Alipay Public Key",
|
||||
"sandbox": "Sandbox Mode",
|
||||
"sandboxDescription": "Enable sandbox mode to test payments"
|
||||
},
|
||||
"AlipayF2F": "Alipay Face to Face",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Apply for Payment",
|
||||
"balance": "Balance",
|
||||
"batchDelete": "Batch Delete",
|
||||
"cancel": "Cancel",
|
||||
"config": "Configuration",
|
||||
"configInfo": "Configuration Information",
|
||||
"configPlaceholder": "Please fill in the provided {field} configuration",
|
||||
"confirm": "Confirm",
|
||||
"confirmDelete": "Confirm Delete",
|
||||
"copy": "Copy",
|
||||
"copySuccess": "Copied successfully",
|
||||
"create": "Add Payment Method",
|
||||
"createPayment": "Add Payment Method",
|
||||
"createSuccess": "Created successfully",
|
||||
"delete": "Delete",
|
||||
"deleteSuccess": "Deleted successfully",
|
||||
"deleteWarning": "Are you sure you want to delete this payment method? This action cannot be undone.",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Enter payment method description",
|
||||
"domain": "Domain",
|
||||
"domainPlaceholder": "optional, e.g. {example}",
|
||||
"edit": "Edit",
|
||||
"editPayment": "Edit Payment Method",
|
||||
"enable": "Enable",
|
||||
"enableDescription": "Enable this payment method",
|
||||
"epay": {
|
||||
"key": "KEY",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Fixed Amount",
|
||||
"feeMode": "Fee Mode",
|
||||
"feeModeDescription": "Fee charging method for additional fees",
|
||||
"feeModeItems": ["No Fee", "Percentage", "Fixed Amount", "Both"],
|
||||
"feePercent": "Percentage Fee (optional)",
|
||||
"feePercentDescription": "Add fee on top of order amount",
|
||||
"fixedFee": "Fixed Fee (optional)",
|
||||
"fixedFeeDescription": "Add fixed fee on top of order amount",
|
||||
"iconUrl": "Icon URL (optional)",
|
||||
"iconUrlDescription": "Used for frontend display",
|
||||
"inputPlaceholder": "Please enter",
|
||||
"key": "KEY",
|
||||
"notifyUrl": "Custom Notification Domain (optional)",
|
||||
"notifyUrlDescription": "Gateway notifications will be sent to this domain",
|
||||
"payForRecommendations": "Pay for Recommendations",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Save Successful",
|
||||
"showName": "Display Name",
|
||||
"showNameDescription": "Used for frontend display",
|
||||
"stripe": {
|
||||
"publicKey": "PUBLIC KEY",
|
||||
"secretKey": "SECRET KEY",
|
||||
"webhookSecret": "WEBHOOK Secret Key"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat Pay"
|
||||
"feePercent": "Fee Percentage",
|
||||
"fixedFee": "Fixed Amount",
|
||||
"handlingFee": "Handling Fee",
|
||||
"icon": "Icon",
|
||||
"iconPlaceholder": "Enter icon URL",
|
||||
"mark": "Identifier",
|
||||
"markPlaceholder": "Enter payment method identifier",
|
||||
"name": "Name",
|
||||
"namePlaceholder": "Enter payment method name",
|
||||
"nameRequired": "Name is required",
|
||||
"noFee": "No Fee",
|
||||
"notify_url": "Notify URL",
|
||||
"paymentManagement": "Payment Management",
|
||||
"percentFee": "Percentage",
|
||||
"platform": "Platform",
|
||||
"searchPlaceholder": "Enter search terms",
|
||||
"selectPlatform": "Select Platform",
|
||||
"selectType": "Select payment type",
|
||||
"submit": "Submit",
|
||||
"type": "Type",
|
||||
"updateSuccess": "Updated successfully"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Privacy Policy"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Custom Data",
|
||||
"customDataDescription": "Custom Data, used for custom data of the site",
|
||||
"customHtml": "Custom HTML",
|
||||
"customHtmlDescription": "Custom HTML code to be injected into the bottom of the site's body tag.",
|
||||
"keywords": "Keywords",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Confirmar",
|
||||
"confirmDelete": "Confirmar eliminación",
|
||||
"create": "Crear anuncio",
|
||||
"createAds": "Crear publicidad",
|
||||
"createSuccess": "Creado con éxito",
|
||||
"delete": "Eliminar",
|
||||
"deleteSuccess": "Eliminado con éxito",
|
||||
"deleteWarning": "¿Está seguro de que desea eliminar este anuncio?",
|
||||
"disabled": "Deshabilitado",
|
||||
"edit": "Editar",
|
||||
"editAds": "Editar publicidad",
|
||||
"enabled": "Habilitado",
|
||||
"form": {
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Confirmar",
|
||||
"content": "Contenido",
|
||||
"description": "Descripción",
|
||||
"endTime": "Hora de finalización",
|
||||
"enterContent": "Por favor, introduzca el contenido del anuncio",
|
||||
"enterDescription": "Por favor, introduzca la descripción del anuncio",
|
||||
"enterEndTime": "Por favor, seleccione la hora de finalización",
|
||||
"enterStartTime": "Por favor, seleccione la hora de inicio",
|
||||
"enterTargetUrl": "Por favor, introduzca la URL de destino",
|
||||
"enterTitle": "Por favor, introduzca el título del anuncio",
|
||||
"startTime": "Hora de inicio",
|
||||
"targetUrl": "URL de destino",
|
||||
"title": "Título",
|
||||
"type": "Tipo de anuncio",
|
||||
"typeImage": "Imagen",
|
||||
"typeVideo": "Vídeo"
|
||||
},
|
||||
"status": "Estado",
|
||||
"targetUrl": "URL de destino",
|
||||
"title": "Título",
|
||||
"type": "Tipo",
|
||||
"updateSuccess": "Actualizado con éxito",
|
||||
"validityPeriod": "Período de validez"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Bloquear Máquina Virtual",
|
||||
"blockVirtualMachineDescription": "Cuando está habilitado, se evitará que los dispositivos se ejecuten en máquinas virtuales o emuladores",
|
||||
"communicationKey": "Clave de Comunicación",
|
||||
"communicationKeyDescription": "La clave de comunicación se utiliza para la comunicación segura entre dispositivos y servidores",
|
||||
"enable": "Habilitar",
|
||||
"enableDescription": "Después de habilitar, se admiten múltiples identificadores de dispositivos como IMEI/IDFA/IDFV/AndroidID/dirección MAC para el inicio de sesión y el registro"
|
||||
"enableDescription": "Después de habilitar, se admiten múltiples identificadores de dispositivos como IMEI/IDFA/IDFV/AndroidID/dirección MAC para el inicio de sesión y el registro",
|
||||
"enableSecurity": "Habilitar Cifrado de Comunicación",
|
||||
"enableSecurityDescription": "Cuando está habilitado, la comunicación entre dispositivos y servidores será cifrada",
|
||||
"saveFailed": "Error al guardar",
|
||||
"saveSuccess": "Guardado exitoso",
|
||||
"showAds": "Mostrar Anuncios",
|
||||
"showAdsDescription": "Cuando está habilitado, se mostrarán anuncios en los dispositivos"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Estado",
|
||||
"subject": "Asunto",
|
||||
"template": "Plantilla",
|
||||
"traffic_exceed_email_template": "Plantilla de Notificación de Exceso de Tráfico",
|
||||
"traffic_exceed_email_templateDescription": "Los marcadores de posición {after}.variable{before} serán reemplazados con datos reales. Asegúrate de mantener estas variables.",
|
||||
"verify_email_template": "Plantilla de Correo Electrónico de Verificación",
|
||||
"verify_email_templateDescription": "Los marcadores de posición {after}.variable{before} serán reemplazados con datos reales. Asegúrese de mantener estas variables.",
|
||||
"whitelistSuffixes": "Sufijos de la lista blanca",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "Configuración de ADS",
|
||||
"Announcement Management": "Gestión de Anuncios",
|
||||
"Apple": "ID de Apple",
|
||||
"Auth Control": "Control de Autenticación",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Pago con Alipay",
|
||||
"alipayf2f": {
|
||||
"appId": "ID de la aplicación de Alipay",
|
||||
"invoiceName": "Nombre personalizado del producto",
|
||||
"invoiceNameDescription": "Se mostrará en la factura de Alipay",
|
||||
"privateKey": "Clave privada de Alipay",
|
||||
"publicKey": "Clave pública de Alipay",
|
||||
"sandbox": "Modo sandbox",
|
||||
"sandboxDescription": "Habilitar el modo sandbox para probar el pago"
|
||||
},
|
||||
"AlipayF2F": "Alipay Cara a Cara",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Solicitar Pago",
|
||||
"balance": "Saldo",
|
||||
"batchDelete": "Eliminar en Lote",
|
||||
"cancel": "Cancelar",
|
||||
"config": "Configuración",
|
||||
"configInfo": "Información de Configuración",
|
||||
"configPlaceholder": "Por favor, complete la configuración de {field} proporcionada",
|
||||
"confirm": "Confirmar",
|
||||
"confirmDelete": "Confirmar Eliminación",
|
||||
"copy": "Copiar",
|
||||
"copySuccess": "Copiado con éxito",
|
||||
"create": "Agregar Método de Pago",
|
||||
"createPayment": "Agregar Método de Pago",
|
||||
"createSuccess": "Creado con éxito",
|
||||
"delete": "Eliminar",
|
||||
"deleteSuccess": "Eliminado con éxito",
|
||||
"deleteWarning": "¿Está seguro de que desea eliminar este método de pago? Esta acción no se puede deshacer.",
|
||||
"description": "Descripción",
|
||||
"descriptionPlaceholder": "Ingrese la descripción del método de pago",
|
||||
"domain": "Dominio",
|
||||
"domainPlaceholder": "opcional, p. ej. {example}",
|
||||
"edit": "Editar",
|
||||
"editPayment": "Editar Método de Pago",
|
||||
"enable": "Habilitar",
|
||||
"enableDescription": "Habilitar este método de pago",
|
||||
"epay": {
|
||||
"key": "CLAVE",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Monto Fijo",
|
||||
"feeMode": "Modo de cobro",
|
||||
"feeModeDescription": "Modo de cobro de tarifas adicionales",
|
||||
"feeModeItems": ["Sin tarifa", "Porcentaje", "Cantidad fija", "Ambos anteriores"],
|
||||
"feePercent": "Porcentaje de tarifa (opcional)",
|
||||
"feePercentDescription": "Se añade una tarifa sobre el monto del pedido",
|
||||
"fixedFee": "Tarifa fija (opcional)",
|
||||
"fixedFeeDescription": "Se añade una tarifa fija sobre el monto del pedido",
|
||||
"iconUrl": "URL del icono (opcional)",
|
||||
"iconUrlDescription": "Usado para mostrar en el frontend",
|
||||
"inputPlaceholder": "Por favor, introduzca",
|
||||
"key": "CLAVE",
|
||||
"notifyUrl": "Dominio de notificación personalizado (opcional)",
|
||||
"notifyUrlDescription": "La notificación del gateway se enviará a este dominio",
|
||||
"payForRecommendations": "Pagar por recomendaciones",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Guardado exitosamente",
|
||||
"showName": "Mostrar nombre",
|
||||
"showNameDescription": "Usado para mostrar en el frontend",
|
||||
"stripe": {
|
||||
"publicKey": "CLAVE PÚBLICA",
|
||||
"secretKey": "CLAVE SECRETA",
|
||||
"webhookSecret": "FIRMA DE CLAVE WEBHOOK"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "Pago con WeChat"
|
||||
"handlingFee": "Tarifa de manejo",
|
||||
"icon": "Ícono",
|
||||
"iconPlaceholder": "Ingrese la URL del ícono",
|
||||
"mark": "Identificador",
|
||||
"markPlaceholder": "Ingrese el identificador del método de pago",
|
||||
"name": "Nombre",
|
||||
"namePlaceholder": "Ingrese el nombre del método de pago",
|
||||
"nameRequired": "El nombre es obligatorio",
|
||||
"noFee": "Sin Tarifa",
|
||||
"notify_url": "URL de notificación",
|
||||
"paymentManagement": "Gestión de Pagos",
|
||||
"percentFee": "Porcentaje",
|
||||
"platform": "Plataforma",
|
||||
"searchPlaceholder": "Ingrese términos de búsqueda",
|
||||
"selectPlatform": "Seleccionar Plataforma",
|
||||
"selectType": "Seleccionar tipo de pago",
|
||||
"submit": "Enviar",
|
||||
"type": "Tipo",
|
||||
"updateSuccess": "Actualizado con éxito"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Política de Privacidad"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Datos Personalizados",
|
||||
"customDataDescription": "Datos Personalizados, utilizados para datos personalizados del sitio",
|
||||
"customHtml": "HTML personalizado",
|
||||
"customHtmlDescription": "Código HTML personalizado que se inyectará en la parte inferior de la etiqueta body del sitio.",
|
||||
"keywords": "Palabras clave",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Confirmar",
|
||||
"confirmDelete": "Confirmar Eliminación",
|
||||
"create": "Crear Anuncio",
|
||||
"createAds": "Crear Publicidad",
|
||||
"createSuccess": "Creado con éxito",
|
||||
"delete": "Eliminar",
|
||||
"deleteSuccess": "Eliminado con éxito",
|
||||
"deleteWarning": "¿Está seguro de que desea eliminar este anuncio?",
|
||||
"disabled": "Deshabilitado",
|
||||
"edit": "Editar",
|
||||
"editAds": "Editar Publicidad",
|
||||
"enabled": "Habilitado",
|
||||
"form": {
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Confirmar",
|
||||
"content": "Contenido",
|
||||
"description": "Descripción",
|
||||
"endTime": "Hora de Finalización",
|
||||
"enterContent": "Por favor ingrese el contenido del anuncio",
|
||||
"enterDescription": "Por favor ingrese la descripción del anuncio",
|
||||
"enterEndTime": "Por favor seleccione la hora de finalización",
|
||||
"enterStartTime": "Por favor seleccione la hora de inicio",
|
||||
"enterTargetUrl": "Por favor ingrese la URL de destino",
|
||||
"enterTitle": "Por favor ingrese el título del anuncio",
|
||||
"startTime": "Hora de Inicio",
|
||||
"targetUrl": "URL de Destino",
|
||||
"title": "Título",
|
||||
"type": "Tipo de Anuncio",
|
||||
"typeImage": "Imagen",
|
||||
"typeVideo": "Video"
|
||||
},
|
||||
"status": "Estado",
|
||||
"targetUrl": "URL de Destino",
|
||||
"title": "Título",
|
||||
"type": "Tipo",
|
||||
"updateSuccess": "Actualizado con éxito",
|
||||
"validityPeriod": "Período de Validez"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Bloquear Máquina Virtual",
|
||||
"blockVirtualMachineDescription": "Cuando está habilitado, se evitará que los dispositivos se ejecuten en máquinas virtuales o emuladores",
|
||||
"communicationKey": "Clave de Comunicación",
|
||||
"communicationKeyDescription": "La clave de comunicación se utiliza para la comunicación segura entre dispositivos y servidores",
|
||||
"enable": "Habilitar",
|
||||
"enableDescription": "Después de habilitar, se admiten múltiples identificadores de dispositivos como IMEI/IDFA/IDFV/AndroidID/dirección Mac para iniciar sesión y registrarse"
|
||||
"enableDescription": "Después de habilitar, se admiten múltiples identificadores de dispositivos como IMEI/IDFA/IDFV/AndroidID/dirección Mac para iniciar sesión y registrarse",
|
||||
"enableSecurity": "Habilitar Cifrado de Comunicación",
|
||||
"enableSecurityDescription": "Cuando está habilitado, la comunicación entre dispositivos y servidores será cifrada",
|
||||
"saveFailed": "Error al guardar",
|
||||
"saveSuccess": "Guardado exitoso",
|
||||
"showAds": "Mostrar Anuncios",
|
||||
"showAdsDescription": "Cuando está habilitado, se mostrarán anuncios en los dispositivos"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Estado",
|
||||
"subject": "Asunto",
|
||||
"template": "Plantilla",
|
||||
"traffic_exceed_email_template": "Plantilla de Notificación de Exceso de Tráfico",
|
||||
"traffic_exceed_email_templateDescription": "Los marcadores de posición {after}.variable{before} serán reemplazados con datos reales. Asegúrate de mantener estas variables.",
|
||||
"verify_email_template": "Plantilla de Correo Electrónico de Verificación",
|
||||
"verify_email_templateDescription": "Los marcadores de posición {after}.variable{before} serán reemplazados con datos reales. Asegúrate de mantener estas variables.",
|
||||
"whitelistSuffixes": "Sufijos de Lista Blanca",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "Configuración de ADS",
|
||||
"Announcement Management": "Gestión de Anuncios",
|
||||
"Apple": "ID de Apple",
|
||||
"Auth Control": "Control de Autenticación",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Pago con Alipay",
|
||||
"alipayf2f": {
|
||||
"appId": "ID de la aplicación de Alipay",
|
||||
"invoiceName": "Nombre personalizado del producto",
|
||||
"invoiceNameDescription": "Se mostrará en la factura de Alipay",
|
||||
"privateKey": "Clave privada de Alipay",
|
||||
"publicKey": "Clave pública de Alipay",
|
||||
"sandbox": "Modo sandbox",
|
||||
"sandboxDescription": "Habilitar el modo sandbox para probar el pago"
|
||||
},
|
||||
"AlipayF2F": "Alipay Cara a Cara",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Solicitar Pago",
|
||||
"balance": "Saldo",
|
||||
"batchDelete": "Eliminar en Lote",
|
||||
"cancel": "Cancelar",
|
||||
"config": "Configuración",
|
||||
"configInfo": "Información de Configuración",
|
||||
"configPlaceholder": "Por favor, complete la configuración de {field} proporcionada",
|
||||
"confirm": "Confirmar",
|
||||
"confirmDelete": "Confirmar Eliminación",
|
||||
"copy": "Copiar",
|
||||
"copySuccess": "Copiado con éxito",
|
||||
"create": "Agregar Método de Pago",
|
||||
"createPayment": "Agregar Método de Pago",
|
||||
"createSuccess": "Creado con éxito",
|
||||
"delete": "Eliminar",
|
||||
"deleteSuccess": "Eliminado con éxito",
|
||||
"deleteWarning": "¿Está seguro de que desea eliminar este método de pago? Esta acción no se puede deshacer.",
|
||||
"description": "Descripción",
|
||||
"descriptionPlaceholder": "Ingresa la descripción del método de pago",
|
||||
"domain": "Dominio",
|
||||
"domainPlaceholder": "opcional, p. ej. {example}",
|
||||
"edit": "Editar",
|
||||
"editPayment": "Editar Método de Pago",
|
||||
"enable": "Habilitar",
|
||||
"enableDescription": "Habilitar este método de pago",
|
||||
"epay": {
|
||||
"key": "CLAVE",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Monto Fijo",
|
||||
"feeMode": "Modo de cobro",
|
||||
"feeModeDescription": "Modo de cobro de tarifas adicionales",
|
||||
"feeModeItems": ["Sin tarifa", "Porcentaje", "Cantidad fija", "Ambos"],
|
||||
"feePercent": "Porcentaje de tarifa (opcional)",
|
||||
"feePercentDescription": "Se añade una tarifa sobre el monto del pedido",
|
||||
"fixedFee": "Cuota fija (opcional)",
|
||||
"fixedFeeDescription": "Agregar una tarifa fija sobre el monto del pedido",
|
||||
"iconUrl": "URL del ícono (opcional)",
|
||||
"iconUrlDescription": "Usado para mostrar en el frontend",
|
||||
"inputPlaceholder": "Por favor ingrese",
|
||||
"key": "LLAVE",
|
||||
"notifyUrl": "Dominio de notificación personalizado (opcional)",
|
||||
"notifyUrlDescription": "La notificación del gateway se enviará a este dominio",
|
||||
"payForRecommendations": "Pagar por recomendaciones",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Guardado exitoso",
|
||||
"showName": "Mostrar nombre",
|
||||
"showNameDescription": "Usado para mostrar en el frontend",
|
||||
"stripe": {
|
||||
"publicKey": "CLAVE PÚBLICA",
|
||||
"secretKey": "CLAVE SECRETA",
|
||||
"webhookSecret": "FIRMA DE SECRETO DE WEBHOOK"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat Pay"
|
||||
"handlingFee": "Cargo por manejo",
|
||||
"icon": "Ícono",
|
||||
"iconPlaceholder": "Ingrese la URL del ícono",
|
||||
"mark": "Identificador",
|
||||
"markPlaceholder": "Ingrese el identificador del método de pago",
|
||||
"name": "Nombre",
|
||||
"namePlaceholder": "Ingrese el nombre del método de pago",
|
||||
"nameRequired": "El nombre es obligatorio",
|
||||
"noFee": "Sin Tarifa",
|
||||
"notify_url": "URL de notificación",
|
||||
"paymentManagement": "Gestión de Pagos",
|
||||
"percentFee": "Porcentaje",
|
||||
"platform": "Plataforma",
|
||||
"searchPlaceholder": "Ingrese términos de búsqueda",
|
||||
"selectPlatform": "Seleccionar Plataforma",
|
||||
"selectType": "Seleccionar tipo de pago",
|
||||
"submit": "Enviar",
|
||||
"type": "Tipo",
|
||||
"updateSuccess": "Actualizado con éxito"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Política de Privacidad"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Datos Personalizados",
|
||||
"customDataDescription": "Datos Personalizados, utilizados para datos personalizados del sitio",
|
||||
"customHtml": "HTML personalizado",
|
||||
"customHtmlDescription": "Código HTML personalizado que se inyectará al final de la etiqueta body del sitio.",
|
||||
"keywords": "Palabras clave",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "لغو",
|
||||
"confirm": "تأیید",
|
||||
"confirmDelete": "تأیید حذف",
|
||||
"create": "ایجاد آگهی",
|
||||
"createAds": "ایجاد تبلیغ",
|
||||
"createSuccess": "با موفقیت ایجاد شد",
|
||||
"delete": "حذف",
|
||||
"deleteSuccess": "با موفقیت حذف شد",
|
||||
"deleteWarning": "آیا مطمئن هستید که میخواهید این آگهی را حذف کنید؟",
|
||||
"disabled": "غیرفعال",
|
||||
"edit": "ویرایش",
|
||||
"editAds": "ویرایش تبلیغ",
|
||||
"enabled": "فعال",
|
||||
"form": {
|
||||
"cancel": "لغو",
|
||||
"confirm": "تأیید",
|
||||
"content": "محتوا",
|
||||
"description": "توضیحات",
|
||||
"endTime": "زمان پایان",
|
||||
"enterContent": "لطفاً محتوای آگهی را وارد کنید",
|
||||
"enterDescription": "لطفاً توضیحات آگهی را وارد کنید",
|
||||
"enterEndTime": "لطفاً زمان پایان را انتخاب کنید",
|
||||
"enterStartTime": "لطفاً زمان شروع را انتخاب کنید",
|
||||
"enterTargetUrl": "لطفاً URL هدف را وارد کنید",
|
||||
"enterTitle": "لطفاً عنوان آگهی را وارد کنید",
|
||||
"startTime": "زمان شروع",
|
||||
"targetUrl": "URL هدف",
|
||||
"title": "عنوان",
|
||||
"type": "نوع آگهی",
|
||||
"typeImage": "تصویر",
|
||||
"typeVideo": "ویدیو"
|
||||
},
|
||||
"status": "وضعیت",
|
||||
"targetUrl": "URL هدف",
|
||||
"title": "عنوان",
|
||||
"type": "نوع",
|
||||
"updateSuccess": "با موفقیت بهروزرسانی شد",
|
||||
"validityPeriod": "مدت اعتبار"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "مسدود کردن ماشین مجازی",
|
||||
"blockVirtualMachineDescription": "هنگامی که فعال باشد، دستگاهها از اجرای ماشینهای مجازی یا شبیهسازها جلوگیری خواهند شد",
|
||||
"communicationKey": "کلید ارتباطی",
|
||||
"communicationKeyDescription": "کلید ارتباطی برای ارتباط امن بین دستگاهها و سرورها استفاده میشود",
|
||||
"enable": "فعال کردن",
|
||||
"enableDescription": "پس از فعالسازی، شناسههای دستگاههای مختلف مانند IMEI/IDFA/IDFV/AndroidID/آدرس مک برای ورود و ثبتنام پشتیبانی میشوند"
|
||||
"enableDescription": "پس از فعالسازی، شناسههای دستگاههای مختلف مانند IMEI/IDFA/IDFV/AndroidID/آدرس مک برای ورود و ثبتنام پشتیبانی میشوند",
|
||||
"enableSecurity": "فعالسازی رمزنگاری ارتباطات",
|
||||
"enableSecurityDescription": "هنگامی که فعال باشد، ارتباط بین دستگاهها و سرورها رمزنگاری خواهد شد",
|
||||
"saveFailed": "ذخیرهسازی ناموفق بود",
|
||||
"saveSuccess": "ذخیرهسازی با موفقیت انجام شد",
|
||||
"showAds": "نمایش تبلیغات",
|
||||
"showAdsDescription": "هنگامی که فعال باشد، تبلیغات بر روی دستگاهها نمایش داده خواهد شد"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "وضعیت",
|
||||
"subject": "موضوع",
|
||||
"template": "الگو",
|
||||
"traffic_exceed_email_template": "الگوی اعلان ترافیک بیش از حد",
|
||||
"traffic_exceed_email_templateDescription": "جایگزینهای {after}.variable{before} با دادههای واقعی خواهد شد. اطمینان حاصل کنید که این متغیرها را حفظ کنید.",
|
||||
"verify_email_template": "قالب ایمیل تأیید",
|
||||
"verify_email_templateDescription": "جایگذاریهای {after}.variable{before} با دادههای واقعی جایگزین خواهند شد. اطمینان حاصل کنید که این متغیرها را حفظ کنید.",
|
||||
"whitelistSuffixes": "پسوندهای لیست سفید",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "تنظیمات ADS",
|
||||
"Announcement Management": "مدیریت اطلاعیهها",
|
||||
"Apple": "شناسه اپل",
|
||||
"Auth Control": "کنترل احراز هویت",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "پرداخت علیپی",
|
||||
"alipayf2f": {
|
||||
"appId": "شناسه برنامه Alipay",
|
||||
"invoiceName": "نام محصول سفارشی",
|
||||
"invoiceNameDescription": "در صورتحساب Alipay نمایش داده خواهد شد",
|
||||
"privateKey": "کلید خصوصی Alipay",
|
||||
"publicKey": "کلید عمومی Alipay",
|
||||
"sandbox": "حالت Sandbox",
|
||||
"sandboxDescription": "حالت sandbox را برای آزمایش پرداختها فعال کنید"
|
||||
},
|
||||
"AlipayF2F": "علیپی چهره به چهره",
|
||||
"EPay": "ایپی",
|
||||
"Stripe": "استرایپ",
|
||||
"applyForPayment": "درخواست پرداخت",
|
||||
"balance": "موجودی",
|
||||
"batchDelete": "حذف دستهای",
|
||||
"cancel": "لغو",
|
||||
"config": "پیکربندی",
|
||||
"configInfo": "اطلاعات پیکربندی",
|
||||
"configPlaceholder": "لطفاً پیکربندی {field} ارائه شده را پر کنید",
|
||||
"confirm": "تأیید",
|
||||
"confirmDelete": "تأیید حذف",
|
||||
"copy": "کپی",
|
||||
"copySuccess": "با موفقیت کپی شد",
|
||||
"create": "افزودن روش پرداخت",
|
||||
"createPayment": "افزودن روش پرداخت",
|
||||
"createSuccess": "با موفقیت ایجاد شد",
|
||||
"delete": "حذف",
|
||||
"deleteSuccess": "با موفقیت حذف شد",
|
||||
"deleteWarning": "آیا مطمئن هستید که میخواهید این روش پرداخت را حذف کنید؟ این عمل قابل بازگشت نیست.",
|
||||
"description": "توضیحات",
|
||||
"descriptionPlaceholder": "توضیحات روش پرداخت را وارد کنید",
|
||||
"domain": "دامنه",
|
||||
"domainPlaceholder": "اختیاری، به عنوان مثال {example}",
|
||||
"edit": "ویرایش",
|
||||
"editPayment": "ویرایش روش پرداخت",
|
||||
"enable": "فعال کردن",
|
||||
"enableDescription": "این روش پرداخت را فعال کنید",
|
||||
"epay": {
|
||||
"key": "کلید",
|
||||
"pid": "شناسه محصول",
|
||||
"url": "نشانی وب"
|
||||
},
|
||||
"feeAmount": "مقدار ثابت",
|
||||
"feeMode": "حالت هزینه",
|
||||
"feeModeDescription": "روش دریافت هزینه برای هزینههای اضافی",
|
||||
"feeModeItems": ["بدون هزینه", "درصدی", "مبلغ ثابت", "هر دو"],
|
||||
"feePercent": "درصد کارمزد (اختیاری)",
|
||||
"feePercentDescription": "افزودن کارمزد به مبلغ سفارش",
|
||||
"fixedFee": "هزینه ثابت (اختیاری)",
|
||||
"fixedFeeDescription": "افزودن هزینه ثابت به مبلغ سفارش",
|
||||
"iconUrl": "آدرس آیکون (اختیاری)",
|
||||
"iconUrlDescription": "برای نمایش در رابط کاربری استفاده میشود",
|
||||
"inputPlaceholder": "لطفاً وارد کنید",
|
||||
"key": "کلید",
|
||||
"notifyUrl": "دامنه اعلان سفارشی (اختیاری)",
|
||||
"notifyUrlDescription": "اعلانهای درگاه به این دامنه ارسال خواهند شد",
|
||||
"payForRecommendations": "پرداخت برای توصیهها",
|
||||
"pid": "شناسه فرآیند",
|
||||
"saveSuccess": "ذخیره با موفقیت انجام شد",
|
||||
"showName": "نمایش نام",
|
||||
"showNameDescription": "برای نمایش در قسمت جلویی استفاده میشود",
|
||||
"stripe": {
|
||||
"publicKey": "کلید عمومی",
|
||||
"secretKey": "کلید مخفی",
|
||||
"webhookSecret": "کلید مخفی وبهوک"
|
||||
},
|
||||
"url": "آدرس اینترنتی",
|
||||
"wechatPay": "ویچت پی"
|
||||
"handlingFee": "هزینه خدمات",
|
||||
"icon": "آیکون",
|
||||
"iconPlaceholder": "آدرس URL آیکون را وارد کنید",
|
||||
"mark": "شناسه",
|
||||
"markPlaceholder": "شناسه روش پرداخت را وارد کنید",
|
||||
"name": "نام",
|
||||
"namePlaceholder": "نام روش پرداخت را وارد کنید",
|
||||
"nameRequired": "نام الزامی است",
|
||||
"noFee": "بدون هزینه",
|
||||
"notify_url": "آدرس اطلاعرسانی",
|
||||
"paymentManagement": "مدیریت پرداخت",
|
||||
"percentFee": "درصد",
|
||||
"platform": "پلتفرم",
|
||||
"searchPlaceholder": "عبارات جستجو را وارد کنید",
|
||||
"selectPlatform": "انتخاب پلتفرم",
|
||||
"selectType": "انتخاب نوع پرداخت",
|
||||
"submit": "ارسال",
|
||||
"type": "نوع",
|
||||
"updateSuccess": "با موفقیت بهروزرسانی شد"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "سیاست حفظ حریم خصوصی"
|
||||
},
|
||||
"site": {
|
||||
"customData": "دادههای سفارشی",
|
||||
"customDataDescription": "دادههای سفارشی، استفاده شده برای دادههای سفارشی سایت",
|
||||
"customHtml": "HTML سفارشی",
|
||||
"customHtmlDescription": "کد HTML سفارشی که باید در انتهای تگ body سایت وارد شود.",
|
||||
"keywords": "کلمات کلیدی",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Peruuta",
|
||||
"confirm": "Vahvista",
|
||||
"confirmDelete": "Vahvista poisto",
|
||||
"create": "Luo ilmoitus",
|
||||
"createAds": "Luo mainos",
|
||||
"createSuccess": "Luonti onnistui",
|
||||
"delete": "Poista",
|
||||
"deleteSuccess": "Poisto onnistui",
|
||||
"deleteWarning": "Oletko varma, että haluat poistaa tämän ilmoituksen?",
|
||||
"disabled": "Pois käytöstä",
|
||||
"edit": "Muokkaa",
|
||||
"editAds": "Muokkaa mainosta",
|
||||
"enabled": "Käytössä",
|
||||
"form": {
|
||||
"cancel": "Peruuta",
|
||||
"confirm": "Vahvista",
|
||||
"content": "Sisältö",
|
||||
"description": "Kuvaus",
|
||||
"endTime": "Loppuaika",
|
||||
"enterContent": "Ole hyvä ja syötä mainoksen sisältö",
|
||||
"enterDescription": "Ole hyvä ja syötä mainoksen kuvaus",
|
||||
"enterEndTime": "Ole hyvä ja valitse loppuaika",
|
||||
"enterStartTime": "Ole hyvä ja valitse aloitusaika",
|
||||
"enterTargetUrl": "Ole hyvä ja syötä kohde-URL",
|
||||
"enterTitle": "Ole hyvä ja syötä mainoksen otsikko",
|
||||
"startTime": "Aloitusaika",
|
||||
"targetUrl": "Kohde-URL",
|
||||
"title": "Otsikko",
|
||||
"type": "Mainostyyppi",
|
||||
"typeImage": "Kuva",
|
||||
"typeVideo": "Video"
|
||||
},
|
||||
"status": "Tila",
|
||||
"targetUrl": "Kohde-URL",
|
||||
"title": "Otsikko",
|
||||
"type": "Tyyppi",
|
||||
"updateSuccess": "Päivitys onnistui",
|
||||
"validityPeriod": "Voimassaoloaika"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Estä virtuaalikone",
|
||||
"blockVirtualMachineDescription": "Kun tämä on käytössä, laitteiden käyttö virtuaalikoneissa tai emulaattoreissa estetään",
|
||||
"communicationKey": "Viestintäavain",
|
||||
"communicationKeyDescription": "Viestintäavain käytetään turvalliseen viestintään laitteiden ja palvelimien välillä",
|
||||
"enable": "Ota käyttöön",
|
||||
"enableDescription": "Kun otat käyttöön, useita laiteidentifikaattoreita, kuten IMEI/IDFA/IDFV/AndroidID/Mac-osoite, tuetaan kirjautumiseen ja rekisteröitymiseen."
|
||||
"enableDescription": "Kun otat käyttöön, useita laiteidentifikaattoreita, kuten IMEI/IDFA/IDFV/AndroidID/Mac-osoite, tuetaan kirjautumiseen ja rekisteröitymiseen.",
|
||||
"enableSecurity": "Ota käyttöön viestinnän salaus",
|
||||
"enableSecurityDescription": "Kun tämä on käytössä, laitteiden ja palvelimien välinen viestintä salataan",
|
||||
"saveFailed": "Tallennus epäonnistui",
|
||||
"saveSuccess": "Tallennus onnistui",
|
||||
"showAds": "Näytä mainoksia",
|
||||
"showAdsDescription": "Kun tämä on käytössä, mainoksia näytetään laitteilla"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Tila",
|
||||
"subject": "Aihe",
|
||||
"template": "Malline",
|
||||
"traffic_exceed_email_template": "Liikenteen Ylitysilmoitusmalli",
|
||||
"traffic_exceed_email_templateDescription": "{after}.variable{before} -paikat korvataan todellisilla tiedoilla. Varmista, että säilytät nämä muuttujat.",
|
||||
"verify_email_template": "Sähköpostin Vahvistusmalli",
|
||||
"verify_email_templateDescription": "Paikkamerkit {after}.variable{before} korvataan todellisilla tiedoilla. Varmista, että pidät nämä muuttujat.",
|
||||
"whitelistSuffixes": "Sallittujen luetteloiden päätteet",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS-asetukset",
|
||||
"Announcement Management": "Ilmoitusten hallinta",
|
||||
"Apple": "Apple ID",
|
||||
"Auth Control": "Todennuksen hallinta",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Alipay-maksu",
|
||||
"alipayf2f": {
|
||||
"appId": "Alipay-sovelluksen ID",
|
||||
"invoiceName": "Mukautettu tuotteen nimi",
|
||||
"invoiceNameDescription": "Näkyy Alipay-laskussa",
|
||||
"privateKey": "Alipay-yksityinen avain",
|
||||
"publicKey": "Alipay-julkinen avain",
|
||||
"sandbox": "Hiekkalaatikkotila",
|
||||
"sandboxDescription": "Ota hiekkalaatikkotila käyttöön maksujen testaamiseksi"
|
||||
},
|
||||
"AlipayF2F": "Alipay Kasvokkain",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Hae maksua",
|
||||
"balance": "Saldo",
|
||||
"batchDelete": "Ryhmän poisto",
|
||||
"cancel": "Peruuta",
|
||||
"config": "Konfiguraatio",
|
||||
"configInfo": "Konfiguraatio tiedot",
|
||||
"configPlaceholder": "Täytä annettu {field} konfiguraatio",
|
||||
"confirm": "Vahvista",
|
||||
"confirmDelete": "Vahvista poisto",
|
||||
"copy": "Kopioi",
|
||||
"copySuccess": "Kopiointi onnistui",
|
||||
"create": "Lisää maksutapa",
|
||||
"createPayment": "Lisää maksutapa",
|
||||
"createSuccess": "Luonti onnistui",
|
||||
"delete": "Poista",
|
||||
"deleteSuccess": "Poisto onnistui",
|
||||
"deleteWarning": "Oletko varma, että haluat poistaa tämän maksutavan? Tätä toimintoa ei voi peruuttaa.",
|
||||
"description": "Kuvaus",
|
||||
"descriptionPlaceholder": "Syötä maksutavan kuvaus",
|
||||
"domain": "Verkkotunnus",
|
||||
"domainPlaceholder": "valinnainen, esim. {esimerkki}",
|
||||
"edit": "Muokkaa",
|
||||
"editPayment": "Muokkaa maksutapaa",
|
||||
"enable": "Ota käyttöön",
|
||||
"enableDescription": "Ota tämä maksutapa käyttöön",
|
||||
"epay": {
|
||||
"key": "AVAIN",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Kiinteä summa",
|
||||
"feeMode": "Maksutapa",
|
||||
"feeModeDescription": "Lisämaksun veloitustapa",
|
||||
"feeModeItems": ["Ei käsittelymaksua", "Prosenttiosuus", "Kiinteä summa", "Molemmat yllä olevat"],
|
||||
"feePercent": "Prosenttiosuusmaksu (valinnainen)",
|
||||
"feePercentDescription": "Lisätään maksu tilauksen summan päälle",
|
||||
"fixedFee": "Kiinteä maksu (valinnainen)",
|
||||
"fixedFeeDescription": "Lisää kiinteä maksu tilauksen summan päälle",
|
||||
"iconUrl": "Kuvakkeen URL (valinnainen)",
|
||||
"iconUrlDescription": "Käytetään etunäytössä",
|
||||
"inputPlaceholder": "Kirjoita tähän",
|
||||
"key": "AVAIN",
|
||||
"notifyUrl": "Mukautettu ilmoitusalue (valinnainen)",
|
||||
"notifyUrlDescription": "Yhdyskäytävän ilmoitus lähetetään tähän verkkotunnukseen",
|
||||
"payForRecommendations": "Maksa suosituksista",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Tallennus onnistui",
|
||||
"showName": "Näytä nimi",
|
||||
"showNameDescription": "Näytetään käyttöliittymässä",
|
||||
"stripe": {
|
||||
"publicKey": "JULKINEN AVAIN",
|
||||
"secretKey": "SALAINEN AVAIN",
|
||||
"webhookSecret": "WEBHOOK-SALAINEN ALLEKIRJOITUS"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat-maksu"
|
||||
"handlingFee": "Käsittelymaksu",
|
||||
"icon": "Ikoni",
|
||||
"iconPlaceholder": "Syötä ikonin URL-osoite",
|
||||
"mark": "Tunniste",
|
||||
"markPlaceholder": "Syötä maksutavan tunniste",
|
||||
"name": "Nimi",
|
||||
"namePlaceholder": "Syötä maksutavan nimi",
|
||||
"nameRequired": "Nimi on pakollinen",
|
||||
"noFee": "Ei maksua",
|
||||
"notify_url": "Ilmoitus-URL",
|
||||
"paymentManagement": "Maksujen hallinta",
|
||||
"percentFee": "Prosentti",
|
||||
"platform": "Alusta",
|
||||
"searchPlaceholder": "Syötä hakusanat",
|
||||
"selectPlatform": "Valitse alusta",
|
||||
"selectType": "Valitse maksutyyppi",
|
||||
"submit": "Lähetä",
|
||||
"type": "Tyyppi",
|
||||
"updateSuccess": "Päivitys onnistui"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Tietosuojakäytäntö"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Mukautettu tieto",
|
||||
"customDataDescription": "Mukautettu tieto, jota käytetään sivuston mukautettuun tietoon",
|
||||
"customHtml": "Mukautettu HTML",
|
||||
"customHtmlDescription": "Mukautettu HTML-koodi, joka lisätään sivuston body -tagin loppuun.",
|
||||
"keywords": "Avainsanat",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Annuler",
|
||||
"confirm": "Confirmer",
|
||||
"confirmDelete": "Confirmer la suppression",
|
||||
"create": "Créer une annonce",
|
||||
"createAds": "Créer une publicité",
|
||||
"createSuccess": "Créé avec succès",
|
||||
"delete": "Supprimer",
|
||||
"deleteSuccess": "Supprimé avec succès",
|
||||
"deleteWarning": "Êtes-vous sûr de vouloir supprimer cette annonce ?",
|
||||
"disabled": "Désactivé",
|
||||
"edit": "Modifier",
|
||||
"editAds": "Modifier la publicité",
|
||||
"enabled": "Activé",
|
||||
"form": {
|
||||
"cancel": "Annuler",
|
||||
"confirm": "Confirmer",
|
||||
"content": "Contenu",
|
||||
"description": "Description",
|
||||
"endTime": "Heure de fin",
|
||||
"enterContent": "Veuillez entrer le contenu de l'annonce",
|
||||
"enterDescription": "Veuillez entrer la description de l'annonce",
|
||||
"enterEndTime": "Veuillez sélectionner l'heure de fin",
|
||||
"enterStartTime": "Veuillez sélectionner l'heure de début",
|
||||
"enterTargetUrl": "Veuillez entrer l'URL cible",
|
||||
"enterTitle": "Veuillez entrer le titre de l'annonce",
|
||||
"startTime": "Heure de début",
|
||||
"targetUrl": "URL cible",
|
||||
"title": "Titre",
|
||||
"type": "Type d'annonce",
|
||||
"typeImage": "Image",
|
||||
"typeVideo": "Vidéo"
|
||||
},
|
||||
"status": "Statut",
|
||||
"targetUrl": "URL cible",
|
||||
"title": "Titre",
|
||||
"type": "Type",
|
||||
"updateSuccess": "Mis à jour avec succès",
|
||||
"validityPeriod": "Période de validité"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Bloquer la machine virtuelle",
|
||||
"blockVirtualMachineDescription": "Lorsqu'il est activé, les appareils seront empêchés de fonctionner sur des machines virtuelles ou des émulateurs",
|
||||
"communicationKey": "Clé de communication",
|
||||
"communicationKeyDescription": "La clé de communication est utilisée pour une communication sécurisée entre les appareils et les serveurs",
|
||||
"enable": "Activer",
|
||||
"enableDescription": "Après activation, plusieurs identifiants de périphériques tels que IMEI/IDFA/IDFV/AndroidID/adresse Mac sont pris en charge pour la connexion et l'enregistrement"
|
||||
"enableDescription": "Après activation, plusieurs identifiants de périphériques tels que IMEI/IDFA/IDFV/AndroidID/adresse Mac sont pris en charge pour la connexion et l'enregistrement",
|
||||
"enableSecurity": "Activer le chiffrement de la communication",
|
||||
"enableSecurityDescription": "Lorsqu'il est activé, la communication entre les appareils et les serveurs sera chiffrée",
|
||||
"saveFailed": "Échec de l'enregistrement",
|
||||
"saveSuccess": "Enregistrement réussi",
|
||||
"showAds": "Afficher les publicités",
|
||||
"showAdsDescription": "Lorsqu'il est activé, des publicités seront affichées sur les appareils"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Statut",
|
||||
"subject": "Sujet",
|
||||
"template": "Modèle",
|
||||
"traffic_exceed_email_template": "Modèle de notification de dépassement de trafic",
|
||||
"traffic_exceed_email_templateDescription": "Les espaces réservés {after}.variable{before} seront remplacés par des données réelles. Assurez-vous de conserver ces variables.",
|
||||
"verify_email_template": "Modèle d'Email de Vérification",
|
||||
"verify_email_templateDescription": "Les espaces réservés {after}.variable{before} seront remplacés par des données réelles. Assurez-vous de conserver ces variables.",
|
||||
"whitelistSuffixes": "Suffixes de la liste blanche",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "Configuration ADS",
|
||||
"Announcement Management": "Gestion des annonces",
|
||||
"Apple": "Identifiant Apple",
|
||||
"Auth Control": "Contrôle d'authentification",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Paiement par Alipay",
|
||||
"alipayf2f": {
|
||||
"appId": "ID de l'application Alipay",
|
||||
"invoiceName": "Nom personnalisé du produit",
|
||||
"invoiceNameDescription": "S'affichera sur la facture Alipay",
|
||||
"privateKey": "Clé privée Alipay",
|
||||
"publicKey": "Clé publique Alipay",
|
||||
"sandbox": "Mode bac à sable",
|
||||
"sandboxDescription": "Activez le mode bac à sable pour tester le paiement"
|
||||
},
|
||||
"AlipayF2F": "Alipay Face à Face",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Demander un paiement",
|
||||
"balance": "Solde",
|
||||
"batchDelete": "Suppression par lot",
|
||||
"cancel": "Annuler",
|
||||
"config": "Configuration",
|
||||
"configInfo": "Informations de configuration",
|
||||
"configPlaceholder": "Veuillez remplir la configuration {field} fournie",
|
||||
"confirm": "Confirmer",
|
||||
"confirmDelete": "Confirmer la suppression",
|
||||
"copy": "Copier",
|
||||
"copySuccess": "Copié avec succès",
|
||||
"create": "Ajouter un mode de paiement",
|
||||
"createPayment": "Ajouter un mode de paiement",
|
||||
"createSuccess": "Créé avec succès",
|
||||
"delete": "Supprimer",
|
||||
"deleteSuccess": "Supprimé avec succès",
|
||||
"deleteWarning": "Êtes-vous sûr de vouloir supprimer ce mode de paiement ? Cette action ne peut pas être annulée.",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Entrez la description du mode de paiement",
|
||||
"domain": "Domaine",
|
||||
"domainPlaceholder": "facultatif, par exemple {exemple}",
|
||||
"edit": "Modifier",
|
||||
"editPayment": "Modifier le mode de paiement",
|
||||
"enable": "Activer",
|
||||
"enableDescription": "Activer ce mode de paiement",
|
||||
"epay": {
|
||||
"key": "CLÉ",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Montant fixe",
|
||||
"feeMode": "Mode de facturation",
|
||||
"feeModeDescription": "Mode de facturation des frais supplémentaires",
|
||||
"feeModeItems": ["Pas de frais", "Pourcentage", "Montant fixe", "Les deux ci-dessus"],
|
||||
"feePercent": "Pourcentage de frais (optionnel)",
|
||||
"feePercentDescription": "Ajouter des frais au montant de la commande",
|
||||
"fixedFee": "Frais fixes (optionnel)",
|
||||
"fixedFeeDescription": "Ajouter des frais fixes au montant de la commande",
|
||||
"iconUrl": "URL de l'icône (facultatif)",
|
||||
"iconUrlDescription": "Utilisé pour l'affichage frontal",
|
||||
"inputPlaceholder": "Veuillez entrer",
|
||||
"key": "CLÉ",
|
||||
"notifyUrl": "Domaine de notification personnalisé (facultatif)",
|
||||
"notifyUrlDescription": "Les notifications de la passerelle seront envoyées à ce domaine",
|
||||
"payForRecommendations": "Payer pour les recommandations",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Enregistrement réussi",
|
||||
"showName": "Afficher le nom",
|
||||
"showNameDescription": "Utilisé pour l'affichage frontal",
|
||||
"stripe": {
|
||||
"publicKey": "CLÉ PUBLIQUE",
|
||||
"secretKey": "CLÉ SECRÈTE",
|
||||
"webhookSecret": "SIGNATURE DE CLÉ WEBHOOK"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "Paiement WeChat"
|
||||
"handlingFee": "Frais de traitement",
|
||||
"icon": "Icône",
|
||||
"iconPlaceholder": "Entrez l'URL de l'icône",
|
||||
"mark": "Identifiant",
|
||||
"markPlaceholder": "Entrez l'identifiant du mode de paiement",
|
||||
"name": "Nom",
|
||||
"namePlaceholder": "Entrez le nom du mode de paiement",
|
||||
"nameRequired": "Le nom est requis",
|
||||
"noFee": "Pas de frais",
|
||||
"notify_url": "URL de notification",
|
||||
"paymentManagement": "Gestion des paiements",
|
||||
"percentFee": "Pourcentage",
|
||||
"platform": "Plateforme",
|
||||
"searchPlaceholder": "Entrez des termes de recherche",
|
||||
"selectPlatform": "Sélectionner la plateforme",
|
||||
"selectType": "Sélectionner le type de paiement",
|
||||
"submit": "Soumettre",
|
||||
"type": "Type",
|
||||
"updateSuccess": "Mis à jour avec succès"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Politique de confidentialité"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Données personnalisées",
|
||||
"customDataDescription": "Données personnalisées, utilisées pour les données personnalisées du site",
|
||||
"customHtml": "HTML personnalisé",
|
||||
"customHtmlDescription": "Code HTML personnalisé à injecter dans le bas de la balise body du site.",
|
||||
"keywords": "Mots-clés",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "रद्द करें",
|
||||
"confirm": "पुष्टि करें",
|
||||
"confirmDelete": "हटाने की पुष्टि करें",
|
||||
"create": "विज्ञापन बनाएं",
|
||||
"createAds": "विज्ञापन बनाएं",
|
||||
"createSuccess": "सफलता से बनाया गया",
|
||||
"delete": "हटाएं",
|
||||
"deleteSuccess": "सफलता से हटाया गया",
|
||||
"deleteWarning": "क्या आप वास्तव में इस विज्ञापन को हटाना चाहते हैं?",
|
||||
"disabled": "अक्षम",
|
||||
"edit": "संपादित करें",
|
||||
"editAds": "विज्ञापन संपादित करें",
|
||||
"enabled": "सक्षम",
|
||||
"form": {
|
||||
"cancel": "रद्द करें",
|
||||
"confirm": "पुष्टि करें",
|
||||
"content": "सामग्री",
|
||||
"description": "विवरण",
|
||||
"endTime": "समाप्ति समय",
|
||||
"enterContent": "कृपया विज्ञापन सामग्री दर्ज करें",
|
||||
"enterDescription": "कृपया विज्ञापन विवरण दर्ज करें",
|
||||
"enterEndTime": "कृपया समाप्ति समय चुनें",
|
||||
"enterStartTime": "कृपया प्रारंभ समय चुनें",
|
||||
"enterTargetUrl": "कृपया लक्षित URL दर्ज करें",
|
||||
"enterTitle": "कृपया विज्ञापन शीर्षक दर्ज करें",
|
||||
"startTime": "प्रारंभ समय",
|
||||
"targetUrl": "लक्षित URL",
|
||||
"title": "शीर्षक",
|
||||
"type": "विज्ञापन प्रकार",
|
||||
"typeImage": "छवि",
|
||||
"typeVideo": "वीडियो"
|
||||
},
|
||||
"status": "स्थिति",
|
||||
"targetUrl": "लक्षित URL",
|
||||
"title": "शीर्षक",
|
||||
"type": "प्रकार",
|
||||
"updateSuccess": "सफलता से अपडेट किया गया",
|
||||
"validityPeriod": "वैधता अवधि"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "वर्चुअल मशीन को ब्लॉक करें",
|
||||
"blockVirtualMachineDescription": "जब सक्षम किया जाता है, तो उपकरणों को वर्चुअल मशीनों या एमुलेटर्स पर चलने से रोका जाएगा",
|
||||
"communicationKey": "संचार कुंजी",
|
||||
"communicationKeyDescription": "संचार कुंजी का उपयोग उपकरणों और सर्वरों के बीच सुरक्षित संचार के लिए किया जाता है",
|
||||
"enable": "सक्रिय करें",
|
||||
"enableDescription": "सक्रिय करने के बाद, लॉगिन और पंजीकरण के लिए IMEI/IDFA/IDFV/AndroidID/Mac पता जैसे कई डिवाइस पहचानकर्ताओं का समर्थन किया जाता है"
|
||||
"enableDescription": "सक्रिय करने के बाद, लॉगिन और पंजीकरण के लिए IMEI/IDFA/IDFV/AndroidID/Mac पता जैसे कई डिवाइस पहचानकर्ताओं का समर्थन किया जाता है",
|
||||
"enableSecurity": "संचार एन्क्रिप्शन सक्षम करें",
|
||||
"enableSecurityDescription": "जब सक्षम किया जाता है, तो उपकरणों और सर्वरों के बीच का संचार एन्क्रिप्ट किया जाएगा",
|
||||
"saveFailed": "सहेजना विफल",
|
||||
"saveSuccess": "सहेजना सफल",
|
||||
"showAds": "विज्ञापन दिखाएँ",
|
||||
"showAdsDescription": "जब सक्षम किया जाता है, तो उपकरणों पर विज्ञापन प्रदर्शित किए जाएंगे"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "स्थिति",
|
||||
"subject": "विषय",
|
||||
"template": "टेम्पलेट",
|
||||
"traffic_exceed_email_template": "ट्रैफिक अधिकता सूचना टेम्पलेट",
|
||||
"traffic_exceed_email_templateDescription": "{after}.variable{before} प्लेसहोल्डर्स को वास्तविक डेटा के साथ प्रतिस्थापित किया जाएगा। सुनिश्चित करें कि इन वेरिएबल्स को बनाए रखें।",
|
||||
"verify_email_template": "सत्यापन ईमेल टेम्पलेट",
|
||||
"verify_email_templateDescription": "{after}.variable{before} प्लेसहोल्डर्स को वास्तविक डेटा से बदला जाएगा। सुनिश्चित करें कि इन वेरिएबल्स को बनाए रखें।",
|
||||
"whitelistSuffixes": "श्वेतसूची प्रत्यय",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "एडीएस कॉन्फ़िग",
|
||||
"Announcement Management": "घोषणा प्रबंधन",
|
||||
"Apple": "एप्पल आईडी",
|
||||
"Auth Control": "प्रमाणिकरण नियंत्रण",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "अलीपे भुगतान",
|
||||
"alipayf2f": {
|
||||
"appId": "अलीपे एप्लिकेशन आईडी",
|
||||
"invoiceName": "कस्टम उत्पाद नाम",
|
||||
"invoiceNameDescription": "अलीपे बिल में प्रदर्शित होगा",
|
||||
"privateKey": "अलीपे निजी कुंजी",
|
||||
"publicKey": "अलीपे सार्वजनिक कुंजी",
|
||||
"sandbox": "सैंडबॉक्स मोड",
|
||||
"sandboxDescription": "भुगतान का परीक्षण करने के लिए सैंडबॉक्स मोड सक्षम करें"
|
||||
},
|
||||
"AlipayF2F": "अलीपे फेस टू फेस",
|
||||
"EPay": "ईपे",
|
||||
"Stripe": "स्ट्राइप",
|
||||
"applyForPayment": "भुगतान के लिए आवेदन करें",
|
||||
"balance": "शेष",
|
||||
"batchDelete": "बैच हटाएं",
|
||||
"cancel": "रद्द करें",
|
||||
"config": "कॉन्फ़िगरेशन",
|
||||
"configInfo": "कॉन्फ़िगरेशन जानकारी",
|
||||
"configPlaceholder": "कृपया प्रदान किए गए {field} कॉन्फ़िगरेशन को भरें",
|
||||
"confirm": "पुष्टि करें",
|
||||
"confirmDelete": "हटाने की पुष्टि करें",
|
||||
"copy": "कॉपी करें",
|
||||
"copySuccess": "सफलता से कॉपी किया गया",
|
||||
"create": "भुगतान विधि जोड़ें",
|
||||
"createPayment": "भुगतान विधि जोड़ें",
|
||||
"createSuccess": "सफलता से बनाया गया",
|
||||
"delete": "हटाएं",
|
||||
"deleteSuccess": "सफलता से हटाया गया",
|
||||
"deleteWarning": "क्या आप वास्तव में इस भुगतान विधि को हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती।",
|
||||
"description": "विवरण",
|
||||
"descriptionPlaceholder": "भुगतान विधि का विवरण दर्ज करें",
|
||||
"domain": "डोमेन",
|
||||
"domainPlaceholder": "वैकल्पिक, जैसे कि {example}",
|
||||
"edit": "संपादित करें",
|
||||
"editPayment": "भुगतान विधि संपादित करें",
|
||||
"enable": "सक्षम करें",
|
||||
"enableDescription": "इस भुगतान विधि को सक्षम करें",
|
||||
"epay": {
|
||||
"key": "कुंजी",
|
||||
"pid": "पीआईडी",
|
||||
"url": "यूआरएल"
|
||||
},
|
||||
"feeAmount": "निश्चित राशि",
|
||||
"feeMode": "शुल्क मोड",
|
||||
"feeModeDescription": "अतिरिक्त शुल्क की वसूली का तरीका",
|
||||
"feeModeItems": ["कोई शुल्क नहीं", "प्रतिशत", "निश्चित राशि", "उपरोक्त दोनों"],
|
||||
"feePercent": "प्रतिशत शुल्क (वैकल्पिक)",
|
||||
"feePercentDescription": "ऑर्डर राशि के ऊपर शुल्क जोड़ा जाएगा",
|
||||
"fixedFee": "निश्चित शुल्क (वैकल्पिक)",
|
||||
"fixedFeeDescription": "ऑर्डर राशि के ऊपर एक निश्चित शुल्क जोड़ा जाता है",
|
||||
"iconUrl": "आइकन URL (वैकल्पिक)",
|
||||
"iconUrlDescription": "फ्रंटएंड प्रदर्शन के लिए उपयोग किया जाता है",
|
||||
"inputPlaceholder": "कृपया दर्ज करें",
|
||||
"key": "कुंजी",
|
||||
"notifyUrl": "कस्टम अधिसूचना डोमेन (वैकल्पिक)",
|
||||
"notifyUrlDescription": "गेटवे सूचना इस डोमेन पर भेजी जाएगी",
|
||||
"payForRecommendations": "सिफारिशों के लिए भुगतान करें",
|
||||
"pid": "पीआईडी",
|
||||
"saveSuccess": "सहेजा गया",
|
||||
"showName": "नाम दिखाएं",
|
||||
"showNameDescription": "फ्रंटएंड प्रदर्शन के लिए उपयोग किया जाता है",
|
||||
"stripe": {
|
||||
"publicKey": "सार्वजनिक कुंजी",
|
||||
"secretKey": "गुप्त कुंजी",
|
||||
"webhookSecret": "वेबहुक कुंजी हस्ताक्षर"
|
||||
},
|
||||
"url": "यूआरएल",
|
||||
"wechatPay": "वीचैट पे"
|
||||
"handlingFee": "हैंडलिंग शुल्क",
|
||||
"icon": "चिन्ह",
|
||||
"iconPlaceholder": "चिन्ह URL दर्ज करें",
|
||||
"mark": "पहचानकर्ता",
|
||||
"markPlaceholder": "भुगतान विधि पहचानकर्ता दर्ज करें",
|
||||
"name": "नाम",
|
||||
"namePlaceholder": "भुगतान विधि का नाम दर्ज करें",
|
||||
"nameRequired": "नाम आवश्यक है",
|
||||
"noFee": "कोई शुल्क नहीं",
|
||||
"notify_url": "सूचना URL",
|
||||
"paymentManagement": "भुगतान प्रबंधन",
|
||||
"percentFee": "प्रतिशत",
|
||||
"platform": "प्लेटफ़ॉर्म",
|
||||
"searchPlaceholder": "खोज शब्द दर्ज करें",
|
||||
"selectPlatform": "प्लेटफ़ॉर्म चुनें",
|
||||
"selectType": "भुगतान प्रकार चुनें",
|
||||
"submit": "जमा करें",
|
||||
"type": "प्रकार",
|
||||
"updateSuccess": "सफलता से अपडेट किया गया"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "गोपनीयता नीति"
|
||||
},
|
||||
"site": {
|
||||
"customData": "कस्टम डेटा",
|
||||
"customDataDescription": "कस्टम डेटा, साइट के कस्टम डेटा के लिए उपयोग किया जाता है",
|
||||
"customHtml": "कस्टम HTML",
|
||||
"customHtmlDescription": "साइट के bodyैग के नीचे इंजेक्ट करने के लिए कस्टम HTML कोड।",
|
||||
"keywords": "कीवर्ड",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Mégse",
|
||||
"confirm": "Megerősítés",
|
||||
"confirmDelete": "Törlés megerősítése",
|
||||
"create": "Hirdetés létrehozása",
|
||||
"createAds": "Hirdetés létrehozása",
|
||||
"createSuccess": "Sikeresen létrehozva",
|
||||
"delete": "Törlés",
|
||||
"deleteSuccess": "Sikeresen törölve",
|
||||
"deleteWarning": "Biztosan törölni szeretné ezt a hirdetést?",
|
||||
"disabled": "Letiltva",
|
||||
"edit": "Szerkesztés",
|
||||
"editAds": "Hirdetés szerkesztése",
|
||||
"enabled": "Engedélyezve",
|
||||
"form": {
|
||||
"cancel": "Mégse",
|
||||
"confirm": "Megerősítés",
|
||||
"content": "Tartalom",
|
||||
"description": "Leírás",
|
||||
"endTime": "Befejezési idő",
|
||||
"enterContent": "Kérjük, adja meg a hirdetés tartalmát",
|
||||
"enterDescription": "Kérjük, adja meg a hirdetés leírását",
|
||||
"enterEndTime": "Kérjük, válassza ki a befejezési időt",
|
||||
"enterStartTime": "Kérjük, válassza ki a kezdési időt",
|
||||
"enterTargetUrl": "Kérjük, adja meg a cél URL-t",
|
||||
"enterTitle": "Kérjük, adja meg a hirdetés címét",
|
||||
"startTime": "Kezdési idő",
|
||||
"targetUrl": "Cél URL",
|
||||
"title": "Cím",
|
||||
"type": "Hirdetés típusa",
|
||||
"typeImage": "Kép",
|
||||
"typeVideo": "Videó"
|
||||
},
|
||||
"status": "Állapot",
|
||||
"targetUrl": "Cél URL",
|
||||
"title": "Cím",
|
||||
"type": "Típus",
|
||||
"updateSuccess": "Sikeresen frissítve",
|
||||
"validityPeriod": "Érvényességi időszak"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Virtuális gép blokkolása",
|
||||
"blockVirtualMachineDescription": "Ha engedélyezve van, az eszközök nem fognak tudni virtuális gépeken vagy emulátorokon futni",
|
||||
"communicationKey": "Kommunikációs kulcs",
|
||||
"communicationKeyDescription": "A kommunikációs kulcs a biztonságos kommunikációhoz szükséges az eszközök és a szerverek között",
|
||||
"enable": "Engedélyezés",
|
||||
"enableDescription": "Engedélyezés után több eszközazonosító, például IMEI/IDFA/IDFV/AndroidID/Mac-cím támogatott a bejelentkezéshez és a regisztrációhoz."
|
||||
"enableDescription": "Engedélyezés után több eszközazonosító, például IMEI/IDFA/IDFV/AndroidID/Mac-cím támogatott a bejelentkezéshez és a regisztrációhoz.",
|
||||
"enableSecurity": "Kommunikációs titkosítás engedélyezése",
|
||||
"enableSecurityDescription": "Ha engedélyezve van, az eszközök és a szerverek közötti kommunikáció titkosítva lesz",
|
||||
"saveFailed": "Mentés sikertelen",
|
||||
"saveSuccess": "Mentés sikeres",
|
||||
"showAds": "Hirdetések megjelenítése",
|
||||
"showAdsDescription": "Ha engedélyezve van, hirdetések fognak megjelenni az eszközökön"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Állapot",
|
||||
"subject": "Tárgy",
|
||||
"template": "Sablon",
|
||||
"traffic_exceed_email_template": "Forgalmi Túllépés Értesítő Sablon",
|
||||
"traffic_exceed_email_templateDescription": "A {after}.variable{before} helyettesítők tényleges adatokkal lesznek helyettesítve. Győződjön meg róla, hogy ezeket a változókat megőrzi.",
|
||||
"verify_email_template": "Ellenőrző Email Sablon",
|
||||
"verify_email_templateDescription": "A {after}.variable{before} helyőrzőket tényleges adatokkal fogjuk helyettesíteni. Ügyeljen arra, hogy ezeket a változókat megtartsa.",
|
||||
"whitelistSuffixes": "Engedélyezett utótagok",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS konfiguráció",
|
||||
"Announcement Management": "Hirdetménykezelés",
|
||||
"Apple": "Apple ID",
|
||||
"Auth Control": "Hitelesítési vezérlés",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Alipay fizetés",
|
||||
"alipayf2f": {
|
||||
"appId": "Alipay alkalmazásazonosító",
|
||||
"invoiceName": "Egyedi terméknév",
|
||||
"invoiceNameDescription": "A számlán az Alipay-ben fog megjelenni",
|
||||
"privateKey": "Alipay privát kulcs",
|
||||
"publicKey": "Alipay nyilvános kulcs",
|
||||
"sandbox": "Tesztkörnyezet",
|
||||
"sandboxDescription": "Tesztkörnyezet engedélyezése a fizetések teszteléséhez"
|
||||
},
|
||||
"AlipayF2F": "Alipay Személyesen",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Kérjen kifizetést",
|
||||
"balance": "Egyenleg",
|
||||
"batchDelete": "Tömeges törlés",
|
||||
"cancel": "Mégse",
|
||||
"config": "Beállítások",
|
||||
"configInfo": "Beállítási információk",
|
||||
"configPlaceholder": "Kérjük, töltse ki a megadott {field} beállítást",
|
||||
"confirm": "Megerősít",
|
||||
"confirmDelete": "Törlés megerősítése",
|
||||
"copy": "Másolás",
|
||||
"copySuccess": "Sikeresen másolva",
|
||||
"create": "Fizetési mód hozzáadása",
|
||||
"createPayment": "Fizetési mód hozzáadása",
|
||||
"createSuccess": "Sikeresen létrehozva",
|
||||
"delete": "Törlés",
|
||||
"deleteSuccess": "Sikeresen törölve",
|
||||
"deleteWarning": "Biztosan törölni szeretné ezt a fizetési módot? Ez a művelet nem vonható vissza.",
|
||||
"description": "Leírás",
|
||||
"descriptionPlaceholder": "Írja be a fizetési mód leírását",
|
||||
"domain": "Domain",
|
||||
"domainPlaceholder": "opcionális, pl. {példa}",
|
||||
"edit": "Szerkesztés",
|
||||
"editPayment": "Fizetési mód szerkesztése",
|
||||
"enable": "Engedélyezés",
|
||||
"enableDescription": "Engedélyezze ezt a fizetési módot",
|
||||
"epay": {
|
||||
"key": "KULCS",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Fix összeg",
|
||||
"feeMode": "Díjfizetési mód",
|
||||
"feeModeDescription": "További díjak felszámításának módja",
|
||||
"feeModeItems": ["Nincs díj", "Százalékos", "Fix összeg", "Mindkettő"],
|
||||
"feePercent": "Díjszázalék (opcionális)",
|
||||
"feePercentDescription": "Díj hozzáadása a rendelés összegéhez",
|
||||
"fixedFee": "Fix díj (opcionális)",
|
||||
"fixedFeeDescription": "Rögzített díj hozzáadása a rendelés összegéhez",
|
||||
"iconUrl": "Ikon URL (opcionális)",
|
||||
"iconUrlDescription": "Előnézeti kép megjelenítéséhez",
|
||||
"inputPlaceholder": "Kérjük, írja be",
|
||||
"key": "KULCS",
|
||||
"notifyUrl": "Egyéni értesítési domain (opcionális)",
|
||||
"notifyUrlDescription": "A kapu értesítéseket erre a tartományra küldi",
|
||||
"payForRecommendations": "Fizetés ajánlásokért",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Sikeres mentés",
|
||||
"showName": "Megjelenítési név",
|
||||
"showNameDescription": "Előnézet megjelenítésére használatos",
|
||||
"stripe": {
|
||||
"publicKey": "NYILVÁNOS KULCS",
|
||||
"secretKey": "TITKOS KULCS",
|
||||
"webhookSecret": "WEBHOOK TITKOS ALÁÍRÁS"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat fizetés"
|
||||
"handlingFee": "Kezelési díj",
|
||||
"icon": "Ikon",
|
||||
"iconPlaceholder": "Adja meg az ikon URL-jét",
|
||||
"mark": "Azonosító",
|
||||
"markPlaceholder": "Adja meg a fizetési mód azonosítóját",
|
||||
"name": "Név",
|
||||
"namePlaceholder": "Adja meg a fizetési mód nevét",
|
||||
"nameRequired": "A név megadása kötelező",
|
||||
"noFee": "Nincs díj",
|
||||
"notify_url": "Értesítési URL",
|
||||
"paymentManagement": "Fizetéskezelés",
|
||||
"percentFee": "Százalékos díj",
|
||||
"platform": "Platform",
|
||||
"searchPlaceholder": "Adja meg a keresési kifejezéseket",
|
||||
"selectPlatform": "Válassza ki a platformot",
|
||||
"selectType": "Válassza ki a fizetési típust",
|
||||
"submit": "Beküldés",
|
||||
"type": "Típus",
|
||||
"updateSuccess": "Sikeresen frissítve"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Adatvédelmi irányelvek"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Egyedi adatok",
|
||||
"customDataDescription": "Egyedi adatok, a webhely egyedi adatainak használatára",
|
||||
"customHtml": "Egyedi HTML",
|
||||
"customHtmlDescription": "Egyedi HTML kód, amelyet a webhely bodyímkéjének aljára kell beilleszteni.",
|
||||
"keywords": "Kulcsszavak",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "キャンセル",
|
||||
"confirm": "確認",
|
||||
"confirmDelete": "削除を確認",
|
||||
"create": "広告を作成",
|
||||
"createAds": "広告を作成",
|
||||
"createSuccess": "作成に成功しました",
|
||||
"delete": "削除",
|
||||
"deleteSuccess": "削除に成功しました",
|
||||
"deleteWarning": "この広告を削除してもよろしいですか?",
|
||||
"disabled": "無効",
|
||||
"edit": "編集",
|
||||
"editAds": "広告を編集",
|
||||
"enabled": "有効",
|
||||
"form": {
|
||||
"cancel": "キャンセル",
|
||||
"confirm": "確認",
|
||||
"content": "コンテンツ",
|
||||
"description": "説明",
|
||||
"endTime": "終了時間",
|
||||
"enterContent": "広告の内容を入力してください",
|
||||
"enterDescription": "広告の説明を入力してください",
|
||||
"enterEndTime": "終了時間を選択してください",
|
||||
"enterStartTime": "開始時間を選択してください",
|
||||
"enterTargetUrl": "ターゲットURLを入力してください",
|
||||
"enterTitle": "広告のタイトルを入力してください",
|
||||
"startTime": "開始時間",
|
||||
"targetUrl": "ターゲットURL",
|
||||
"title": "タイトル",
|
||||
"type": "広告の種類",
|
||||
"typeImage": "画像",
|
||||
"typeVideo": "動画"
|
||||
},
|
||||
"status": "ステータス",
|
||||
"targetUrl": "ターゲットURL",
|
||||
"title": "タイトル",
|
||||
"type": "種類",
|
||||
"updateSuccess": "更新に成功しました",
|
||||
"validityPeriod": "有効期限"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "仮想マシンをブロック",
|
||||
"blockVirtualMachineDescription": "有効にすると、デバイスは仮想マシンやエミュレーター上での実行が禁止されます",
|
||||
"communicationKey": "通信キー",
|
||||
"communicationKeyDescription": "通信キーは、デバイスとサーバー間の安全な通信に使用されます",
|
||||
"enable": "有効化",
|
||||
"enableDescription": "有効化後、ログインおよび登録のために、IMEI/IDFA/IDFV/AndroidID/Macアドレスなどの複数のデバイス識別子がサポートされます。"
|
||||
"enableDescription": "有効化後、ログインおよび登録のために、IMEI/IDFA/IDFV/AndroidID/Macアドレスなどの複数のデバイス識別子がサポートされます。",
|
||||
"enableSecurity": "通信暗号化を有効にする",
|
||||
"enableSecurityDescription": "有効にすると、デバイスとサーバー間の通信が暗号化されます",
|
||||
"saveFailed": "保存に失敗しました",
|
||||
"saveSuccess": "保存に成功しました",
|
||||
"showAds": "広告を表示",
|
||||
"showAdsDescription": "有効にすると、デバイスに広告が表示されます"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "ステータス",
|
||||
"subject": "件名",
|
||||
"template": "テンプレート",
|
||||
"traffic_exceed_email_template": "トラフィック超過通知テンプレート",
|
||||
"traffic_exceed_email_templateDescription": "{after}と{before}の変数は実際のデータに置き換えられます。これらの変数を保持することを確認してください。",
|
||||
"verify_email_template": "確認メールテンプレート",
|
||||
"verify_email_templateDescription": "{after}.variable{before} のプレースホルダーは実際のデータに置き換えられます。これらの変数を保持してください。",
|
||||
"whitelistSuffixes": "ホワイトリストのサフィックス",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS設定",
|
||||
"Announcement Management": "お知らせ管理",
|
||||
"Apple": "Apple ID",
|
||||
"Auth Control": "認証管理",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "アリペイ決済",
|
||||
"alipayf2f": {
|
||||
"appId": "支付宝アプリID",
|
||||
"invoiceName": "カスタム製品名",
|
||||
"invoiceNameDescription": "支付宝の請求書に表示されます",
|
||||
"privateKey": "支付宝プライベートキー",
|
||||
"publicKey": "支付宝パブリックキー",
|
||||
"sandbox": "サンドボックスモード",
|
||||
"sandboxDescription": "支払いをテストするためにサンドボックスモードを有効にします"
|
||||
},
|
||||
"AlipayF2F": "アリペイ対面",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "ストライプ",
|
||||
"applyForPayment": "支払いを申請する",
|
||||
"balance": "残高",
|
||||
"batchDelete": "一括削除",
|
||||
"cancel": "キャンセル",
|
||||
"config": "設定",
|
||||
"configInfo": "設定情報",
|
||||
"configPlaceholder": "提供された{field}の設定を入力してください",
|
||||
"confirm": "確認",
|
||||
"confirmDelete": "削除を確認",
|
||||
"copy": "コピー",
|
||||
"copySuccess": "コピー成功",
|
||||
"create": "支払い方法を追加",
|
||||
"createPayment": "支払い方法を追加",
|
||||
"createSuccess": "作成成功",
|
||||
"delete": "削除",
|
||||
"deleteSuccess": "削除成功",
|
||||
"deleteWarning": "この支払い方法を削除してもよろしいですか?この操作は元に戻せません。",
|
||||
"description": "説明",
|
||||
"descriptionPlaceholder": "支払い方法の説明を入力してください",
|
||||
"domain": "ドメイン",
|
||||
"domainPlaceholder": "任意、例:{example}",
|
||||
"edit": "編集",
|
||||
"editPayment": "支払い方法を編集",
|
||||
"enable": "有効",
|
||||
"enableDescription": "この支払い方法を有効にする",
|
||||
"epay": {
|
||||
"key": "キー",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "固定額",
|
||||
"feeMode": "料金方式",
|
||||
"feeModeDescription": "追加手数料の課金方式",
|
||||
"feeModeItems": ["手数料なし", "パーセンテージ", "固定金額", "上記の2つ"],
|
||||
"feePercent": "パーセンテージ手数料(オプション)",
|
||||
"feePercentDescription": "注文金額に追加される手数料",
|
||||
"fixedFee": "固定料金(オプション)",
|
||||
"fixedFeeDescription": "注文金額に固定料金を追加する",
|
||||
"iconUrl": "アイコンURL(任意)",
|
||||
"iconUrlDescription": "フロントエンド表示用",
|
||||
"inputPlaceholder": "入力してください",
|
||||
"key": "キー",
|
||||
"notifyUrl": "カスタム通知ドメイン(オプション)",
|
||||
"notifyUrlDescription": "ゲートウェイ通知はこのドメインに送信されます",
|
||||
"payForRecommendations": "おすすめの支払い",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "保存が成功しました",
|
||||
"showName": "表示名",
|
||||
"showNameDescription": "フロントエンド表示用",
|
||||
"stripe": {
|
||||
"publicKey": "パブリックキー",
|
||||
"secretKey": "シークレットキー",
|
||||
"webhookSecret": "WEBHOOK シークレットサイン"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChatペイ"
|
||||
"handlingFee": "手数料",
|
||||
"icon": "アイコン",
|
||||
"iconPlaceholder": "アイコンのURLを入力してください",
|
||||
"mark": "識別子",
|
||||
"markPlaceholder": "支払い方法の識別子を入力してください",
|
||||
"name": "名前",
|
||||
"namePlaceholder": "支払い方法の名前を入力してください",
|
||||
"nameRequired": "名前は必須です",
|
||||
"noFee": "手数料なし",
|
||||
"notify_url": "通知URL",
|
||||
"paymentManagement": "支払い管理",
|
||||
"percentFee": "パーセンテージ",
|
||||
"platform": "プラットフォーム",
|
||||
"searchPlaceholder": "検索用語を入力してください",
|
||||
"selectPlatform": "プラットフォームを選択",
|
||||
"selectType": "支払いタイプを選択",
|
||||
"submit": "送信",
|
||||
"type": "タイプ",
|
||||
"updateSuccess": "更新成功"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "プライバシーポリシー"
|
||||
},
|
||||
"site": {
|
||||
"customData": "カスタムデータ",
|
||||
"customDataDescription": "サイトのカスタムデータに使用されるカスタムデータ",
|
||||
"customHtml": "カスタムHTML",
|
||||
"customHtmlDescription": "サイトの body タグの下部に挿入されるカスタム HTML コード。",
|
||||
"keywords": "キーワード",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "취소",
|
||||
"confirm": "확인",
|
||||
"confirmDelete": "삭제 확인",
|
||||
"create": "광고 만들기",
|
||||
"createAds": "광고 생성",
|
||||
"createSuccess": "성공적으로 생성되었습니다",
|
||||
"delete": "삭제",
|
||||
"deleteSuccess": "성공적으로 삭제되었습니다",
|
||||
"deleteWarning": "이 광고를 삭제하시겠습니까?",
|
||||
"disabled": "비활성화됨",
|
||||
"edit": "편집",
|
||||
"editAds": "광고 편집",
|
||||
"enabled": "활성화됨",
|
||||
"form": {
|
||||
"cancel": "취소",
|
||||
"confirm": "확인",
|
||||
"content": "내용",
|
||||
"description": "설명",
|
||||
"endTime": "종료 시간",
|
||||
"enterContent": "광고 내용을 입력하세요",
|
||||
"enterDescription": "광고 설명을 입력하세요",
|
||||
"enterEndTime": "종료 시간을 선택하세요",
|
||||
"enterStartTime": "시작 시간을 선택하세요",
|
||||
"enterTargetUrl": "대상 URL을 입력하세요",
|
||||
"enterTitle": "광고 제목을 입력하세요",
|
||||
"startTime": "시작 시간",
|
||||
"targetUrl": "대상 URL",
|
||||
"title": "제목",
|
||||
"type": "광고 유형",
|
||||
"typeImage": "이미지",
|
||||
"typeVideo": "비디오"
|
||||
},
|
||||
"status": "상태",
|
||||
"targetUrl": "대상 URL",
|
||||
"title": "제목",
|
||||
"type": "유형",
|
||||
"updateSuccess": "성공적으로 업데이트되었습니다",
|
||||
"validityPeriod": "유효 기간"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "가상 머신 차단",
|
||||
"blockVirtualMachineDescription": "활성화되면, 장치가 가상 머신이나 에뮬레이터에서 실행되는 것을 방지합니다.",
|
||||
"communicationKey": "통신 키",
|
||||
"communicationKeyDescription": "통신 키는 장치와 서버 간의 안전한 통신을 위해 사용됩니다.",
|
||||
"enable": "활성화",
|
||||
"enableDescription": "활성화 후 IMEI/IDFA/IDFV/AndroidID/Mac 주소와 같은 여러 장치 식별자를 사용하여 로그인 및 등록할 수 있습니다."
|
||||
"enableDescription": "활성화 후 IMEI/IDFA/IDFV/AndroidID/Mac 주소와 같은 여러 장치 식별자를 사용하여 로그인 및 등록할 수 있습니다.",
|
||||
"enableSecurity": "통신 암호화 활성화",
|
||||
"enableSecurityDescription": "활성화되면, 장치와 서버 간의 통신이 암호화됩니다.",
|
||||
"saveFailed": "저장 실패",
|
||||
"saveSuccess": "저장 성공",
|
||||
"showAds": "광고 표시",
|
||||
"showAdsDescription": "활성화되면, 장치에 광고가 표시됩니다."
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "상태",
|
||||
"subject": "제목",
|
||||
"template": "템플릿",
|
||||
"traffic_exceed_email_template": "트래픽 초과 알림 템플릿",
|
||||
"traffic_exceed_email_templateDescription": "{after}.variable{before} 자리표시는 실제 데이터로 대체됩니다. 이러한 변수를 유지해야 합니다.",
|
||||
"verify_email_template": "이메일 인증 템플릿",
|
||||
"verify_email_templateDescription": "{after}.variable{before} 자리표시는 실제 데이터로 대체됩니다. 이 변수를 반드시 유지하십시오.",
|
||||
"whitelistSuffixes": "허용 목록 접미사",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS 구성",
|
||||
"Announcement Management": "공지 관리",
|
||||
"Apple": "Apple ID",
|
||||
"Auth Control": "인증 제어",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "알리페이 결제",
|
||||
"alipayf2f": {
|
||||
"appId": "알리페이 애플리케이션 ID",
|
||||
"invoiceName": "사용자 정의 제품 이름",
|
||||
"invoiceNameDescription": "알리페이 청구서에 표시됩니다",
|
||||
"privateKey": "알리페이 개인 키",
|
||||
"publicKey": "알리페이 공개 키",
|
||||
"sandbox": "샌드박스 모드",
|
||||
"sandboxDescription": "결제를 테스트하기 위해 샌드박스 모드를 활성화합니다"
|
||||
},
|
||||
"AlipayF2F": "알리페이 대면 결제",
|
||||
"EPay": "이페이",
|
||||
"Stripe": "스트라이프",
|
||||
"applyForPayment": "결제 신청",
|
||||
"balance": "잔액",
|
||||
"batchDelete": "일괄 삭제",
|
||||
"cancel": "취소",
|
||||
"config": "설정",
|
||||
"configInfo": "설정 정보",
|
||||
"configPlaceholder": "{field} 설정을 입력해 주세요",
|
||||
"confirm": "확인",
|
||||
"confirmDelete": "삭제 확인",
|
||||
"copy": "복사",
|
||||
"copySuccess": "복사 성공",
|
||||
"create": "결제 수단 추가",
|
||||
"createPayment": "결제 수단 추가",
|
||||
"createSuccess": "생성 성공",
|
||||
"delete": "삭제",
|
||||
"deleteSuccess": "삭제 성공",
|
||||
"deleteWarning": "이 결제 수단을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.",
|
||||
"description": "설명",
|
||||
"descriptionPlaceholder": "결제 수단 설명을 입력하세요",
|
||||
"domain": "도메인",
|
||||
"domainPlaceholder": "선택 사항, 예: {example}",
|
||||
"edit": "편집",
|
||||
"editPayment": "결제 수단 편집",
|
||||
"enable": "사용",
|
||||
"enableDescription": "이 결제 수단을 활성화합니다",
|
||||
"epay": {
|
||||
"key": "키",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "고정 금액",
|
||||
"feeMode": "요금 방식",
|
||||
"feeModeDescription": "추가 수수료의 부과 방식",
|
||||
"feeModeItems": ["수수료 없음", "백분율", "고정 금액", "이상 두 가지"],
|
||||
"feePercent": "수수료 비율(선택 사항)",
|
||||
"feePercentDescription": "주문 금액에 추가 요금 부과",
|
||||
"fixedFee": "고정 수수료(선택 사항)",
|
||||
"fixedFeeDescription": "주문 금액에 고정 요금 추가",
|
||||
"iconUrl": "아이콘 URL(선택 사항)",
|
||||
"iconUrlDescription": "프론트엔드 표시용",
|
||||
"inputPlaceholder": "입력하세요",
|
||||
"key": "키",
|
||||
"notifyUrl": "사용자 정의 알림 도메인 (선택 사항)",
|
||||
"notifyUrlDescription": "게이트웨이 알림이 이 도메인으로 전송됩니다",
|
||||
"payForRecommendations": "추천에 대한 지불",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "저장 성공",
|
||||
"showName": "이름 표시",
|
||||
"showNameDescription": "프론트엔드 표시용",
|
||||
"stripe": {
|
||||
"publicKey": "공개 키",
|
||||
"secretKey": "비밀 키",
|
||||
"webhookSecret": "웹훅 비밀 서명"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "위챗페이"
|
||||
"handlingFee": "수수료",
|
||||
"icon": "아이콘",
|
||||
"iconPlaceholder": "아이콘 URL 입력",
|
||||
"mark": "식별자",
|
||||
"markPlaceholder": "결제 수단 식별자 입력",
|
||||
"name": "이름",
|
||||
"namePlaceholder": "결제 수단 이름 입력",
|
||||
"nameRequired": "이름은 필수입니다",
|
||||
"noFee": "수수료 없음",
|
||||
"notify_url": "알림 URL",
|
||||
"paymentManagement": "결제 관리",
|
||||
"percentFee": "백분율",
|
||||
"platform": "플랫폼",
|
||||
"searchPlaceholder": "검색어 입력",
|
||||
"selectPlatform": "플랫폼 선택",
|
||||
"selectType": "결제 유형 선택",
|
||||
"submit": "제출",
|
||||
"type": "유형",
|
||||
"updateSuccess": "업데이트 성공"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "개인정보 처리방침"
|
||||
},
|
||||
"site": {
|
||||
"customData": "사용자 정의 데이터",
|
||||
"customDataDescription": "사이트의 사용자 정의 데이터에 사용되는 사용자 정의 데이터",
|
||||
"customHtml": "사용자 정의 HTML",
|
||||
"customHtmlDescription": "사이트의 body그 하단에 삽입될 사용자 정의 HTML 코드입니다.",
|
||||
"keywords": "키워드",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Avbryt",
|
||||
"confirm": "Bekreft",
|
||||
"confirmDelete": "Bekreft sletting",
|
||||
"create": "Opprett annonse",
|
||||
"createAds": "Opprett annonse",
|
||||
"createSuccess": "Opprettet med suksess",
|
||||
"delete": "Slett",
|
||||
"deleteSuccess": "Slettet med suksess",
|
||||
"deleteWarning": "Er du sikker på at du vil slette denne annonsen?",
|
||||
"disabled": "Deaktivert",
|
||||
"edit": "Rediger",
|
||||
"editAds": "Rediger annonse",
|
||||
"enabled": "Aktivert",
|
||||
"form": {
|
||||
"cancel": "Avbryt",
|
||||
"confirm": "Bekreft",
|
||||
"content": "Innhold",
|
||||
"description": "Beskrivelse",
|
||||
"endTime": "Sluttid",
|
||||
"enterContent": "Vennligst skriv inn annonseinnhold",
|
||||
"enterDescription": "Vennligst skriv inn annonsebeskrivelse",
|
||||
"enterEndTime": "Vennligst velg sluttid",
|
||||
"enterStartTime": "Vennligst velg starttid",
|
||||
"enterTargetUrl": "Vennligst skriv inn mål-URL",
|
||||
"enterTitle": "Vennligst skriv inn annonsetittel",
|
||||
"startTime": "Starttid",
|
||||
"targetUrl": "Mål-URL",
|
||||
"title": "Tittel",
|
||||
"type": "Annonsetype",
|
||||
"typeImage": "Bilde",
|
||||
"typeVideo": "Video"
|
||||
},
|
||||
"status": "Status",
|
||||
"targetUrl": "Mål-URL",
|
||||
"title": "Tittel",
|
||||
"type": "Type",
|
||||
"updateSuccess": "Oppdatert med suksess",
|
||||
"validityPeriod": "Gyldighetsperiode"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Blokker virtuell maskin",
|
||||
"blockVirtualMachineDescription": "Når aktivert, vil enheter bli forhindret fra å kjøre på virtuelle maskiner eller emulatorer",
|
||||
"communicationKey": "Kommunikasjonsnøkkel",
|
||||
"communicationKeyDescription": "Kommunikasjonsnøkkelen brukes for sikker kommunikasjon mellom enheter og servere",
|
||||
"enable": "Aktiver",
|
||||
"enableDescription": "Etter aktivering støttes flere enhetsidentifikatorer som IMEI/IDFA/IDFV/AndroidID/Mac-adresse for pålogging og registrering"
|
||||
"enableDescription": "Etter aktivering støttes flere enhetsidentifikatorer som IMEI/IDFA/IDFV/AndroidID/Mac-adresse for pålogging og registrering",
|
||||
"enableSecurity": "Aktiver kommunikasjonskryptering",
|
||||
"enableSecurityDescription": "Når aktivert, vil kommunikasjonen mellom enheter og servere bli kryptert",
|
||||
"saveFailed": "Lagring mislyktes",
|
||||
"saveSuccess": "Lagring vellykket",
|
||||
"showAds": "Vis annonser",
|
||||
"showAdsDescription": "Når aktivert, vil annonser bli vist på enhetene"
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"status": "Status",
|
||||
"subject": "Emne",
|
||||
"template": "Mal",
|
||||
"traffic_exceed_email_template": "Varsel om overskridelse av trafikk",
|
||||
"traffic_exceed_email_templateDescription": "Plassholderne {after}.variable{before} vil bli erstattet med faktiske data. Sørg for å beholde disse variablene.",
|
||||
"verify_email_template": "Verifikasjons-e-postmal",
|
||||
"verify_email_templateDescription": "Plassholderne {after}.variable{before} vil bli erstattet med faktiske data. Sørg for å beholde disse variablene.",
|
||||
"whitelistSuffixes": "Hvitelistesuffikser",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"ADS Config": "ADS-konfigurasjon",
|
||||
"Announcement Management": "Kunngjøringsadministrasjon",
|
||||
"Apple": "Apple-ID",
|
||||
"Auth Control": "Autentiseringskontroll",
|
||||
|
||||
@@ -1,44 +1,52 @@
|
||||
{
|
||||
"aliPay": "Betaling med Alipay",
|
||||
"alipayf2f": {
|
||||
"appId": "Alipay-applikasjons-ID",
|
||||
"invoiceName": "Tilpasset produktnavn",
|
||||
"invoiceNameDescription": "Vil vises på Alipay-fakturaen",
|
||||
"privateKey": "Alipay privat nøkkel",
|
||||
"publicKey": "Alipay offentlig nøkkel",
|
||||
"sandbox": "Sandkassemodus",
|
||||
"sandboxDescription": "Aktiver sandkassemodus for å teste betaling"
|
||||
},
|
||||
"AlipayF2F": "Alipay Ansikt-til-Ansikt",
|
||||
"EPay": "EPay",
|
||||
"Stripe": "Stripe",
|
||||
"applyForPayment": "Søk om betaling",
|
||||
"balance": "Saldo",
|
||||
"batchDelete": "Slett i batch",
|
||||
"cancel": "Avbryt",
|
||||
"config": "Konfigurasjon",
|
||||
"configInfo": "Konfigurasjonsinformasjon",
|
||||
"configPlaceholder": "Vennligst fyll inn den angitte {field} konfigurasjonen",
|
||||
"confirm": "Bekreft",
|
||||
"confirmDelete": "Bekreft sletting",
|
||||
"copy": "Kopier",
|
||||
"copySuccess": "Kopiert med suksess",
|
||||
"create": "Legg til betalingsmetode",
|
||||
"createPayment": "Legg til betalingsmetode",
|
||||
"createSuccess": "Opprettet med suksess",
|
||||
"delete": "Slett",
|
||||
"deleteSuccess": "Slettet med suksess",
|
||||
"deleteWarning": "Er du sikker på at du vil slette denne betalingsmetoden? Denne handlingen kan ikke angres.",
|
||||
"description": "Beskrivelse",
|
||||
"descriptionPlaceholder": "Skriv inn beskrivelse av betalingsmetode",
|
||||
"domain": "Domene",
|
||||
"domainPlaceholder": "valgfritt, f.eks. {example}",
|
||||
"edit": "Rediger",
|
||||
"editPayment": "Rediger betalingsmetode",
|
||||
"enable": "Aktiver",
|
||||
"enableDescription": "Aktiver denne betalingsmetoden",
|
||||
"epay": {
|
||||
"key": "NØKKEL",
|
||||
"pid": "PID",
|
||||
"url": "URL"
|
||||
},
|
||||
"feeAmount": "Fast beløp",
|
||||
"feeMode": "Avgiftsmåte",
|
||||
"feeModeDescription": "Gebyrmodus for ekstra avgifter",
|
||||
"feeModeItems": ["Ingen gebyr", "Prosentandel", "Fast beløp", "Begge ovennevnte"],
|
||||
"feePercent": "Prosentavgift (valgfritt)",
|
||||
"feePercentDescription": "Legg til et gebyr på toppen av ordrebeløpet",
|
||||
"fixedFee": "Fast gebyr (valgfritt)",
|
||||
"fixedFeeDescription": "Legg til et fast gebyr i tillegg til ordrebeløpet",
|
||||
"iconUrl": "Ikon URL (valgfritt)",
|
||||
"iconUrlDescription": "Brukes for visning på frontend",
|
||||
"inputPlaceholder": "Vennligst skriv inn",
|
||||
"key": "NØKKEL",
|
||||
"notifyUrl": "Tilpasset varslingsdomene (valgfritt)",
|
||||
"notifyUrlDescription": "Gateway-varsler vil bli sendt til dette domenet",
|
||||
"payForRecommendations": "Betal for anbefalinger",
|
||||
"pid": "PID",
|
||||
"saveSuccess": "Lagring vellykket",
|
||||
"showName": "Vis navn",
|
||||
"showNameDescription": "Brukes for visning på frontend",
|
||||
"stripe": {
|
||||
"publicKey": "OFFENTLIG NØKKEL",
|
||||
"secretKey": "HEMMELIG NØKKEL",
|
||||
"webhookSecret": "WEBHOOK SIGNATUR"
|
||||
},
|
||||
"url": "URL",
|
||||
"wechatPay": "WeChat-betaling"
|
||||
"handlingFee": "Håndteringsgebyr",
|
||||
"icon": "Ikon",
|
||||
"iconPlaceholder": "Skriv inn ikon-URL",
|
||||
"mark": "Identifikator",
|
||||
"markPlaceholder": "Skriv inn identifikator for betalingsmetode",
|
||||
"name": "Navn",
|
||||
"namePlaceholder": "Skriv inn navn på betalingsmetode",
|
||||
"nameRequired": "Navn er påkrevd",
|
||||
"noFee": "Ingen gebyr",
|
||||
"notify_url": "Varslings-URL",
|
||||
"paymentManagement": "Betalingsadministrasjon",
|
||||
"percentFee": "Prosentandel",
|
||||
"platform": "Plattform",
|
||||
"searchPlaceholder": "Skriv inn søkeord",
|
||||
"selectPlatform": "Velg plattform",
|
||||
"selectType": "Velg betalingstype",
|
||||
"submit": "Send inn",
|
||||
"type": "Type",
|
||||
"updateSuccess": "Oppdatert med suksess"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"title": "Personvernerklæring"
|
||||
},
|
||||
"site": {
|
||||
"customData": "Egendata",
|
||||
"customDataDescription": "Egendata, brukt for egendata på nettstedet",
|
||||
"customHtml": "Egendefinert HTML",
|
||||
"customHtmlDescription": "Egendefinert HTML-kode som skal settes inn i bunnen av nettstedets body-tag.",
|
||||
"keywords": "Nøkkelord",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"cancel": "Anuluj",
|
||||
"confirm": "Potwierdź",
|
||||
"confirmDelete": "Potwierdź usunięcie",
|
||||
"create": "Utwórz reklamę",
|
||||
"createAds": "Utwórz ogłoszenie",
|
||||
"createSuccess": "Pomyślnie utworzono",
|
||||
"delete": "Usuń",
|
||||
"deleteSuccess": "Pomyślnie usunięto",
|
||||
"deleteWarning": "Czy na pewno chcesz usunąć tę reklamę?",
|
||||
"disabled": "Wyłączone",
|
||||
"edit": "Edytuj",
|
||||
"editAds": "Edytuj ogłoszenie",
|
||||
"enabled": "Włączone",
|
||||
"form": {
|
||||
"cancel": "Anuluj",
|
||||
"confirm": "Potwierdź",
|
||||
"content": "Treść",
|
||||
"description": "Opis",
|
||||
"endTime": "Czas zakończenia",
|
||||
"enterContent": "Proszę wprowadzić treść reklamy",
|
||||
"enterDescription": "Proszę wprowadzić opis reklamy",
|
||||
"enterEndTime": "Proszę wybrać czas zakończenia",
|
||||
"enterStartTime": "Proszę wybrać czas rozpoczęcia",
|
||||
"enterTargetUrl": "Proszę wprowadzić docelowy URL",
|
||||
"enterTitle": "Proszę wprowadzić tytuł reklamy",
|
||||
"startTime": "Czas rozpoczęcia",
|
||||
"targetUrl": "Docelowy URL",
|
||||
"title": "Tytuł",
|
||||
"type": "Typ reklamy",
|
||||
"typeImage": "Obraz",
|
||||
"typeVideo": "Wideo"
|
||||
},
|
||||
"status": "Status",
|
||||
"targetUrl": "Docelowy URL",
|
||||
"title": "Tytuł",
|
||||
"type": "Typ",
|
||||
"updateSuccess": "Pomyślnie zaktualizowano",
|
||||
"validityPeriod": "Okres ważności"
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"blockVirtualMachine": "Zablokuj maszynę wirtualną",
|
||||
"blockVirtualMachineDescription": "Po włączeniu urządzenia nie będą mogły działać na maszynach wirtualnych lub emulatorach",
|
||||
"communicationKey": "Klucz komunikacji",
|
||||
"communicationKeyDescription": "Klucz komunikacji jest używany do bezpiecznej komunikacji między urządzeniami a serwerami",
|
||||
"enable": "Włącz",
|
||||
"enableDescription": "Po włączeniu obsługiwane są różne identyfikatory urządzeń, takie jak IMEI/IDFA/IDFV/AndroidID/adres MAC do logowania i rejestracji"
|
||||
"enableDescription": "Po włączeniu obsługiwane są różne identyfikatory urządzeń, takie jak IMEI/IDFA/IDFV/AndroidID/adres MAC do logowania i rejestracji",
|
||||
"enableSecurity": "Włącz szyfrowanie komunikacji",
|
||||
"enableSecurityDescription": "Po włączeniu komunikacja między urządzeniami a serwerami będzie szyfrowana",
|
||||
"saveFailed": "Zapis nie powiódł się",
|
||||
"saveSuccess": "Zapisano pomyślnie",
|
||||
"showAds": "Wyświetl reklamy",
|
||||
"showAdsDescription": "Po włączeniu na urządzeniach będą wyświetlane reklamy"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user