Compare commits

...

21 Commits

Author SHA1 Message Date
semantic-release-bot a7936de6dc 🔖 chore(release): v1.3.0 [skip ci]
# [1.3.0](https://github.com/perfect-panel/ppanel-web/compare/v1.2.0...v1.3.0) (2025-08-15)

### ♻ Code Refactoring

* Refactoring and adding multiple features ([65c9b9f](https://github.com/perfect-panel/ppanel-web/commit/65c9b9f))

###  Features

* **api**: Add getClient API endpoint to retrieve subscription applications ([7a279e6](https://github.com/perfect-panel/ppanel-web/commit/7a279e6))
* **marketing**: Add marketing management features and localization updates ([ea08de0](https://github.com/perfect-panel/ppanel-web/commit/ea08de0))
* **protocol**: Add template preview functionality with localization support ([0448d21](https://github.com/perfect-panel/ppanel-web/commit/0448d21))
* **subscribe**: Update subscription management localization and add new fields ([1d9b0a4](https://github.com/perfect-panel/ppanel-web/commit/1d9b0a4))

### 🐛 Bug Fixes

* **bun**: Update bun.lockb to reflect dependency changes ([bbcd018](https://github.com/perfect-panel/ppanel-web/commit/bbcd018))
* **editor**: Add Go template editor component and update related schemas ([9d9c3cd](https://github.com/perfect-panel/ppanel-web/commit/9d9c3cd))
* **editor**: Enhance Go Template Editor to support trimmed template tags and improve range/end matching ([641ed5e](https://github.com/perfect-panel/ppanel-web/commit/641ed5e))
* **editor**: Enhance Go Template Editor with schema support and improved completion ([5b21d8a](https://github.com/perfect-panel/ppanel-web/commit/5b21d8a))
* **enhaced-input**: Disable autocomplete for EnhancedInput component ([f190c68](https://github.com/perfect-panel/ppanel-web/commit/f190c68))
* **global**: Add user agent limit settings to subscription configuration ([822416d](https://github.com/perfect-panel/ppanel-web/commit/822416d))
* **locales**: Update 'conf' output format to use uppercase 'CONF' ([fce9119](https://github.com/perfect-panel/ppanel-web/commit/fce9119))
* **locales**: Update "userAccount" label to "user" in multiple localization files ([48415e9](https://github.com/perfect-panel/ppanel-web/commit/48415e9))
* **protocol-form**: Swap 'description' and 'user_agent' columns for improved clarity in the table ([72a4106](https://github.com/perfect-panel/ppanel-web/commit/72a4106))
* **protocol-form**: Update protocol options descriptions for clarity and add new security and transport options ([e5d4deb](https://github.com/perfect-panel/ppanel-web/commit/e5d4deb))
* **protocol**: Add 'conf' output format option and update translations ([292efdf](https://github.com/perfect-panel/ppanel-web/commit/292efdf))
* **protpcp-form**: Rename 'schema' to 'scheme' for consistency across the application ([6ab2ba9](https://github.com/perfect-panel/ppanel-web/commit/6ab2ba9))
* **register**: Update localization files to include trial subscription settings and descriptions ([33daa1f](https://github.com/perfect-panel/ppanel-web/commit/33daa1f))
* **system**: Add time unit translations for user registration settings in multiple languages ([296a6c1](https://github.com/perfect-panel/ppanel-web/commit/296a6c1))
* Update privacy policy and terms of service schemas to use correct field names ([0e6ba5b](https://github.com/perfect-panel/ppanel-web/commit/0e6ba5b))
2025-08-15 16:47:17 +00:00
web 72a4106022 🐛 fix(protocol-form): Swap 'description' and 'user_agent' columns for improved clarity in the table 2025-08-15 09:43:02 -07:00
web 6ab2ba92a0 🐛 fix(protpcp-form): Rename 'schema' to 'scheme' for consistency across the application 2025-08-15 04:30:20 -07:00
web e5d4deb346 🐛 fix(protocol-form): Update protocol options descriptions for clarity and add new security and transport options 2025-08-14 10:13:12 -07:00
web 0448d213a3 feat(protocol): Add template preview functionality with localization support 2025-08-14 09:55:13 -07:00
web f190c68eb0 🐛 fix(enhaced-input): Disable autocomplete for EnhancedInput component 2025-08-13 07:39:28 -07:00
web 7a279e6e30 feat(api): Add getClient API endpoint to retrieve subscription applications 2025-08-13 07:35:58 -07:00
web 641ed5ec36 🐛 fix(editor): Enhance Go Template Editor to support trimmed template tags and improve range/end matching 2025-08-12 12:44:49 -07:00
web 5b21d8a7bc 🐛 fix(editor): Enhance Go Template Editor with schema support and improved completion 2025-08-12 12:32:00 -07:00
web fce9119567 🐛 fix(locales): Update 'conf' output format to use uppercase 'CONF' 2025-08-12 06:04:00 -07:00
web 292efdf1d8 🐛 fix(protocol): Add 'conf' output format option and update translations 2025-08-12 05:58:25 -07:00
web 9d9c3cd7b3 🐛 fix(editor): Add Go template editor component and update related schemas 2025-08-12 05:47:58 -07:00
web 296a6c10a3 🐛 fix(system): Add time unit translations for user registration settings in multiple languages 2025-08-11 04:06:39 -07:00
web 822416d22d 🐛 fix(global): Add user agent limit settings to subscription configuration 2025-08-11 03:34:14 -07:00
web bbcd018aeb 🐛 fix(bun): Update bun.lockb to reflect dependency changes 2025-08-11 03:28:14 -07:00
web 0e6ba5b081 🐛 fix: Update privacy policy and terms of service schemas to use correct field names 2025-08-10 08:10:49 -07:00
web 33daa1fb73 🐛 fix(register): Update localization files to include trial subscription settings and descriptions 2025-08-09 19:04:59 -07:00
web 1d9b0a4e06 feat(subscribe): Update subscription management localization and add new fields 2025-08-08 11:22:31 -07:00
web ea08de0aa2 feat(marketing): Add marketing management features and localization updates 2025-08-08 08:59:19 -07:00
web 65c9b9f64f ♻️ refactor: Refactoring and adding multiple features 2025-08-05 06:42:39 -07:00
web 48415e9a30 🐛 fix(locales): Update "userAccount" label to "user" in multiple localization files 2025-08-04 09:17:04 -07:00
200 changed files with 12902 additions and 4895 deletions
+39 -3
View File
@@ -1,17 +1,53 @@
<a name="readme-top"></a>
# Changelog
# [1.2.0](https://github.com/perfect-panel/ppanel-web/compare/v1.1.5...v1.2.0) (2025-08-04)
# [1.3.0](https://github.com/perfect-panel/ppanel-web/compare/v1.2.0...v1.3.0) (2025-08-15)
### ♻ Code Refactoring
* **view**: System and Auth Control ([b2b4a95](https://github.com/perfect-panel/ppanel-web/commit/b2b4a95))
* Refactoring and adding multiple features ([65c9b9f](https://github.com/perfect-panel/ppanel-web/commit/65c9b9f))
### ✨ Features
* **netlify**: Add Netlify configuration for admin and user apps with Next.js plugin ([b4d4f59](https://github.com/perfect-panel/ppanel-web/commit/b4d4f59))
* **api**: Add getClient API endpoint to retrieve subscription applications ([7a279e6](https://github.com/perfect-panel/ppanel-web/commit/7a279e6))
* **marketing**: Add marketing management features and localization updates ([ea08de0](https://github.com/perfect-panel/ppanel-web/commit/ea08de0))
* **protocol**: Add template preview functionality with localization support ([0448d21](https://github.com/perfect-panel/ppanel-web/commit/0448d21))
* **subscribe**: Update subscription management localization and add new fields ([1d9b0a4](https://github.com/perfect-panel/ppanel-web/commit/1d9b0a4))
### 🐛 Bug Fixes
* **bun**: Update bun.lockb to reflect dependency changes ([bbcd018](https://github.com/perfect-panel/ppanel-web/commit/bbcd018))
* **editor**: Add Go template editor component and update related schemas ([9d9c3cd](https://github.com/perfect-panel/ppanel-web/commit/9d9c3cd))
* **editor**: Enhance Go Template Editor to support trimmed template tags and improve range/end matching ([641ed5e](https://github.com/perfect-panel/ppanel-web/commit/641ed5e))
* **editor**: Enhance Go Template Editor with schema support and improved completion ([5b21d8a](https://github.com/perfect-panel/ppanel-web/commit/5b21d8a))
* **enhaced-input**: Disable autocomplete for EnhancedInput component ([f190c68](https://github.com/perfect-panel/ppanel-web/commit/f190c68))
* **global**: Add user agent limit settings to subscription configuration ([822416d](https://github.com/perfect-panel/ppanel-web/commit/822416d))
* **locales**: Update 'conf' output format to use uppercase 'CONF' ([fce9119](https://github.com/perfect-panel/ppanel-web/commit/fce9119))
* **locales**: Update "userAccount" label to "user" in multiple localization files ([48415e9](https://github.com/perfect-panel/ppanel-web/commit/48415e9))
* **protocol-form**: Swap 'description' and 'user_agent' columns for improved clarity in the table ([72a4106](https://github.com/perfect-panel/ppanel-web/commit/72a4106))
* **protocol-form**: Update protocol options descriptions for clarity and add new security and transport options ([e5d4deb](https://github.com/perfect-panel/ppanel-web/commit/e5d4deb))
* **protocol**: Add 'conf' output format option and update translations ([292efdf](https://github.com/perfect-panel/ppanel-web/commit/292efdf))
* **protpcp-form**: Rename 'schema' to 'scheme' for consistency across the application ([6ab2ba9](https://github.com/perfect-panel/ppanel-web/commit/6ab2ba9))
* **register**: Update localization files to include trial subscription settings and descriptions ([33daa1f](https://github.com/perfect-panel/ppanel-web/commit/33daa1f))
* **system**: Add time unit translations for user registration settings in multiple languages ([296a6c1](https://github.com/perfect-panel/ppanel-web/commit/296a6c1))
* Update privacy policy and terms of service schemas to use correct field names ([0e6ba5b](https://github.com/perfect-panel/ppanel-web/commit/0e6ba5b))
<a name="readme-top"></a>
# Changelog
# [1.2.0](https://github.com/perfect-panel/ppanel-web/compare/v1.1.5...v1.2.0) (2025-08-04)
### ♻ Code Refactoring
- **view**: System and Auth Control ([b2b4a95](https://github.com/perfect-panel/ppanel-web/commit/b2b4a95))
### ✨ Features
- **netlify**: Add Netlify configuration for admin and user apps with Next.js plugin ([b4d4f59](https://github.com/perfect-panel/ppanel-web/commit/b4d4f59))
<a name="readme-top"></a>
@@ -51,7 +51,7 @@ const formSchema = z.object({
type FormSchema = z.infer<typeof formSchema>;
export default function ConfigForm() {
const t = useTranslations('subscribe.app');
const t = useTranslations('product.app');
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
@@ -80,7 +80,7 @@ interface FormProps<T> {
export default function SubscribeAppForm<
T extends API.CreateApplicationRequest | API.UpdateApplicationRequest,
>({ trigger, title, loading, initialValues, onSubmit }: FormProps<T>) {
const t = useTranslations('subscribe.app');
const t = useTranslations('product.app');
const [open, setOpen] = useState(false);
type FormSchema = z.infer<typeof formSchema>;
@@ -17,7 +17,7 @@ import ConfigForm from './config';
import SubscribeAppForm from './form';
export default function SubscribeApp() {
const t = useTranslations('subscribe.app');
const t = useTranslations('product.app');
const [loading, setLoading] = useState(false);
const ref = useRef<ProTableActions>(null);
@@ -0,0 +1,495 @@
'use client';
import { createBatchSendEmailTask, getPreSendEmailCount } from '@/services/admin/marketing';
import { zodResolver } from '@hookform/resolvers/zod';
import { Button } from '@workspace/ui/components/button';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { Input } from '@workspace/ui/components/input';
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 { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Textarea } from '@workspace/ui/components/textarea';
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 { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { z } from 'zod';
export default function EmailBroadcastForm() {
const t = useTranslations('marketing');
// Define schema with internationalized error messages
const emailBroadcastSchema = z.object({
subject: z.string().min(1, t('subject') + ' ' + t('cannotBeEmpty')),
content: z.string().min(1, t('content') + ' ' + t('cannotBeEmpty')),
scope: z.string().default('all'),
register_start_time: z.string().optional(),
register_end_time: z.string().optional(),
additional: z
.string()
.optional()
.refine(
(value) => {
if (!value || value.trim() === '') return true;
const emails = value.split('\n').filter((email) => email.trim() !== '');
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emails.every((email) => emailRegex.test(email.trim()));
},
{
message: t('pleaseEnterValidEmailAddresses'),
},
),
scheduled: z.string().optional(),
interval: z.number().min(0.1, t('emailIntervalMinimum')).optional(),
limit: z.number().min(1, t('dailyLimit')).optional(),
});
type EmailBroadcastFormData = z.infer<typeof emailBroadcastSchema>;
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [estimatedRecipients, setEstimatedRecipients] = useState<{
users: number;
additional: number;
total: number;
}>({ users: 0, additional: 0, total: 0 });
const form = useForm<EmailBroadcastFormData>({
resolver: zodResolver(emailBroadcastSchema),
defaultValues: {
subject: '',
content: '',
scope: 'all',
register_start_time: '',
register_end_time: '',
additional: '',
scheduled: '',
interval: 1,
limit: 1000,
},
});
// Calculate recipient count
const calculateRecipients = async () => {
const formData = form.getValues();
try {
// Call API to get actual recipient count
const scope = formData.scope || 'all';
// Convert dates to timestamps if they exist
let register_start_time: number = 0;
let register_end_time: number = 0;
if (formData.register_start_time) {
register_start_time = Math.floor(new Date(formData.register_start_time).getTime());
}
if (formData.register_end_time) {
register_end_time = Math.floor(new Date(formData.register_end_time).getTime());
}
const response = await getPreSendEmailCount({
scope,
register_start_time,
register_end_time,
});
const userCount = response.data?.data?.count || 0;
// Calculate additional email count
const additionalEmails = formData.additional || '';
const additionalCount = additionalEmails
.split('\n')
.filter((email: string) => email.trim() !== '').length;
const total = userCount + additionalCount;
setEstimatedRecipients({
users: userCount,
additional: additionalCount,
total,
});
} catch (error) {
console.error('Failed to get recipient count:', error);
// Set to 0 if API fails, don't use fallback simulation
const additionalEmails = formData.additional || '';
const additionalCount = additionalEmails
.split('\n')
.filter((email: string) => email.trim() !== '').length;
setEstimatedRecipients({
users: 0,
additional: additionalCount,
total: additionalCount,
});
}
};
// Listen to form changes
const watchedValues = form.watch();
// Use useEffect to respond to form changes
useEffect(() => {
const debounceTimer = setTimeout(() => {
calculateRecipients();
}, 500); // Add debounce to avoid too frequent API calls
return () => clearTimeout(debounceTimer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
watchedValues.scope,
watchedValues.register_start_time,
watchedValues.register_end_time,
watchedValues.additional,
]);
const onSubmit = async (data: EmailBroadcastFormData) => {
setLoading(true);
try {
// Validate scheduled send time
let scheduled: number | undefined;
if (data.scheduled && data.scheduled.trim() !== '') {
const scheduledDate = new Date(data.scheduled);
const now = new Date();
if (scheduledDate <= now) {
toast.error(t('scheduledSendTimeMustBeLater'));
return;
}
scheduled = Math.floor(scheduledDate.getTime());
}
let register_start_time: number = 0;
let register_end_time: number = 0;
if (data.register_start_time) {
register_start_time = Math.floor(new Date(data.register_start_time).getTime());
}
if (data.register_end_time) {
register_end_time = Math.floor(new Date(data.register_end_time).getTime());
}
// Prepare API request data
const requestData: API.CreateBatchSendEmailTaskRequest = {
subject: data.subject,
content: data.content,
scope: data.scope,
register_start_time,
register_end_time,
additional: data.additional || undefined,
scheduled,
interval: data.interval ? data.interval * 1000 : undefined, // Convert seconds to milliseconds
limit: data.limit,
};
// Call API to create batch send email task
await createBatchSendEmailTask(requestData);
if (!data.scheduled || data.scheduled.trim() === '') {
toast.success(t('emailBroadcastTaskCreatedSuccessfully'));
} else {
toast.success(t('emailAddedToScheduledQueue'));
}
form.reset();
setOpen(false);
} catch (error) {
console.error('Email broadcast failed:', error);
toast.error(t('sendFailed'));
} finally {
setLoading(false);
}
};
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<div className='flex cursor-pointer items-center justify-between transition-colors'>
<div className='flex items-center gap-3'>
<div className='bg-primary/10 flex h-10 w-10 items-center justify-center rounded-lg'>
<Icon icon='mdi:email-send' className='text-primary h-5 w-5' />
</div>
<div className='flex-1'>
<p className='font-medium'>{t('emailBroadcast')}</p>
<p className='text-muted-foreground text-sm'>
{t('createNewEmailBroadcastCampaign')}
</p>
</div>
</div>
<Icon icon='mdi:chevron-right' className='size-6' />
</div>
</SheetTrigger>
<SheetContent className='w-[700px] max-w-full md:max-w-screen-lg'>
<SheetHeader>
<SheetTitle>{t('createBroadcast')}</SheetTitle>
</SheetHeader>
<ScrollArea className='-mx-6 h-[calc(100dvh-48px-36px-36px-env(safe-area-inset-top))] px-6'>
<Form {...form}>
<form
id='broadcast-form'
onSubmit={form.handleSubmit(onSubmit)}
className='space-y-2 pt-4'
>
<Tabs defaultValue='content' className='space-y-2'>
<TabsList className='grid w-full grid-cols-2'>
<TabsTrigger value='content'>{t('content')}</TabsTrigger>
<TabsTrigger value='settings'>{t('sendSettings')}</TabsTrigger>
</TabsList>
{/* Email Content Tab */}
<TabsContent value='content' className='space-y-2'>
<FormField
control={form.control}
name='subject'
render={({ field }) => (
<FormItem>
<FormLabel>{t('subject')}</FormLabel>
<FormControl>
<Input
placeholder={`${t('pleaseEnter')} ${t('subject').toLowerCase()}`}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='content'
render={({ field }) => (
<FormItem>
<FormLabel>{t('content')}</FormLabel>
<FormControl>
<MarkdownEditor
value={field.value}
onChange={(value) => {
form.setValue(field.name, value || '');
}}
/>
</FormControl>
<FormDescription>{t('useMarkdownEditor')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</TabsContent>
{/* Send Settings Tab */}
<TabsContent value='settings' className='space-y-2'>
{/* Send scope and estimated recipients */}
<div className='grid grid-cols-2 items-center gap-4'>
<FormField
control={form.control}
name='scope'
render={({ field }) => (
<FormItem>
<FormLabel>{t('sendScope')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || 'all'}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('selectSendScope')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='all'>{t('allUsers')}</SelectItem>
<SelectItem value='active'>{t('subscribedUsersOnly')}</SelectItem>
<SelectItem value='expired'>
{t('expiredSubscriptionUsersOnly')}
</SelectItem>
<SelectItem value='none'>{t('noSubscriptionUsersOnly')}</SelectItem>
<SelectItem value='skip'>{t('specificUsersOnly')}</SelectItem>
</SelectContent>
</Select>
<FormDescription>{t('sendScopeDescription')}</FormDescription>
</FormItem>
)}
/>
{/* Estimated recipients info */}
<div className='flex justify-end'>
<div className='border-l-primary bg-primary/10 border-l-4 px-4 py-3 text-sm'>
<span className='text-muted-foreground'>{t('estimatedRecipients')}: </span>
<span className='text-primary text-lg font-medium'>
{estimatedRecipients.total}
</span>
<span className='text-muted-foreground ml-2 text-xs'>
({t('users')}: {estimatedRecipients.users}, {t('additional')}:{' '}
{estimatedRecipients.additional})
</span>
</div>
</div>
</div>
<div className='grid grid-cols-2 gap-4'>
<FormField
control={form.control}
name='register_start_time'
render={({ field }) => (
<FormItem>
<FormLabel>{t('registrationStartDate')}</FormLabel>
<FormControl>
<EnhancedInput
type='datetime-local'
disabled={form.watch('scope') === 'skip'}
value={field.value}
onValueChange={field.onChange}
/>
</FormControl>
<FormDescription>{t('includeUsersRegisteredAfter')}</FormDescription>
</FormItem>
)}
/>
<FormField
control={form.control}
name='register_end_time'
render={({ field }) => (
<FormItem>
<FormLabel>{t('registrationEndDate')}</FormLabel>
<FormControl>
<EnhancedInput
type='datetime-local'
disabled={form.watch('scope') === 'skip'}
value={field.value}
onValueChange={field.onChange}
/>
</FormControl>
<FormDescription>{t('includeUsersRegisteredBefore')}</FormDescription>
</FormItem>
)}
/>
</div>
{/* Additional recipients */}
<FormField
control={form.control}
name='additional'
render={({ field }) => (
<FormItem>
<FormLabel>{t('additionalRecipientEmails')}</FormLabel>
<FormControl>
<Textarea
placeholder={`${t('pleaseEnter')}${t('additionalRecipientEmails').toLowerCase()}${t('onePerLine')}for example:\nexample1@domain.com\nexample2@domain.com\nexample3@domain.com`}
className='min-h-[120px] font-mono text-sm'
{...field}
/>
</FormControl>
<FormDescription>{t('additionalRecipientsDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Send time settings */}
<FormField
control={form.control}
name='scheduled'
render={({ field }) => (
<FormItem>
<FormLabel>{t('scheduledSend')}</FormLabel>
<FormControl>
<EnhancedInput
type='datetime-local'
placeholder={t('leaveEmptyForImmediateSend')}
value={field.value}
onValueChange={field.onChange}
/>
</FormControl>
<FormDescription>{t('selectSendTime')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Send rate control */}
<div className='grid grid-cols-2 gap-4'>
<FormField
control={form.control}
name='interval'
render={({ field }) => (
<FormItem>
<FormLabel>{t('emailInterval')}</FormLabel>
<FormControl>
<Input
type='number'
min={1}
step={0.1}
placeholder='1'
{...field}
onChange={(e) => field.onChange(parseFloat(e.target.value) || 1)}
/>
</FormControl>
<FormDescription>{t('intervalTimeBetweenEmails')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='limit'
render={({ field }) => (
<FormItem>
<FormLabel>{t('dailySendLimit')}</FormLabel>
<FormControl>
<Input
type='number'
min={1}
step={1}
placeholder='1000'
{...field}
onChange={(e) => field.onChange(parseInt(e.target.value) || 1000)}
/>
</FormControl>
<FormDescription>{t('maximumNumberPerDay')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</div>
</TabsContent>
</Tabs>
</form>
</Form>
</ScrollArea>
<SheetFooter className='flex flex-row items-center justify-end gap-2 pt-3'>
<Button variant='outline' onClick={() => setOpen(false)}>
{t('cancel')}
</Button>
<Button type='submit' form='broadcast-form' disabled={loading}>
{loading && <Icon icon='mdi:loading' className='mr-2 h-4 w-4 animate-spin' />}
{loading
? t('processing')
: !form.watch('scheduled') || form.watch('scheduled')?.trim() === ''
? t('sendNow')
: t('scheduleSend')}
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
@@ -0,0 +1,302 @@
'use client';
import { ProTable } from '@/components/pro-table';
import {
getBatchSendEmailTaskList,
getBatchSendEmailTaskStatus,
stopBatchSendEmailTask,
} from '@/services/admin/marketing';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@workspace/ui/components/dialog';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@workspace/ui/components/sheet';
import { Icon } from '@workspace/ui/custom-components/icon';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { toast } from 'sonner';
export default function EmailTaskManager() {
const t = useTranslations('marketing');
const [refreshing, setRefreshing] = useState<Record<number, boolean>>({});
const [selectedTask, setSelectedTask] = useState<API.BatchSendEmailTask | null>(null);
// Get task status
const refreshTaskStatus = async (taskId: number) => {
setRefreshing((prev) => ({ ...prev, [taskId]: true }));
try {
const response = await getBatchSendEmailTaskStatus({
id: taskId,
});
const taskStatus = response.data?.data;
if (taskStatus) {
// Just show success message, ProTable will auto-refresh
toast.success(t('taskStatusRefreshed'));
}
} catch (error) {
console.error('Failed to refresh task status:', error);
toast.error(t('failedToRefreshTaskStatus'));
} finally {
setRefreshing((prev) => ({ ...prev, [taskId]: false }));
}
};
// Stop task
const stopTask = async (taskId: number) => {
try {
await stopBatchSendEmailTask({
id: taskId,
});
toast.success(t('taskStoppedSuccessfully'));
await refreshTaskStatus(taskId);
} catch (error) {
console.error('Failed to stop task:', error);
toast.error(t('failedToStopTask'));
}
};
const getStatusBadge = (status: number) => {
const statusConfig = {
0: { label: t('notStarted'), variant: 'secondary' as const },
1: { label: t('inProgress'), variant: 'default' as const },
2: { label: t('completed'), variant: 'default' as const },
};
const config = statusConfig[status as keyof typeof statusConfig] || {
label: `${t('status')} ${status}`,
variant: 'secondary' as const,
};
return <Badge variant={config.variant}>{config.label}</Badge>;
};
return (
<Sheet>
<SheetTrigger asChild>
<div className='flex cursor-pointer items-center justify-between transition-colors'>
<div className='flex items-center gap-3'>
<div className='bg-primary/10 flex h-10 w-10 items-center justify-center rounded-lg'>
<Icon icon='mdi:email-multiple' className='text-primary h-5 w-5' />
</div>
<div className='flex-1'>
<p className='font-medium'>{t('emailTaskManager')}</p>
<p className='text-muted-foreground text-sm'>
{t('viewAndManageEmailBroadcastTasks')}
</p>
</div>
</div>
<Icon icon='mdi:chevron-right' className='size-6' />
</div>
</SheetTrigger>
<SheetContent className='w-[1000px] max-w-full md:max-w-screen-lg'>
<SheetHeader>
<SheetTitle>{t('emailBroadcastTasks')}</SheetTitle>
</SheetHeader>
<ScrollArea className='-mx-6 h-[calc(100dvh-48px-36px-env(safe-area-inset-top))] px-6'>
<div className='mt-4 space-y-4'>
<ProTable<API.BatchSendEmailTask, API.GetBatchSendEmailTaskListParams>
columns={[
{
accessorKey: 'subject',
header: t('subject'),
size: 200,
cell: ({ row }) => (
<div
className='max-w-[200px] truncate font-medium'
title={row.getValue('subject') as string}
>
{row.getValue('subject') as string}
</div>
),
},
{
accessorKey: 'scope',
header: t('recipientType'),
size: 120,
cell: ({ row }) => {
const scope = row.getValue('scope') as string;
const scopeLabels = {
all: t('allUsers'),
active: t('subscribedUsers'),
expired: t('expiredUsers'),
none: t('nonSubscribers'),
skip: t('specificUsers'),
};
return scopeLabels[scope as keyof typeof scopeLabels] || scope;
},
},
{
accessorKey: 'status',
header: t('status'),
size: 100,
cell: ({ row }) => getStatusBadge(row.getValue('status') as number),
},
{
accessorKey: 'progress',
header: t('progress'),
size: 150,
cell: ({ row }) => {
const task = row.original as API.BatchSendEmailTask;
const progress = task.total > 0 ? (task.current / task.total) * 100 : 0;
return (
<div className='space-y-1'>
<div className='flex justify-between text-sm'>
<span>
{task.current} / {task.total}
</span>
<span>{progress.toFixed(1)}%</span>
</div>
<div className='bg-muted h-2 overflow-hidden rounded-full'>
<div
className='bg-primary h-full transition-all duration-300'
style={{ width: `${progress}%` }}
/>
</div>
</div>
);
},
},
{
accessorKey: 'created_at',
header: t('createdAt'),
size: 150,
cell: ({ row }) => {
const createdAt = row.getValue('created_at') as number;
return formatDate(createdAt);
},
},
{
accessorKey: 'scheduled',
header: t('sendTime'),
size: 150,
cell: ({ row }) => {
const scheduled = row.getValue('scheduled') as number;
return scheduled && scheduled > 0 ? formatDate(scheduled) : '--';
},
},
]}
request={async (pagination, filters) => {
const response = await getBatchSendEmailTaskList({
...filters,
page: pagination.page,
size: pagination.size,
});
return {
list: response.data?.data?.list || [],
total: response.data?.data?.total || 0,
};
}}
params={[
{
key: 'status',
placeholder: t('status'),
options: [
{ label: t('notStarted'), value: '0' },
{ label: t('inProgress'), value: '1' },
{ label: t('completed'), value: '2' },
],
},
{
key: 'scope',
placeholder: t('sendScope'),
options: [
{ label: t('allUsers'), value: 'all' },
{ label: t('subscribedUsers'), value: 'active' },
{ label: t('expiredUsers'), value: 'expired' },
{ label: t('nonSubscribers'), value: 'none' },
{ label: t('specificUsers'), value: 'skip' },
],
},
]}
actions={{
render: (row) => {
return [
<Dialog key='view-content'>
<DialogTrigger asChild>
<Button
variant='outline'
size='icon'
onClick={() => setSelectedTask(row as API.BatchSendEmailTask)}
>
<Icon icon='mdi:eye' />
</Button>
</DialogTrigger>
<DialogContent className='max-h-[80vh] max-w-4xl'>
<DialogHeader>
<DialogTitle>{t('emailContent')}</DialogTitle>
</DialogHeader>
<ScrollArea className='h-[60vh] pr-4'>
{selectedTask && (
<div className='space-y-4'>
<div>
<h4 className='text-muted-foreground mb-2 text-sm font-medium'>
{t('subject')}
</h4>
<p className='font-medium'>{selectedTask.subject}</p>
</div>
<div>
<h4 className='text-muted-foreground mb-2 text-sm font-medium'>
{t('content')}
</h4>
<div
className='prose prose-sm max-w-none'
dangerouslySetInnerHTML={{ __html: selectedTask.content }}
/>
</div>
{selectedTask.additional && (
<div>
<h4 className='text-muted-foreground mb-2 text-sm font-medium'>
{t('additionalRecipients')}
</h4>
<p className='text-sm'>{selectedTask.additional}</p>
</div>
)}
</div>
)}
</ScrollArea>
</DialogContent>
</Dialog>,
<Button
key='refresh'
variant='outline'
size='icon'
onClick={() => refreshTaskStatus(row.id)}
disabled={refreshing[row.id]}
>
{refreshing[row.id] && (
<Icon icon='mdi:loading' className='mr-2 h-3 w-3 animate-spin' />
)}
<Icon icon='mdi:refresh' className='h-3 w-3' />
</Button>,
...([0, 1].includes(row.status)
? [
<Button key='stop' variant='destructive' onClick={() => stopTask(row.id)}>
{t('stop')}
</Button>,
]
: []),
];
},
}}
/>
</div>
</ScrollArea>
</SheetContent>
</Sheet>
);
}
@@ -0,0 +1,41 @@
'use client';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { useTranslations } from 'next-intl';
import EmailBroadcastForm from './email/broadcast-form';
import EmailTaskManager from './email/task-manager';
export default function MarketingPage() {
const t = useTranslations('marketing');
const formSections = [
{
title: t('emailMarketing'),
forms: [{ component: EmailBroadcastForm }, { component: EmailTaskManager }],
},
];
return (
<div className='space-y-8'>
{formSections.map((section, sectionIndex) => (
<div key={sectionIndex}>
<h2 className='mb-4 text-lg font-semibold'>{section.title}</h2>
<Table>
<TableBody>
{section.forms.map((form, formIndex) => {
const FormComponent = form.component;
return (
<TableRow key={formIndex}>
<TableCell>
<FormComponent />
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
))}
</div>
);
}
@@ -44,7 +44,7 @@ export default function GroupForm<T extends Record<string, any>>({
trigger,
title,
}: GroupFormProps<T>) {
const t = useTranslations('subscribe');
const t = useTranslations('product');
const [open, setOpen] = useState(false);
const form = useForm({
@@ -17,7 +17,7 @@ import { toast } from 'sonner';
import GroupForm from './form';
const GroupTable = () => {
const t = useTranslations('subscribe');
const t = useTranslations('product');
const [loading, setLoading] = useState(false);
const ref = useRef<ProTableActions>(null);
+25
View File
@@ -0,0 +1,25 @@
import { getTranslations } from 'next-intl/server';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import GroupTable from './group/table';
import SubscribeTable from './subscribe-table';
export default async function Page() {
const t = await getTranslations('product');
return (
<Tabs defaultValue='subscribe'>
<TabsList>
<TabsTrigger value='subscribe'>{t('tabs.subscribe')}</TabsTrigger>
<TabsTrigger value='group'>{t('tabs.subscribeGroup')}</TabsTrigger>
</TabsList>
<TabsContent value='subscribe'>
<SubscribeTable />
</TabsContent>
<TabsContent value='group'>
<GroupTable />
</TabsContent>
</Tabs>
);
}
@@ -79,7 +79,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
trigger,
title,
}: Readonly<SubscribeFormProps<T>>) {
const t = useTranslations('subscribe');
const t = useTranslations('product');
const [open, setOpen] = useState(false);
const updateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
@@ -22,7 +22,7 @@ import { toast } from 'sonner';
import SubscribeForm from './subscribe-form';
export default function SubscribeTable() {
const t = useTranslations('subscribe');
const t = useTranslations('product');
const [loading, setLoading] = useState(false);
const { data: groups } = useQuery({
queryKey: ['getSubscribeGroupList', 'all'],
@@ -1,240 +0,0 @@
'use client';
import { createRuleGroup } from '@/services/admin/server';
import { Button } from '@workspace/ui/components/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@workspace/ui/components/dialog';
import { Label } from '@workspace/ui/components/label';
import { Progress } from '@workspace/ui/components/progress';
import { Textarea } from '@workspace/ui/components/textarea';
import { Icon } from '@workspace/ui/custom-components/icon';
import yaml from 'js-yaml';
import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react';
import { toast } from 'sonner';
interface ImportYamlRulesProps {
onImportSuccess?: () => void;
}
interface RuleGroup {
name: string;
rules: string[];
}
export default function ImportYamlRules({ onImportSuccess }: ImportYamlRulesProps) {
const t = useTranslations('rules');
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [yamlContent, setYamlContent] = useState('');
const [importProgress, setImportProgress] = useState(0);
const [importTotal, setImportTotal] = useState(0);
const [analyzing, setAnalyzing] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const content = event.target?.result as string;
setYamlContent(content);
setOpen(true);
};
reader.readAsText(file);
e.target.value = '';
};
const processRule = (rule: string): { policyGroup: string; cleanRule: string } | null => {
const parts = rule.split(',');
if (parts.length === 1) {
return null;
}
let policyGroup = 'default';
let cleanRule = rule;
if (parts.length >= 3) {
const thirdPart = parts[2]?.trim();
if (thirdPart) {
policyGroup = thirdPart;
}
}
cleanRule = parts.slice(0, 2).join(',');
return { policyGroup, cleanRule };
};
const parseRulesIntoGroups = (rules: string[]): Record<string, string[]> => {
const groups: Record<string, string[]> = {};
for (const rule of rules) {
if (!rule.trim()) continue;
const result = processRule(rule);
if (result === null) continue;
const { policyGroup, cleanRule } = result;
if (!groups[policyGroup]) {
groups[policyGroup] = [];
}
// 不插入 MATCH 规则,只用于标识默认规则组
if (!rule.trim().startsWith('MATCH,')) {
groups[policyGroup].push(cleanRule);
}
}
return groups;
};
const checkIfDefaultRule = (originalRules: string[], groupName: string): boolean => {
return originalRules.some((rule) => {
const trimmedRule = rule.trim();
if (!trimmedRule.startsWith('MATCH,')) return false;
// 检查 MATCH 规则是否属于当前组
const parts = trimmedRule.split(',');
if (parts.length >= 3) {
const ruleGroup = parts[2]?.trim();
return ruleGroup === groupName;
}
return groupName === 'default';
});
};
const handleImport = async () => {
if (!yamlContent) {
toast.error(t('pleaseUploadFile'));
return;
}
setLoading(true);
setAnalyzing(true);
try {
const parsedYaml = yaml.load(yamlContent) as any;
if (!parsedYaml || !parsedYaml.rules) {
throw new Error(t('invalidYamlFormat'));
}
let allRules: string[] = [];
if (Array.isArray(parsedYaml.rules)) {
allRules = parsedYaml.rules.filter((rule: string) => rule.trim());
}
if (allRules.length === 0) {
throw new Error(t('noValidRules'));
}
const ruleGroups = parseRulesIntoGroups(allRules);
const groups = Object.entries(ruleGroups).map(([name, rules]) => ({
name,
rules,
}));
setImportTotal(groups.length);
setAnalyzing(false);
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (!group?.name || !group?.rules.length) continue;
const isDefault = checkIfDefaultRule(allRules, group.name);
await createRuleGroup({
name: group.name,
rules: group?.rules.join('\n'),
enable: false,
tags: [],
icon: '',
type: 'default',
default: isDefault,
});
setImportProgress(i + 1);
}
toast.success(t('importSuccess'));
setOpen(false);
setYamlContent('');
setImportProgress(0);
setImportTotal(0);
onImportSuccess?.();
} catch (error) {
console.error('Import error:', error);
toast.error(error instanceof Error ? error.message : t('importFailed'));
} finally {
setLoading(false);
setAnalyzing(false);
}
};
return (
<>
<input
ref={fileInputRef}
type='file'
accept='.yml,.yaml'
style={{ display: 'none' }}
onChange={handleFileUpload}
/>
<Button variant='default' onClick={() => fileInputRef.current?.click()}>
{t('import')}
</Button>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className='sm:max-w-[500px]'>
<DialogHeader>
<DialogTitle>{t('importYamlRules')}</DialogTitle>
<DialogDescription>{t('importYamlDescription')}</DialogDescription>
</DialogHeader>
<div className='grid gap-4 py-4'>
{yamlContent && (
<div className='grid gap-2'>
<Label htmlFor='preview'>{t('preview')}</Label>
<Textarea
id='preview'
value={yamlContent}
readOnly
rows={10}
className='font-mono text-xs'
/>
</div>
)}
{importTotal > 0 && (
<div className='grid gap-2'>
<div className='flex justify-between text-sm'>
<span>{analyzing ? t('analyzing') : t('importing')}</span>
<span>
{importProgress} / {importTotal}
</span>
</div>
<Progress value={(importProgress / importTotal) * 100} />
</div>
)}
</div>
<DialogFooter>
<Button variant='outline' onClick={() => setOpen(false)} disabled={loading}>
{t('cancel')}
</Button>
<Button onClick={handleImport} disabled={loading || !yamlContent}>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
{t('import')}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}
-244
View File
@@ -1,244 +0,0 @@
'use client';
import { ProTable, ProTableActions } from '@/components/pro-table';
import {
createRuleGroup,
deleteRuleGroup,
getRuleGroupList,
updateRuleGroup,
} from '@/services/admin/server';
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 Image from 'next/legacy/image';
import Link from 'next/link';
import { useRef, useState } from 'react';
import { toast } from 'sonner';
import ImportYamlRules from './import-yaml-rules';
import RuleForm from './rule-form';
export default function Page() {
const t = useTranslations('rules');
const [loading, setLoading] = useState(false);
const ref = useRef<ProTableActions>(null);
return (
<ProTable<API.ServerRuleGroup, { query: string }>
action={ref}
header={{
toolbar: (
<div className='flex gap-2'>
<Button variant='default' asChild>
<Link href='/template/rules.yml' target='_blank' download>
{t('downloadTemplate')}
</Link>
</Button>
<ImportYamlRules onImportSuccess={() => ref.current?.refresh()} />
<RuleForm<API.CreateRuleGroupRequest>
trigger={t('create')}
title={t('createRule')}
loading={loading}
onSubmit={async (values) => {
setLoading(true);
try {
await createRuleGroup({
name: values.name,
rules: values.rules || '',
enable: false,
tags: values.tags || [],
icon: values.icon || '',
type: values.type || 'default',
default: false,
});
toast.success(t('createSuccess'));
ref.current?.refresh();
setLoading(false);
return true;
} catch (error) {
setLoading(false);
return false;
}
}}
/>
</div>
),
}}
params={[
{
key: 'search',
placeholder: t('searchRule'),
},
]}
request={async (pagination, filters) => {
const { data } = await getRuleGroupList({
...pagination,
...filters,
});
return {
list: data.data?.list || [],
total: data.data?.total || 0,
};
}}
columns={[
{
accessorKey: 'enable',
header: t('enable'),
cell: ({ row }) => {
return (
<Switch
defaultChecked={row.getValue('enable')}
onCheckedChange={async (checked) => {
await updateRuleGroup({
...row.original,
enable: checked,
} as API.UpdateRuleGroupRequest);
ref.current?.refresh();
}}
/>
);
},
},
{
accessorKey: 'default',
header: t('defaultRule'),
cell: ({ row }) => (
<Switch
defaultChecked={row.original.default}
onCheckedChange={async (checked) => {
await updateRuleGroup({
...row.original,
default: checked,
} as API.UpdateRuleGroupRequest);
ref.current?.refresh();
}}
/>
),
},
{
accessorKey: 'type',
header: t('type'),
cell: ({ row }) => {
const type = row.original.type || 'default';
if (type === 'default') {
return <Badge variant='default'>{t('default')}</Badge>;
}
if (type === 'reject') {
return <Badge variant='destructive'>{t('reject')}</Badge>;
}
if (type === 'direct') {
return <Badge variant='secondary'>{t('direct')}</Badge>;
}
return <Badge variant='default'>{t('default')}</Badge>;
},
},
{
accessorKey: 'name',
header: t('name'),
cell: ({ row }) => (
<div className='flex items-center gap-2'>
{row.original.icon && (
<Image
src={row.original.icon}
alt={row.original.name}
className='h-6 w-6 rounded-md'
width={24}
height={24}
/>
)}
<span>{row.original.name}</span>
</div>
),
},
{
accessorKey: 'tags',
header: t('tags'),
cell: ({ row }) => {
const tags = row.original.tags.filter((item) => item) || [];
if (!tags.length) return '--';
return (
<>
{tags.map((tag) => (
<Badge key={tag} variant='outline' className='mr-1'>
{tag}
</Badge>
))}
</>
);
},
},
{
accessorKey: 'created_at',
header: t('createdAt'),
cell: ({ row }) => formatDate(row.original.created_at),
},
]}
actions={{
render: (row) => [
<RuleForm<API.UpdateRuleGroupRequest>
key='edit'
trigger={t('edit')}
title={t('editRule')}
loading={loading}
initialValues={row}
onSubmit={async (values) => {
setLoading(true);
try {
await updateRuleGroup({
id: row.id,
name: values.name,
tags: values.tags,
rules: values.rules,
enable: row.enable,
icon: values.icon,
type: values.type,
default: row.default,
});
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 deleteRuleGroup({ id: row.id });
toast.success(t('deleteSuccess'));
ref.current?.refresh();
}}
cancelText={t('cancel')}
confirmText={t('confirm')}
/>,
],
batchRender: (rows) => [
<ConfirmButton
key='delete'
trigger={<Button variant='destructive'>{t('delete')}</Button>}
title={t('confirmDelete')}
description={t('deleteWarning')}
onConfirm={async () => {
for (const row of rows) {
await deleteRuleGroup({ id: row.id });
}
toast.success(t('deleteSuccess'));
ref.current?.reset();
ref.current?.refresh();
}}
cancelText={t('cancel')}
confirmText={t('confirm')}
/>,
],
}}
/>
);
}
@@ -1,266 +0,0 @@
'use client';
import { getNodeTagList } from '@/services/admin/server';
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 { 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 { Textarea } from '@workspace/ui/components/textarea';
import { Combobox } from '@workspace/ui/custom-components/combobox';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { Icon } from '@workspace/ui/custom-components/icon';
import { UploadImage } from '@workspace/ui/custom-components/upload-image';
import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({
name: z.string().min(1, { message: '请输入规则名称' }),
tags: z.array(z.string()).default([]),
rules: z.string().default(''),
icon: z.string().default(''),
type: z.string().default('default'),
});
interface RuleFormProps<T> {
onSubmit: (data: T) => Promise<boolean> | boolean;
initialValues?: T;
loading?: boolean;
trigger: string;
title: string;
}
export default function RuleForm<T extends Record<string, any>>({
onSubmit,
initialValues,
loading,
trigger,
title,
}: RuleFormProps<T>) {
const t = useTranslations('rules');
const [open, setOpen] = useState(false);
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
...initialValues,
} as any,
});
useEffect(() => {
if (initialValues) {
form.reset(initialValues);
}
}, [form, initialValues]);
async function handleSubmit(data: { [x: string]: any }) {
const bool = await onSubmit(data as T);
if (bool) setOpen(false);
}
const { data: tags } = useQuery({
queryKey: ['getNodeTagList'],
queryFn: async () => {
const { data } = await getNodeTagList();
return data.data?.tags || [];
},
});
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='icon'
render={({ field }) => (
<FormItem>
<FormLabel>{t('appIcon')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('enterIconUrl')}
value={field.value}
suffix={
<UploadImage
className='bg-muted h-9 rounded-none border-none px-2'
onChange={(value) => {
form.setValue(field.name, value as string);
}}
/>
}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='name'
render={({ field }) => (
<FormItem>
<FormLabel>{t('name')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('enterRuleName')}
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='type'
render={({ field }) => (
<FormItem>
<FormLabel>{t('type')}</FormLabel>
<FormControl>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<SelectTrigger>
<SelectValue placeholder={t('selectType')} />
</SelectTrigger>
<SelectContent>
<SelectItem value='default'>{t('default')}</SelectItem>
<SelectItem value='reject'>{t('reject')}</SelectItem>
<SelectItem value='direct'>{t('direct')}</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='tags'
render={({ field }) => (
<FormItem>
<FormLabel>{t('tagsLabel')}</FormLabel>
<FormControl>
<Combobox<string, true>
multiple
placeholder={t('selectTags')}
value={field.value}
onChange={(value) => {
form.setValue(field.name, value);
}}
options={tags?.map((item: string) => ({
value: item,
label: item,
}))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='rules'
render={({ field }) => (
<FormItem>
<FormLabel>{t('rulesLabel')}</FormLabel>
<FormControl>
<Textarea
placeholder={t('enterRules')}
value={field.value}
rows={10}
onChange={(e) => {
form.setValue(field.name, e.target.value);
}}
/>
</FormControl>
<div className='text-muted-foreground mt-1 text-xs'>
<pre>{t('rulesFormat')}</pre>
<div className='border-muted mt-2 space-y-1 border-l-2 pl-2'>
<p className='font-mono'>DOMAIN,example.com</p>
<p className='font-mono'>DOMAIN-SUFFIX,google.com,DIRECT</p>
<p className='font-mono'>DOMAIN-KEYWORD,amazon,REJECT</p>
<p className='font-mono'>IP-CIDR,192.168.0.0/16</p>
<p className='font-mono'>IP-CIDR6,2001:db8::/32,REJECT</p>
<p className='font-mono'>SRC-IP-CIDR,192.168.1.201/32</p>
<p className='font-mono'>GEOIP,CN,DIRECT</p>
<p className='font-mono'>GEOIP,US</p>
<p className='font-mono'>DST-PORT,80,DIRECT</p>
<p className='font-mono'>SRC-PORT,7777,REJECT</p>
<p className='font-mono'>PROCESS-NAME,telegram</p>
</div>
</div>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</ScrollArea>
<SheetFooter className='flex-row justify-end gap-2 pt-3'>
<Button
variant='outline'
disabled={loading}
onClick={() => {
setOpen(false);
}}
>
{t('cancel')}
</Button>
<Button disabled={loading} onClick={form.handleSubmit(handleSubmit)}>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
{t('confirm')}
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
@@ -0,0 +1,258 @@
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useQuery } from '@tanstack/react-query';
import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { z } from 'zod';
import { getSubscribeConfig, updateSubscribeConfig } from '@/services/admin/system';
import { Button } from '@workspace/ui/components/button';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import {
Sheet,
SheetContent,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@workspace/ui/components/sheet';
import { Switch } from '@workspace/ui/components/switch';
import { Textarea } from '@workspace/ui/components/textarea';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { Icon } from '@workspace/ui/custom-components/icon';
const subscribeConfigSchema = z.object({
single_model: z.boolean().optional(),
pan_domain: z.boolean().optional(),
subscribe_path: z.string().optional(),
subscribe_domain: z.string().optional(),
user_agent_limit: z.boolean().optional(),
user_agent_list: z.string().optional(),
});
type SubscribeConfigFormData = z.infer<typeof subscribeConfigSchema>;
export default function ConfigForm() {
const t = useTranslations('subscribe');
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const { data, refetch } = useQuery({
queryKey: ['getSubscribeConfig'],
queryFn: async () => {
const { data } = await getSubscribeConfig();
return data.data;
},
enabled: open,
});
const form = useForm<SubscribeConfigFormData>({
resolver: zodResolver(subscribeConfigSchema),
defaultValues: {
single_model: false,
pan_domain: false,
subscribe_path: '',
subscribe_domain: '',
user_agent_limit: false,
user_agent_list: '',
},
});
useEffect(() => {
if (data) {
form.reset(data);
}
}, [data, form]);
async function onSubmit(values: SubscribeConfigFormData) {
setLoading(true);
try {
await updateSubscribeConfig(values as API.SubscribeConfig);
toast.success(t('config.updateSuccess'));
refetch();
setOpen(false);
} catch (error) {
toast.error(t('config.updateError'));
} finally {
setLoading(false);
}
}
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<div className='flex cursor-pointer items-center justify-between transition-colors'>
<div className='flex items-center gap-3'>
<div className='bg-primary/10 flex h-10 w-10 items-center justify-center rounded-lg'>
<Icon icon='mdi:cog' className='text-primary h-5 w-5' />
</div>
<div className='flex-1'>
<p className='font-medium'>{t('config.title')}</p>
<p className='text-muted-foreground text-sm'>{t('config.description')}</p>
</div>
</div>
<Icon icon='mdi:chevron-right' className='size-6' />
</div>
</SheetTrigger>
<SheetContent className='w-[600px] max-w-full md:max-w-screen-md'>
<SheetHeader>
<SheetTitle>{t('config.title')}</SheetTitle>
</SheetHeader>
<ScrollArea className='-mx-6 h-[calc(100dvh-48px-36px-36px-env(safe-area-inset-top))] px-6'>
<Form {...form}>
<form
id='subscribe-config-form'
onSubmit={form.handleSubmit(onSubmit)}
className='space-y-2 pt-4'
>
<FormField
control={form.control}
name='single_model'
render={({ field }) => (
<FormItem>
<FormLabel>{t('config.singleSubscriptionMode')}</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
className='float-end !mt-0'
/>
</FormControl>
<FormDescription>
{t('config.singleSubscriptionModeDescription')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='pan_domain'
render={({ field }) => (
<FormItem>
<FormLabel>{t('config.wildcardResolution')}</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
className='float-end !mt-0'
/>
</FormControl>
<FormDescription>{t('config.wildcardResolutionDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='subscribe_path'
render={({ field }) => (
<FormItem>
<FormLabel>{t('config.subscriptionPath')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('config.subscriptionPathPlaceholder')}
value={field.value}
onValueBlur={field.onChange}
/>
</FormControl>
<FormDescription>{t('config.subscriptionPathDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='subscribe_domain'
render={({ field }) => (
<FormItem>
<FormLabel>{t('config.subscriptionDomain')}</FormLabel>
<FormControl>
<Textarea
className='h-32'
placeholder={`${t('config.subscriptionDomainPlaceholder')}\nexample.com\nwww.example.com`}
{...field}
/>
</FormControl>
<FormDescription>{t('config.subscriptionDomainDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='user_agent_limit'
render={({ field }) => (
<FormItem>
<FormLabel>{t('config.userAgentLimit', { userAgent: 'User-Agent' })}</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
className='float-end !mt-0'
/>
</FormControl>
<FormDescription>
{t('config.userAgentLimitDescription', { userAgent: 'User-Agent' })}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='user_agent_list'
render={({ field }) => (
<FormItem>
<FormLabel>
{t('config.userAgentList', {
userAgent: 'User-Agent',
})}
</FormLabel>
<FormControl>
<Textarea
className='h-32'
placeholder={`${t('config.userAgentListPlaceholder', { userAgent: 'User-Agent' })}\nClashX\nClashForAndroid\nClash-verge`}
{...field}
/>
</FormControl>
<FormDescription>
{t('config.userAgentListDescription', { userAgent: 'User-Agent' })}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</ScrollArea>
<SheetFooter className='flex-row justify-end gap-2 pt-3'>
<Button variant='outline' disabled={loading} onClick={() => setOpen(false)}>
{t('actions.cancel')}
</Button>
<Button disabled={loading} type='submit' form='subscribe-config-form'>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
{t('actions.save')}
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
+17 -24
View File
@@ -1,30 +1,23 @@
import { getTranslations } from 'next-intl/server';
'use client';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Card, CardContent } from '@workspace/ui/components/card';
import { useTranslations } from 'next-intl';
import ConfigForm from './config-form';
import { ProtocolForm } from './protocol-form';
import GroupTable from './group/table';
import SubscribeConfig from './subscribe-config';
import SubscribeTable from './subscribe-table';
export default async function Page() {
const t = await getTranslations('subscribe');
export default function SubscribePage() {
const t = useTranslations('subscribe');
return (
<Tabs defaultValue='subscribe'>
<TabsList>
<TabsTrigger value='subscribe'>{t('tabs.subscribe')}</TabsTrigger>
<TabsTrigger value='group'>{t('tabs.subscribeGroup')}</TabsTrigger>
<TabsTrigger value='config'>{t('tabs.subscribeConfig')}</TabsTrigger>
</TabsList>
<TabsContent value='subscribe'>
<SubscribeTable />
</TabsContent>
<TabsContent value='group'>
<GroupTable />
</TabsContent>
<TabsContent value='config'>
<SubscribeConfig />
</TabsContent>
</Tabs>
<div className='space-y-4'>
<h2 className='text-lg font-semibold'>{t('config.title')}</h2>
<Card>
<CardContent className='p-4'>
<ConfigForm />
</CardContent>
</Card>
<ProtocolForm />
</div>
);
}
@@ -0,0 +1,841 @@
'use client';
import { ProTable, ProTableActions } from '@/components/pro-table';
import {
createSubscribeApplication,
deleteSubscribeApplication,
getSubscribeApplicationList,
updateSubscribeApplication,
} from '@/services/admin/application';
import { zodResolver } from '@hookform/resolvers/zod';
import { ColumnDef } from '@tanstack/react-table';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { Input } from '@workspace/ui/components/input';
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,
} from '@workspace/ui/components/sheet';
import { Switch } from '@workspace/ui/components/switch';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Textarea } from '@workspace/ui/components/textarea';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@workspace/ui/components/tooltip';
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { GoTemplateEditor } from '@workspace/ui/custom-components/editor';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { Icon } from '@workspace/ui/custom-components/icon';
import { UploadImage } from '@workspace/ui/custom-components/upload-image';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
import { useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { z } from 'zod';
import { TemplatePreview } from './template-preview';
const createClientFormSchema = (t: any) =>
z.object({
name: z.string().min(1, t('form.validation.nameRequired')),
description: z.string().optional(),
icon: z.string().optional(),
user_agent: z.string().min(1, `User-Agent ${t('form.validation.userAgentRequiredSuffix')}`),
scheme: z.string().default(''),
template: z.string().default(''),
output_format: z.string().default(''),
download_link: z.object({
windows: z.string().optional(),
mac: z.string().optional(),
linux: z.string().optional(),
ios: z.string().optional(),
android: z.string().optional(),
harmony: z.string().optional(),
}),
});
type ClientFormData = z.infer<ReturnType<typeof createClientFormSchema>>;
export function ProtocolForm() {
const t = useTranslations('subscribe');
const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false);
const [previewOpen, setPreviewOpen] = useState(false);
const [previewApplicationId, setPreviewApplicationId] = useState<number | null>(null);
const [editingClient, setEditingClient] = useState<API.SubscribeApplication | null>(null);
const tableRef = useRef<ProTableActions>(null);
const clientFormSchema = createClientFormSchema(t);
const form = useForm<ClientFormData>({
resolver: zodResolver(clientFormSchema),
defaultValues: {
name: '',
description: '',
icon: '',
user_agent: '',
scheme: '',
template: '',
output_format: '',
download_link: {
windows: '',
mac: '',
linux: '',
ios: '',
android: '',
harmony: '',
},
},
});
// API请求函数
const request = async (
pagination: { page: number; size: number },
filter: Record<string, unknown>,
) => {
const { data } = await getSubscribeApplicationList({
page: pagination.page,
size: pagination.size,
});
return {
list: data.data?.list || [],
total: data.data?.total || 0,
};
};
// 表格列定义
const columns: ColumnDef<API.SubscribeApplication, any>[] = [
{
accessorKey: 'is_default',
header: t('table.columns.default'),
cell: ({ row }) => (
<Switch
checked={row.original.is_default || false}
onCheckedChange={async (checked) => {
await updateSubscribeApplication({
...row.original,
proxy_template: '',
is_default: checked,
});
tableRef.current?.refresh();
}}
/>
),
},
{
accessorKey: 'name',
header: t('table.columns.name'),
cell: ({ row }) => (
<div className='flex items-center gap-2'>
{row.original.icon && (
<div className='relative h-6 w-6 flex-shrink-0'>
<Image
src={row.original.icon}
alt={row.original.name}
width={24}
height={24}
className='rounded object-contain'
onError={() => {
console.log(`Failed to load image for ${row.original.name}`);
}}
/>
</div>
)}
<span className='font-medium'>{row.original.name}</span>
</div>
),
},
{
accessorKey: 'user_agent',
header: 'User-Agent',
cell: ({ row }) => (
<div className='text-muted-foreground max-w-[150px] truncate font-mono text-sm'>
{row.original.user_agent}
</div>
),
},
{
accessorKey: 'output_format',
header: t('table.columns.outputFormat'),
cell: ({ row }) => (
<Badge variant='secondary' className='text-xs'>
{t(`outputFormats.${row.original.output_format}`) || row.original.output_format}
</Badge>
),
},
{
accessorKey: 'download_link',
header: t('table.columns.supportedPlatforms'),
cell: ({ row }) => {
return (
<div className='flex flex-wrap gap-1'>
{Object.entries(row.original.download_link || {}).map(([key, value]) => {
if (value) {
return (
<Badge key={key} variant='secondary' className='text-xs'>
{t(`platforms.${key}`)}
</Badge>
);
}
return null;
})}
</div>
);
},
},
{
accessorKey: 'description',
header: t('table.columns.description'),
cell: ({ row }) => (
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<div className='text-muted-foreground max-w-[200px] truncate text-sm'>
{row.original.description}
</div>
</TooltipTrigger>
<TooltipContent className='max-w-xs'>
<p>{row.original.description}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
),
},
];
const handleAdd = () => {
setEditingClient(null);
form.reset({
name: '',
description: '',
icon: '',
user_agent: '',
scheme: '',
template: '',
output_format: '',
download_link: {
windows: '',
mac: '',
linux: '',
ios: '',
android: '',
harmony: '',
},
});
setOpen(true);
};
const handleEdit = (client: API.SubscribeApplication) => {
setEditingClient(client);
form.reset(client);
setOpen(true);
};
const handleDelete = async (client: API.SubscribeApplication) => {
setLoading(true);
try {
await deleteSubscribeApplication({ id: client.id });
tableRef.current?.refresh();
toast.success(t('actions.deleteSuccess'));
} catch (error) {
console.error('Failed to delete client:', error);
toast.error(t('actions.deleteFailed'));
} finally {
setLoading(false);
}
};
const handleBatchDelete = async (clients: API.SubscribeApplication[]) => {
setLoading(true);
try {
await Promise.all(clients.map((client) => deleteSubscribeApplication({ id: client.id })));
tableRef.current?.refresh();
toast.success(t('actions.batchDeleteSuccess', { count: clients.length }));
} catch (error) {
console.error('Failed to batch delete clients:', error);
toast.error(t('actions.deleteFailed'));
} finally {
setLoading(false);
}
};
const onSubmit = async (data: ClientFormData) => {
setLoading(true);
try {
if (editingClient) {
await updateSubscribeApplication({
...data,
proxy_template: '',
is_default: editingClient.is_default,
id: editingClient.id,
});
toast.success(t('actions.updateSuccess'));
} else {
await createSubscribeApplication({
...data,
is_default: false,
});
toast.success(t('actions.createSuccess'));
}
setOpen(false);
tableRef.current?.refresh();
} catch (error) {
console.error('Failed to save client:', error);
toast.error(t('actions.saveFailed'));
} finally {
setLoading(false);
}
};
return (
<>
<ProTable<API.SubscribeApplication, Record<string, unknown>>
action={tableRef}
columns={columns}
request={request}
header={{
title: <h2 className='text-lg font-semibold'>{t('protocol.title')}</h2>,
toolbar: <Button onClick={handleAdd}>{t('actions.add')}</Button>,
}}
actions={{
render: (row) => [
<TemplatePreview
key='preview'
applicationId={row.id}
output_format={row.output_format}
/>,
<Button
key='edit'
onClick={() => handleEdit(row as unknown as API.SubscribeApplication)}
>
{t('actions.edit')}
</Button>,
<ConfirmButton
key='delete'
trigger={
<Button variant='destructive' disabled={loading}>
{t('actions.delete')}
</Button>
}
title={t('actions.confirmDelete')}
description={t('actions.deleteWarning')}
onConfirm={() => handleDelete(row as unknown as API.SubscribeApplication)}
cancelText={t('actions.cancel')}
confirmText={t('actions.confirm')}
/>,
],
batchRender: (rows) => [
<ConfirmButton
key='batchDelete'
trigger={<Button variant='destructive'>{t('actions.batchDelete')}</Button>}
title={t('actions.confirmDelete')}
description={t('actions.batchDeleteWarning', { count: rows.length })}
onConfirm={() => handleBatchDelete(rows as unknown as API.SubscribeApplication[])}
cancelText={t('actions.cancel')}
confirmText={t('actions.confirm')}
/>,
],
}}
/>
<Sheet open={open} onOpenChange={setOpen}>
<SheetContent className='w-[580px] max-w-full md:max-w-screen-md'>
<SheetHeader>
<SheetTitle>{editingClient ? t('form.editTitle') : t('form.addTitle')}</SheetTitle>
</SheetHeader>
<ScrollArea className='h-[calc(100dvh-48px-36px-36px)]'>
<Form {...form}>
<form className='space-y-6 py-4'>
<Tabs defaultValue='basic' className='w-full'>
<TabsList className='grid w-full grid-cols-3'>
<TabsTrigger value='basic'>{t('form.tabs.basic')}</TabsTrigger>
<TabsTrigger value='template'>{t('form.tabs.template')}</TabsTrigger>
<TabsTrigger value='download'>{t('form.tabs.download')}</TabsTrigger>
</TabsList>
<TabsContent value='basic' className='space-y-4'>
<FormField
control={form.control}
name='icon'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.fields.icon')}</FormLabel>
<FormControl>
<EnhancedInput
type='text'
placeholder='https://example.com/icon.png'
suffix={
<UploadImage
className='bg-muted h-9 rounded-none border-none px-2'
onChange={(value) => {
form.setValue(field.name, value as string);
}}
/>
}
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value as string);
}}
/>
</FormControl>
<FormDescription>{t('form.descriptions.icon')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='name'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.fields.name')}</FormLabel>
<FormControl>
<Input placeholder='Clash for Windows' {...field} />
</FormControl>
<FormDescription>{t('form.descriptions.name')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='user_agent'
render={({ field }) => (
<FormItem>
<FormLabel>User-Agent</FormLabel>
<FormControl>
<Input placeholder='Clash' {...field} />
</FormControl>
<FormDescription>
{t('form.descriptions.userAgentPrefix')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='description'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.fields.description')}</FormLabel>
<FormControl>
<Textarea placeholder={t('form.descriptions.description')} {...field} />
</FormControl>
<FormDescription>{t('form.descriptions.description')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</TabsContent>
<TabsContent value='template' className='space-y-4'>
<FormField
control={form.control}
name='output_format'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.fields.outputFormat')}</FormLabel>
<FormControl>
<Select value={field.value} onValueChange={field.onChange}>
<SelectTrigger>
<SelectValue placeholder='Select ...' />
</SelectTrigger>
<SelectContent>
<SelectItem value='base64'>{t('outputFormats.base64')}</SelectItem>
<SelectItem value='yaml'>{t('outputFormats.yaml')}</SelectItem>
<SelectItem value='json'>{t('outputFormats.json')}</SelectItem>
<SelectItem value='conf'>{t('outputFormats.conf')}</SelectItem>
<SelectItem value='plain'>{t('outputFormats.plain')}</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormDescription>{t('form.descriptions.outputFormat')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='scheme'
render={({ field }) => (
<FormItem>
<FormLabel className='flex items-center gap-2'>
{t('form.fields.scheme')}
<TooltipProvider>
<Tooltip>
<TooltipTrigger
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<Icon
icon='mdi:help-circle-outline'
className='text-muted-foreground h-4 w-4'
/>
</TooltipTrigger>
<TooltipContent
side='right'
className='bg-secondary text-secondary-foreground max-w-md'
>
<div className='space-y-2 text-sm'>
<div className='font-medium'>
{t('form.descriptions.scheme.title')}
</div>
<div>
<div className='font-medium'>
{t('form.descriptions.scheme.variables')}
</div>
<ul className='ml-2 list-disc space-y-1 text-xs'>
<li>
<code className='rounded px-1'>{'${url}'}</code> -{' '}
{t('form.descriptions.scheme.urlVariable')}
</li>
<li>
<code className='rounded px-1'>{'${name}'}</code> -{' '}
{t('form.descriptions.scheme.nameVariable')}
</li>
</ul>
</div>
<div>
<div className='font-medium'>
{t('form.descriptions.scheme.functions')}
</div>
<ul className='ml-2 list-disc space-y-1 text-xs'>
<li>
<code className='rounded px-1'>
{'${encodeURIComponent(...)}'}
</code>{' '}
- {t('form.descriptions.scheme.urlEncoding')}
</li>
<li>
<code className='rounded px-1'>
{'${window.btoa(...)}'}
</code>{' '}
- {t('form.descriptions.scheme.base64Encoding')}
</li>
<li>
<code className='rounded px-1'>
{'${JSON.stringify(...)}'}
</code>{' '}
- {t('form.descriptions.scheme.jsonStringify')}
</li>
</ul>
</div>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</FormLabel>
<FormControl>
<Input
placeholder='clash://install-config?url=${url}&name=${name}'
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='template'
render={({ field }) => (
<FormItem>
<FormLabel className='flex items-center gap-2'>
{t('form.fields.template')}
<TooltipProvider>
<Tooltip>
<TooltipTrigger
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<Icon
icon='mdi:help-circle-outline'
className='text-muted-foreground h-4 w-4'
/>
</TooltipTrigger>
<TooltipContent
side='right'
className='bg-secondary text-secondary-foreground max-w-md'
>
<div className='space-y-2 text-sm'>
<div className='font-medium'>
{t('form.descriptions.template.title')}
</div>
<div>
<div className='font-medium'>
{t('form.descriptions.template.variables')}
</div>
<ul className='ml-2 list-disc space-y-1 text-xs'>
<li>
<code className='rounded px-1'>.SiteName</code> -{' '}
{t('form.descriptions.template.siteName')}
</li>
<li>
<code className='rounded px-1'>.SubscribeName</code> -{' '}
{t('form.descriptions.template.subscribeName')}
</li>
<li>
<code className='rounded px-1'>.Proxies</code> -{' '}
{t('form.descriptions.template.nodes')}
</li>
<li>
<code className='rounded px-1'>.UserInfo</code> -{' '}
{t('form.descriptions.template.userInfo')}
</li>
</ul>
</div>
<div>
<div className='font-medium'>
{t('form.descriptions.template.functions')}
</div>
<ul className='ml-2 list-disc space-y-1 text-xs'>
<li>
<code className='rounded px-1'>
{'{{range .Proxies}}...{{end}}'}
</code>{' '}
- {t('form.descriptions.template.range')}
</li>
<li>
<code className='rounded px-1'>
{'{{if .condition}}...{{end}}'}
</code>{' '}
- {t('form.descriptions.template.if')}
</li>
<li>
<code className='rounded px-1'>{'{{sprig_func}}'}</code> -{' '}
{t('form.descriptions.template.sprig')}
</li>
</ul>
</div>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</FormLabel>
<FormControl>
<GoTemplateEditor
showLineNumbers
schema={{
SiteName: { type: 'string', description: 'Site name' },
SubscribeName: { type: 'string', description: 'Subscribe name' },
Proxies: {
type: 'array',
description: 'Array of proxy nodes',
items: {
type: 'object',
properties: {
Name: { type: 'string', description: 'Node name' },
Server: { type: 'string', description: 'Server host' },
Port: { type: 'number', description: 'Server port' },
Type: { type: 'string', description: 'Proxy type' },
Tags: {
type: 'array',
description: 'Node tags',
items: { type: 'string' },
},
// Security Options
Security: {
type: 'string',
description: 'Security protocol',
},
SNI: {
type: 'string',
description: 'Server Name Indication for TLS',
},
AllowInsecure: {
type: 'boolean',
description:
'Allow insecure connections (skip certificate verification)',
},
Fingerprint: {
type: 'string',
description: 'Client fingerprint for TLS connections',
},
RealityServerAddr: {
type: 'string',
description: 'Reality server address',
},
RealityServerPort: {
type: 'number',
description: 'Reality server port',
},
RealityPrivateKey: {
type: 'string',
description: 'Reality private key for authentication',
},
RealityPublicKey: {
type: 'string',
description: 'Reality public key for authentication',
},
RealityShortId: {
type: 'string',
description: 'Reality short ID for authentication',
},
// Transport Options
Transport: {
type: 'string',
description: 'Transport protocol (e.g., ws, http, grpc)',
},
Host: {
type: 'string',
description: 'For WebSocket/HTTP/HTTPS',
},
Path: { type: 'string', description: 'For HTTP/HTTPS' },
ServiceName: {
type: 'string',
description: 'For gRPC',
},
// Shadowsocks Options
Method: { type: 'string', description: 'Encryption method' },
ServerKey: {
type: 'string',
description: 'For Shadowsocks 2022',
},
// Vmess/Vless/Trojan Options
Flow: {
type: 'string',
description: 'Flow for Vmess/Vless/Trojan',
},
// Hysteria2 Options
HopPorts: {
type: 'string',
description: 'Comma-separated list of hop ports',
},
HopInterval: {
type: 'number',
description: 'Interval for hop ports in seconds',
},
ObfsPassword: {
type: 'string',
description: 'Obfuscation password for Hysteria2',
},
// Tuic Options
DisableSNI: {
type: 'boolean',
description: 'Disable SNI',
},
ReduceRtt: {
type: 'boolean',
description: 'Reduce RTT',
},
UDPRelayMode: {
type: 'string',
description: 'UDP relay mode (e.g., "full", "partial")',
},
CongestionController: {
type: 'string',
description: 'Congestion controller (e.g., "cubic", "bbr")',
},
},
},
},
UserInfo: {
type: 'object',
description: 'User information',
properties: {
Password: { type: 'string', description: 'User password' },
ExpiredAt: { type: 'string', description: 'Expiration date' },
Download: { type: 'number', description: 'Downloaded bytes' },
Upload: { type: 'number', description: 'Uploaded bytes' },
Traffic: { type: 'number', description: 'Total traffic bytes' },
SubscribeURL: {
type: 'string',
description: 'Subscription URL',
},
},
},
}}
enableSprig
value={field.value || ''}
onChange={(value) => field.onChange(value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TabsContent>
<TabsContent value='download' className='space-y-4'>
<div className='space-y-4'>
<div className='grid gap-3'>
{['windows', 'mac', 'linux', 'ios', 'android', 'harmony'].map((key) => (
<FormField
key={key}
control={form.control}
name={
`download_link.${key}` as `download_link.${keyof ClientFormData['download_link']}`
}
render={({ field }) => (
<FormItem>
<FormLabel>{t(`platforms.${key}`)}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
{t(`platforms.${key}`)} {t('form.descriptions.downloadLink')}
</FormDescription>
</FormItem>
)}
/>
))}
</div>
</div>
</TabsContent>
</Tabs>
</form>
</Form>
</ScrollArea>
<SheetFooter className='flex-row justify-end gap-2 pt-3'>
<Button variant='outline' onClick={() => setOpen(false)}>
{t('actions.cancel')}
</Button>
<Button onClick={form.handleSubmit(onSubmit)} disabled={loading}>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
{editingClient ? t('actions.update') : t('actions.add')}
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
</>
);
}
@@ -1,106 +0,0 @@
'use client';
import { useQuery } from '@tanstack/react-query';
import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
import { getSubscribeConfig, updateSubscribeConfig } from '@/services/admin/system';
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 { Textarea } from '@workspace/ui/components/textarea';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
export default function SubscribeConfig() {
const t = useTranslations('subscribe.config');
const { data, refetch } = useQuery({
queryKey: ['getSubscribeConfig'],
queryFn: async () => {
const { data } = await getSubscribeConfig();
return data.data;
},
});
async function updateConfig(key: string, value: unknown) {
if (data?.[key] === value) return;
try {
await updateSubscribeConfig({
...data,
[key]: value,
} as API.SubscribeConfig);
toast.success(t('updateSuccess'));
refetch();
} catch (error) {
/* empty */
}
}
return (
<Table>
<TableBody>
<TableRow>
<TableCell>
<Label>{t('singleSubscriptionMode')}</Label>
<p className='text-muted-foreground text-xs'>
{t('singleSubscriptionModeDescription')}
</p>
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.single_model}
onCheckedChange={(checked) => {
updateConfig('single_model', checked);
}}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('wildcardResolution')}</Label>
<p className='text-muted-foreground text-xs'>{t('wildcardResolutionDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.pan_domain}
onCheckedChange={(checked) => {
updateConfig('pan_domain', checked);
}}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('subscriptionPath')}</Label>
<p className='text-muted-foreground text-xs'>{t('subscriptionPathDescription')}</p>
</TableCell>
<TableCell className='flex items-center gap-2 text-right'>
<EnhancedInput
placeholder={t('subscriptionPathPlaceholder')}
value={data?.subscribe_path}
onValueBlur={(value) => updateConfig('subscribe_path', value)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell className='align-top'>
<Label>{t('subscriptionDomain')}</Label>
<p className='text-muted-foreground text-xs'>{t('subscriptionDomainDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<Textarea
className='h-52'
placeholder={`${t('subscriptionDomainPlaceholder')}\nexample.com\nwww.example.com`}
defaultValue={data?.subscribe_domain}
onBlur={(e) => {
updateConfig('subscribe_domain', e.target.value);
}}
/>
</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
@@ -0,0 +1,89 @@
'use client';
import { previewSubscribeTemplate } from '@/services/admin/application';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@workspace/ui/components/sheet';
import { Icon } from '@workspace/ui/custom-components/icon';
import { Markdown } from '@workspace/ui/custom-components/markdown';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
interface TemplatePreviewProps {
applicationId: number;
output_format?: string;
}
export function TemplatePreview({ applicationId, output_format }: TemplatePreviewProps) {
const t = useTranslations('subscribe.templatePreview');
const [isOpen, setIsOpen] = useState(false);
const { data, isLoading, error } = useQuery({
queryKey: ['previewSubscribeTemplate', applicationId],
queryFn: () => previewSubscribeTemplate({ id: applicationId }, { skipErrorHandler: true }),
enabled: isOpen && !!applicationId,
retry: false,
});
const originalContent = data?.data?.data?.template || '';
const errorMessage = (error as any)?.data?.msg || error?.message || t('failed');
const displayContent = originalContent || (error ? errorMessage : '');
const getDecodedContent = () => {
if (output_format === 'base64' && originalContent) {
try {
return atob(originalContent);
} catch {
return t('base64.decodeError');
}
}
return '';
};
const getDisplayContent = () => {
switch (output_format) {
case 'base64':
return `\`\`\`base64\n# ${t('base64.originalContent')}\n${displayContent}\n\n# ${t('base64.decodedContent')}\n${getDecodedContent()}\n\`\`\``;
case 'yaml':
return `\`\`\`yaml\n${displayContent}\n\`\`\``;
case 'json':
return `\`\`\`json\n${displayContent}\n\`\`\``;
case 'conf':
return `\`\`\`ini\n${displayContent}\n\`\`\``;
case 'plain':
return `\`\`\`text\n${displayContent}\n\`\`\``;
default:
return displayContent;
}
};
const handleOpenChange = (newOpen: boolean) => {
setIsOpen(newOpen);
};
return (
<>
<Button variant='ghost' size='sm' onClick={() => setIsOpen(true)}>
<Icon icon='mdi:eye' className='mr-2 h-4 w-4' />
{t('preview')}
</Button>
<Sheet open={isOpen} onOpenChange={handleOpenChange}>
<SheetContent className='w-[800px] max-w-[90vw] md:max-w-screen-md'>
<SheetHeader>
<SheetTitle>{t('title')}</SheetTitle>
</SheetHeader>
{isLoading ? (
<div className='flex items-center justify-center'>
<Icon icon='mdi:loading' className='h-6 w-6 animate-spin' />
<span className='ml-2'>{t('loading')}</span>
</div>
) : (
<div className='*:text-sm [&_pre>div>div+div]:max-h-[calc(100dvh-48px-36px-36px)] [&_pre>div>div+div]:overflow-auto'>
<Markdown>{getDisplayContent()}</Markdown>
</div>
)}
</SheetContent>
</Sheet>
</>
);
}
@@ -32,7 +32,7 @@ import { toast } from 'sonner';
import { z } from 'zod';
const privacyPolicySchema = z.object({
content: z.string().optional(),
privacy_policy: z.string().optional(),
});
type PrivacyPolicyFormData = z.infer<typeof privacyPolicySchema>;
@@ -54,14 +54,14 @@ export default function PrivacyPolicyConfig() {
const form = useForm<PrivacyPolicyFormData>({
resolver: zodResolver(privacyPolicySchema),
defaultValues: {
content: '',
privacy_policy: '',
},
});
useEffect(() => {
if (data) {
form.reset({
content: data.content || '',
privacy_policy: data.privacy_policy || '',
});
}
}, [data, form]);
@@ -109,7 +109,7 @@ export default function PrivacyPolicyConfig() {
>
<FormField
control={form.control}
name='content'
name='privacy_policy'
render={({ field }) => (
<FormItem>
<FormLabel>{t('privacyPolicy.title')}</FormLabel>
@@ -31,7 +31,7 @@ import { toast } from 'sonner';
import { z } from 'zod';
const tosSchema = z.object({
content: z.string().optional(),
tos_content: z.string().optional(),
});
type TosFormData = z.infer<typeof tosSchema>;
@@ -53,14 +53,14 @@ export default function TosConfig() {
const form = useForm<TosFormData>({
resolver: zodResolver(tosSchema),
defaultValues: {
content: '',
tos_content: '',
},
});
useEffect(() => {
if (data) {
form.reset({
content: data.content || '',
tos_content: data.tos_content || '',
});
}
}, [data, form]);
@@ -104,7 +104,7 @@ export default function TosConfig() {
<form id='tos-form' onSubmit={form.handleSubmit(onSubmit)} className='space-y-2 pt-4'>
<FormField
control={form.control}
name='content'
name='tos_content'
render={({ field }) => (
<FormItem>
<FormLabel>{t('tos.title')}</FormLabel>
@@ -35,12 +35,13 @@ import { z } from 'zod';
const registerSchema = z.object({
stop_register: z.boolean().optional(),
enable_trial: z.boolean().optional(),
trial_subscribe: z.number().optional(),
trial_time: z.number().optional(),
trial_time_unit: z.string().optional(),
enable_ip_register_limit: z.boolean().optional(),
ip_register_limit_count: z.number().optional(),
ip_register_limit_expire_day: z.number().optional(),
trial_flow: z.number().optional(),
trial_day: z.number().optional(),
default_subscribe_id: z.number().optional(),
ip_register_limit: z.number().optional(),
ip_register_limit_duration: z.number().optional(),
});
type RegisterFormData = z.infer<typeof registerSchema>;
@@ -76,12 +77,13 @@ export default function RegisterConfig() {
resolver: zodResolver(registerSchema),
defaultValues: {
stop_register: false,
enable_trial: false,
trial_subscribe: undefined,
trial_time: 0,
trial_time_unit: 'day',
enable_ip_register_limit: false,
ip_register_limit_count: 1,
ip_register_limit_expire_day: 1,
trial_flow: 0,
trial_day: 0,
default_subscribe_id: undefined,
ip_register_limit: 1,
ip_register_limit_duration: 1,
},
});
@@ -165,127 +167,152 @@ export default function RegisterConfig() {
/>
</FormControl>
<FormDescription>{t('ipRegistrationLimitDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{form.watch('enable_ip_register_limit') && (
<div className='grid grid-cols-1 gap-4 md:grid-cols-2'>
<FormField
control={form.control}
name='ip_register_limit'
render={({ field }) => (
<FormItem>
<FormLabel>{t('registrationLimitCount')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={1}
onValueBlur={(value) => field.onChange(Number(value))}
/>
</FormControl>
<FormDescription>{t('registrationLimitCountDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='ip_register_limit_duration'
render={({ field }) => (
<FormItem>
<FormLabel>{t('registrationLimitExpire')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={1}
suffix={t('minute')}
onValueBlur={(value) => field.onChange(Number(value))}
/>
</FormControl>
<FormDescription>{t('registrationLimitExpireDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</div>
)}
<FormField
control={form.control}
name='ip_register_limit_count'
name='enable_trial'
render={({ field }) => (
<FormItem>
<FormLabel>{t('registrationLimitCount')}</FormLabel>
<FormLabel>{t('enableTrial')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={1}
onValueBlur={(value) => field.onChange(Number(value))}
<Switch
checked={field.value}
onCheckedChange={field.onChange}
className='float-end !mt-0'
/>
</FormControl>
<FormDescription>{t('registrationLimitCountDescription')}</FormDescription>
<FormDescription>{t('enableTrialDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='ip_register_limit_expire_day'
render={({ field }) => (
<FormItem>
<FormLabel>{t('registrationLimitExpire')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={1}
suffix={t('day')}
onValueBlur={(value) => field.onChange(Number(value))}
/>
</FormControl>
<FormDescription>{t('registrationLimitExpireDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='trial_flow'
render={({ field }) => (
<FormItem>
<FormLabel>{t('trialFlow')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={0}
suffix='GB'
onValueBlur={(value) => field.onChange(Number(value))}
/>
</FormControl>
<FormDescription>{t('trialFlowDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='trial_day'
render={({ field }) => (
<FormItem>
<FormLabel>{t('trialDay')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={0}
suffix={t('day')}
onValueBlur={(value) => field.onChange(Number(value))}
/>
</FormControl>
<FormDescription>{t('trialDayDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='default_subscribe_id'
render={({ field }) => (
<FormItem>
<FormLabel>{t('defaultSubscribe')}</FormLabel>
<FormControl>
<Combobox
placeholder={t('selectPlaceholder')}
value={field.value}
onChange={(value: number) => {
if (value) {
field.onChange(value);
}
}}
options={
subscribe?.map((item) => ({
label: item.name,
value: item.id,
})) || []
}
/>
</FormControl>
<FormDescription>{t('defaultSubscribeDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{form.watch('enable_trial') && (
<>
<FormField
control={form.control}
name='trial_time'
render={({ field }) => (
<FormItem>
<FormLabel>{t('trialConfig')}</FormLabel>
<FormControl>
<div className='flex gap-2'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={field.value}
type='number'
min={0}
onValueBlur={(value) => field.onChange(Number(value))}
className='flex-1'
prefix={
<FormField
control={form.control}
name='trial_subscribe'
render={({ field }) => (
<Combobox
placeholder={t('selectPlaceholder')}
value={field.value}
onChange={(value: number) => {
if (value) {
field.onChange(value);
}
}}
options={
subscribe?.map((item) => ({
label: item.name,
value: item.id,
})) || []
}
className='bg-secondary w-32 rounded-r-none'
/>
)}
/>
}
suffix={
<FormField
control={form.control}
name='trial_time_unit'
render={({ field: unitField }) => (
<Combobox
placeholder={t('selectPlaceholder')}
value={unitField.value}
onChange={(value: string) => {
unitField.onChange(value);
}}
options={[
{ label: t('none'), value: 'None' },
{ label: t('year'), value: 'Year' },
{ label: t('month'), value: 'Month' },
{ label: t('day'), value: 'Day' },
{ label: t('hour'), value: 'Hour' },
{ label: t('minute'), value: 'Minute' },
]}
className='bg-secondary w-32 rounded-l-none'
/>
)}
/>
}
/>
</div>
</FormControl>
<FormDescription>{t('trialConfigDescription')}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</>
)}
</form>
</Form>
</ScrollArea>
+1 -1
View File
@@ -172,7 +172,7 @@ export default function Page() {
<DrawerDescription>{ticket?.description}</DrawerDescription>
</DrawerHeader>
<ScrollArea className='h-full overflow-hidden' ref={scrollRef}>
<div className='flex h-screen flex-col gap-4 p-4'>
<div className='flex h-full flex-col gap-4 p-4'>
{ticket?.follow?.map((item) => (
<div
key={item.id}
+16 -12
View File
@@ -25,42 +25,46 @@ export function SidebarLeft({ ...props }: React.ComponentProps<typeof Sidebar>)
const pathname = usePathname();
return (
<Sidebar className='border-r-0' collapsible='icon' {...props}>
<SidebarHeader>
<SidebarHeader className='p-2'>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size='lg' asChild>
<SidebarMenuButton size='sm' asChild className='h-10'>
<Link href='/'>
<div className='flex aspect-square size-8 items-center justify-center rounded-lg'>
<div className='flex aspect-square size-6 items-center justify-center rounded-lg'>
<Image
src={site.site_logo || '/favicon.svg'}
alt='logo'
width={48}
height={48}
width={24}
height={24}
className='size-full'
unoptimized
/>
</div>
<div className='grid flex-1 text-left text-sm leading-tight'>
<span className='truncate font-semibold'>{site.site_name}</span>
<span className='truncate text-xs'>{site.site_desc}</span>
<span className='truncate text-xs font-semibold'>{site.site_name}</span>
<span className='truncate text-xs opacity-70'>{site.site_desc}</span>
</div>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarContent className='py-2'>
<SidebarMenu>
{navs.map((nav) => (
<SidebarGroup key={nav.title}>
{nav.items && <SidebarGroupLabel>{t(nav.title)}</SidebarGroupLabel>}
<SidebarGroup key={nav.title} className='py-1'>
{nav.items && (
<SidebarGroupLabel className='py-1 text-xs'>{t(nav.title)}</SidebarGroupLabel>
)}
<SidebarGroupContent>
<SidebarMenu>
{(nav.items || [nav]).map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton
asChild
size='sm'
tooltip={t(item.title)}
className='h-8'
isActive={
item.url === '/dashboard'
? pathname === item.url
@@ -68,8 +72,8 @@ export function SidebarLeft({ ...props }: React.ComponentProps<typeof Sidebar>)
}
>
<Link href={item.url}>
{item.icon && <Icon icon={item.icon} />}
<span>{t(item.title)}</span>
{item.icon && <Icon icon={item.icon} className='size-4' />}
<span className='text-sm'>{t(item.title)}</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
+25 -59
View File
@@ -1,42 +1,3 @@
export const AuthControl = [
{
title: 'Email',
url: '/dashboard/auth-control/email',
},
{
title: 'Phone Number',
url: '/dashboard/auth-control/phone',
},
{
title: 'Telegram',
url: '/dashboard/auth-control/telegram',
},
{
title: 'Apple',
url: '/dashboard/auth-control/apple',
},
{
title: 'Google',
url: '/dashboard/auth-control/google',
},
{
title: 'Facebook',
url: '/dashboard/auth-control/facebook',
},
// {
// title: 'Twitter',
// url: '/dashboard/auth-control/twitter',
// },
{
title: 'GitHub',
url: '/dashboard/auth-control/github',
},
{
title: 'Device',
url: '/dashboard/auth-control/device',
},
];
export const navs = [
{
title: 'Dashboard',
@@ -44,7 +5,7 @@ export const navs = [
icon: 'flat-color-icons:globe',
},
{
title: 'Settings',
title: 'System Management',
items: [
{
title: 'System Config',
@@ -55,43 +16,48 @@ export const navs = [
title: 'Auth Control',
url: '/dashboard/auth-control',
icon: 'flat-color-icons:lock-portrait',
items: AuthControl,
},
{
title: 'Payment Config',
url: '/dashboard/payment',
icon: 'flat-color-icons:currency-exchange',
},
{
title: 'ADS Config',
url: '/dashboard/ads',
icon: 'flat-color-icons:electrical-sensor',
},
{
title: 'Payment Config',
url: '/dashboard/payment',
icon: 'flat-color-icons:currency-exchange',
title: 'System Tool',
url: '/dashboard/tool',
icon: 'flat-color-icons:info',
},
],
},
{
title: 'Server',
items: [
{
title: 'Subscribe Config',
url: '/dashboard/subscribe',
icon: 'flat-color-icons:ruler',
},
{
title: 'Server Management',
url: '/dashboard/server',
icon: 'flat-color-icons:data-protection',
},
{
title: 'Product Management',
url: '/dashboard/product',
icon: 'flat-color-icons:shop',
},
{
title: 'Application Management',
url: '/dashboard/application',
icon: 'flat-color-icons:touchscreen-smartphone',
},
{
title: 'Rule Management',
url: '/dashboard/rules',
icon: 'flat-color-icons:ruler',
},
{
title: 'Subscribe Management',
url: '/dashboard/subscribe',
icon: 'flat-color-icons:shop',
},
],
},
{
@@ -123,6 +89,11 @@ export const navs = [
},
],
},
{
title: 'Marketing Management',
url: '/dashboard/marketing',
icon: 'flat-color-icons:bullish',
},
{
title: 'Announcement Management',
url: '/dashboard/announcement',
@@ -140,11 +111,6 @@ export const navs = [
},
],
},
{
title: 'System Tool',
url: '/dashboard/tool',
icon: 'flat-color-icons:info',
},
];
export function findNavByUrl(url: string) {
+2
View File
@@ -57,6 +57,8 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
subscribe_path: '',
subscribe_domain: '',
pan_domain: false,
user_agent_limit: false,
user_agent_list: '',
},
verify_code: {
verify_code_expire_time: 5,
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Další",
"additionalRecipientEmails": "Další e-mailové adresy příjemců",
"additionalRecipients": "Další příjemci",
"additionalRecipientsDescription": "Tyto e-maily obdrží vysílání kromě uživatelského filtru výše",
"allUsers": "Všichni uživatelé",
"broadcastList": "Seznam vysílání",
"broadcastLogs": "Záznamy vysílání",
"cancel": "Zrušit",
"cannotBeEmpty": "nemůže být prázdné",
"completed": "Dokončeno",
"confirm": "Potvrdit",
"confirmDelete": "Potvrdit smazání",
"content": "Obsah e-mailu",
"create": "Vytvořit",
"createBroadcast": "Vytvořit vysílání",
"createNewEmailBroadcastCampaign": "Vytvořit novou kampaň e-mailového vysílání",
"createSuccess": "Úspěšně vytvořeno",
"createdAt": "Vytvořeno dne",
"dailyLimit": "Denní limit musí být alespoň 1",
"dailySendLimit": "Denní limit odeslání",
"delete": "Smazat",
"deleteDescription": "Tuto operaci nelze vrátit zpět. Opravdu chcete smazat?",
"deleteSuccess": "Úspěšně smazáno",
"edit": "Upravit",
"emailAddedToScheduledQueue": "E-mail přidán do naplánované fronty odeslání",
"emailBroadcast": "E-mailové vysílání",
"emailBroadcastTaskCreatedSuccessfully": "Úkol e-mailového vysílání byl úspěšně vytvořen",
"emailBroadcastTasks": "Úkoly e-mailového vysílání",
"emailContent": "Obsah e-mailu",
"emailInterval": "Interval e-mailu (sekundy)",
"emailIntervalMinimum": "Interval e-mailu musí být alespoň 0,1 sekundy",
"emailMarketing": "E-mailový marketing",
"emailTaskManager": "Správce úkolů e-mailu",
"errorMessage": "Zpráva o chybě",
"estimatedRecipients": "Odhadovaný počet příjemců",
"expiredSubscriptionUsersOnly": "Pouze uživatelé s vypršeným předplatným",
"expiredUsers": "Uživatelé s vypršeným předplatným",
"failCount": "Počet neúspěchů",
"failed": "Neúspěšně",
"failedToRefreshTaskStatus": "Nepodařilo se obnovit stav úkolu",
"failedToStopTask": "Nepodařilo se zastavit úkol",
"inProgress": "Probíhá",
"includeUsersRegisteredAfter": "Zahrnout uživatele registrované po tomto datu",
"includeUsersRegisteredBefore": "Zahrnout uživatele registrované před tímto datem",
"intervalTimeBetweenEmails": "Časový interval mezi jednotlivými e-maily",
"leaveEmptyForImmediateSend": "Nechte prázdné pro okamžité odeslání",
"logList": "Seznam záznamů",
"marketingManagement": "Správa marketingu",
"maximumNumberPerDay": "Maximální počet e-mailů k odeslání za den",
"noSubscriptionUsersOnly": "Pouze uživatelé bez předplatného",
"nonSubscribers": "Nepředplatitelé",
"notStarted": "Nebylo zahájeno",
"onePerLine": "jeden na řádek",
"only": "pouze",
"pending": "Čeká se",
"pleaseEnter": "Prosím zadejte",
"pleaseEnterValidEmailAddresses": "Prosím zadejte platné e-mailové adresy, jednu na řádek",
"processing": "Zpracovává se...",
"progress": "Pokrok",
"recipient": "Příjemce",
"recipientEmail": "E-mail příjemce",
"recipientType": "Typ příjemce",
"registrationEndDate": "Datum ukončení registrace",
"registrationStartDate": "Datum zahájení registrace",
"scheduleSend": "Naplánovat odeslání",
"scheduledSend": "Naplánované odeslání",
"scheduledSendTimeMustBeLater": "Čas naplánovaného odeslání musí být pozdější než aktuální čas",
"selectSendScope": "Vyberte rozsah odeslání",
"selectSendTime": "Vyberte čas odeslání, nechte prázdné pro okamžité odeslání",
"sendFailed": "Odeslání selhalo, zkuste to prosím znovu",
"sendNow": "Odeslat nyní",
"sendScope": "Rozsah odeslání",
"sendScopeDescription": "Vyberte uživatelský rozsah pro odesílání e-mailů. Vyberte \"Pouze další e-maily\" pro odeslání pouze na e-mailové adresy vyplněné níže",
"sendSettings": "Nastavení odeslání",
"sendTime": "Čas odeslání",
"sending": "Odesílání",
"sentAt": "Odesláno dne",
"specificUsers": "Specifičtí uživatelé",
"specificUsersOnly": "Pouze další e-maily (přeskočit uživatele platformy)",
"status": "Stav",
"stop": "Zastavit",
"stopped": "Zastaveno",
"subject": "Předmět e-mailu",
"subscribedUsers": "Přihlášení uživatelé",
"subscribedUsersOnly": "Pouze přihlášení uživatelé",
"successCount": "Počet úspěchů",
"taskStatusRefreshed": "Stav úkolu obnoven",
"taskStoppedSuccessfully": "Úkol úspěšně zastaven",
"totalSent": "Celkem odesláno",
"updateSuccess": "Úspěšně aktualizováno",
"useMarkdownEditor": "Použijte editor Markdown pro psaní obsahu e-mailu s funkcí náhledu",
"users": "uživatelé",
"view": "Zobrazit",
"viewAndManageEmailBroadcastTasks": "Zobrazit a spravovat úkoly e-mailového vysílání",
"viewContent": "Zobrazit obsah"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "Konfigurace ADS",
"Announcement Management": "Správa oznámení",
"Apple": "Apple ID",
"Application Management": "Správa aplikací",
"Auth Control": "Řízení ověřování",
"Coupon Management": "Správa kupónů",
"Dashboard": "Přístrojová deska",
"Device": "Zařízení",
"Document Management": "Správa dokumentů",
"Email": "E-mail",
"Facebook": "Facebook",
"Finance": "Finance",
"General": "Obecné",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Řízení marketingu",
"Order Management": "Správa objednávek",
"Payment Config": "Konfigurace platby",
"Phone Number": "Telefonní číslo",
"Product Management": "Správa produktů",
"Protocol Management": "Správa protokolů",
"Rule Management": "Správa pravidel",
"Server": "Server",
"Server Management": "Správa serveru",
"Settings": "Nastavení",
"Subscribe Management": "Správa předplatného",
"Subscribe Config": "Nastavení odběru",
"System Config": "Systémová konfigurace",
"System Management": "Správa systému",
"System Tool": "Systémový nástroj",
"Telegram": "Telegram",
"Ticket Management": "Správa lístků",
"Twitter": "Twitter",
"User": "Uživatel",
"User Detail": "Podrobnosti o uživateli",
"User Management": "Správa uživatelů"
+161
View File
@@ -0,0 +1,161 @@
{
"actions": "akce",
"app": {
"appDownloadURL": "URL pro stažení aplikace",
"appIcon": "Ikona aplikace",
"appList": "Seznam aplikací",
"appName": "Název aplikace",
"backupDomains": "Seznam záložních domén",
"backupDomainsDescription": "Seznam záložních domén pro řešení domén, jedna doména na řádek",
"batchDelete": "Hromadné smazání",
"cancel": "Zrušit",
"communicationKey": "Komunikační klíč",
"communicationKeyDescription": "Klíč používaný pro komunikaci klienta",
"config": "Konfigurace",
"configApp": "Konfigurace aplikace",
"confirm": "Potvrdit",
"confirmDelete": "Potvrdit smazání",
"create": "Vytvořit",
"createApp": "Vytvořit aplikaci",
"createSuccess": "Úspěšně vytvořeno",
"defaultVersion": "Výchozí",
"delete": "Smazat",
"deleteWarning": "Tuto akci nelze vrátit zpět",
"describeDescription": "Používá se k popisu aplikace, zobrazuje se v seznamu aplikací",
"description": "Popis",
"downloadLink": "Odkaz ke stažení",
"edit": "Upravit",
"editApp": "Upravit aplikaci",
"encryption": "Metoda šifrování",
"encryptionDescription": "Vyberte metodu šifrování pro komunikaci klienta. Pokud je vybrána, klient použije tuto metodu ke komunikaci se serverem",
"nameDescription": "Název aplikace, zobrazuje se v seznamu aplikací",
"platform": "Platforma",
"selectApp": "Vybrat aplikaci",
"selectAppDescription": "Vyberte aplikaci k nastavení, všechna nastavení se použijí na vybranou aplikaci",
"startupPicture": "Úvodní obrázek",
"startupPictureDescription": "Úvodní obrázek, podporuje síťové a lokální obrázky. Pro síťové obrázky zadejte úplnou URL adresu obrázku",
"startupPicturePreview": "Náhled úvodního obrázku",
"startupPictureSkip": "Čas přeskočení úvodního obrázku",
"startupPictureSkipDescription": "Doba zobrazení úvodního obrázku v sekundách, zadejte 0 pro nezobrazení",
"subscriptionProtocol": "Protokol předplatného",
"updateSuccess": "Úspěšně aktualizováno",
"version": "Verze"
},
"cancel": "Zrušit",
"config": {
"singleSubscriptionMode": "Režim jednorázového předplatného",
"singleSubscriptionModeDescription": "Když je povoleno, všechna uživatelská předplatná budou převedena na zůstatek",
"subscriptionDomain": "Doména předplatného",
"subscriptionDomainDescription": "Používá se pro předplatné; nechte prázdné pro použití domény webu",
"subscriptionDomainPlaceholder": "Zadejte doménu předplatného, jednu na řádek",
"subscriptionPath": "Cesta předplatného",
"subscriptionPathDescription": "Používá se pro předplatné; po úpravě nezapomeňte restartovat systém pro optimální výkon",
"subscriptionPathPlaceholder": "Zadejte",
"updateSuccess": "Úspěšně aktualizováno",
"wildcardResolution": "Řešení zástupných znaků",
"wildcardResolutionDescription": "Používá se pro předplatné"
},
"confirm": "Potvrdit",
"confirmDelete": "Opravdu chcete smazat?",
"copy": "Kopírovat",
"copySuccess": "Úspěšně zkopírováno",
"create": "Vytvořit",
"createSubscribe": "Vytvořit odběr",
"createSuccess": "Vytvoření úspěšné",
"delete": "smazat",
"deleteSuccess": "Úspěšně odstraněno",
"deleteWarning": "Po odstranění nelze data obnovit, prosím, postupujte opatrně.",
"deviceLimit": "Počet zařízení/ks",
"edit": "Upravit",
"editSubscribe": "Upravit odběr",
"form": {
"Day": "Den",
"Hour": "Hodina",
"Minute": "Minuta",
"Month": "Měsíc",
"NoLimit": "Bez omezení",
"Year": "Rok",
"annualReset": "Roční Reset",
"basic": "Základní",
"cancel": "Zrušit",
"confirm": "Potvrdit",
"deductionRatio": "Automatická/Manuální Konfigurace Odpočtu",
"deductionRatioDescription": "Používá se pro odpočet. Systém standardně používá automatický výpočetní algoritmus. Když je poskytnut manuální poměr, systém vypočítá proporce na základě časového a dopravního poměru, přičemž celkový součet činí 100%.",
"description": "Popis",
"deviceLimit": "Omezení zařízení",
"discount": "Sleva",
"discountDescription": "Nastavit slevu na základě jednotkové ceny",
"discountMonths": "Měsíce",
"discountPercent": "Procento slevy",
"discount_price": "Cena po slevě",
"duration": "Doba trvání (měsíce)",
"groupId": "Skupina předplatného",
"inventory": "Limit předplatného",
"monthlyReset": "Měsíční Reset",
"name": "Název",
"noLimit": "Bez omezení",
"noReset": "Žádný Reset",
"pricing": "Cenotvorba",
"purchaseWithDiscount": "Povolit Odpočet",
"purchaseWithDiscountDescription": "Povolit nebo zakázat funkci odhlášení. Po aktivaci systém provede zpracování odpočtu podle nakonfigurovaných pravidel a poměrů a zbývající hodnota bude vrácena na zůstatek.",
"quota": "Limit nákupu",
"renewalReset": "Reset při Obnovení",
"renewalResetDescription": "Resetovací cyklus při obnovení",
"replacement": "Cena za reset (za každý)",
"resetCycle": "Resetovací Cyklus",
"resetOn1st": "Reset 1. dne",
"selectResetCycle": "Vyberte prosím resetovací cyklus",
"selectSubscribeGroup": "Vyberte prosím skupinu předplatného",
"selectUnitTime": "Vyberte jednotku času",
"server": "Server",
"serverGroup": "Skupina serverů",
"servers": "Servery",
"speedLimit": "Omezení rychlosti ",
"traffic": "Přenos dat",
"unitPrice": "Jednotková cena",
"unitTime": "Jednotka času"
},
"group": {
"actions": "Akce",
"cancel": "Zrušit",
"confirm": "Potvrdit",
"confirmDelete": "Opravdu chcete smazat?",
"create": "Vytvořit",
"createSubscribeGroup": "Vytvořit novou skupinu odběrů",
"createSuccess": "Úspěšně vytvořeno",
"delete": "Smazat",
"deleteSuccess": "Úspěšně smazáno",
"deleteWarning": "Po smazání nelze data obnovit, prosím postupujte opatrně.",
"description": "Popis",
"edit": "Upravit",
"editSubscribeGroup": "Upravit skupinu odběrů",
"form": {
"cancel": "Zrušit",
"confirm": "Potvrdit",
"description": "Popis",
"name": "Název"
},
"name": "Název",
"title": "Seznam skupin odběrů",
"updateSuccess": "Úspěšně aktualizováno",
"updatedAt": "Čas aktualizace"
},
"inventory": "Limit předplatného",
"name": "název",
"quota": "Limit na nákup/čas",
"replacement": "Obnovení ceny/krát",
"sell": "Prodej",
"show": "Zobrazit",
"sold": "Počet předplatných",
"subscribe": "Předplatit",
"subscribeGroup": "Přihlásit se ke skupině",
"tabs": {
"subscribe": "Předplatit",
"subscribeApp": "Konfigurace aplikace",
"subscribeConfig": "Konfigurace předplatného",
"subscribeGroup": "Skupina předplatných"
},
"traffic": "provoz",
"unitPrice": "Jednotková cena",
"updateSuccess": "Aktualizace byla úspěšná"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Typ",
"updateSuccess": "Úspěšně aktualizováno",
"updatedAt": "Čas aktualizace",
"userAccount": "Uživatelský účet",
"user": "Uživatel",
"userDetail": "Detail uživatele",
"userId": "ID uživatele"
},
+112 -141
View File
@@ -1,161 +1,132 @@
{
"actions": "akce",
"app": {
"appDownloadURL": "URL pro stažení aplikace",
"appIcon": "Ikona aplikace",
"appList": "Seznam aplikací",
"appName": "Název aplikace",
"backupDomains": "Seznam záložních domén",
"backupDomainsDescription": "Seznam záložních domén pro řešení domén, jedna doména na řádek",
"actions": {
"add": "Přidat",
"batchDelete": "Hromadné smazání",
"batchDeleteSuccess": "Úspěšně smazáno {count} klientů",
"batchDeleteWarning": "Opravdu chcete smazat vybrané {count} klienty?",
"cancel": "Zrušit",
"communicationKey": "Komunikační klíč",
"communicationKeyDescription": "Klíč používaný pro komunikaci klienta",
"config": "Konfigurace",
"configApp": "Konfigurace aplikace",
"confirm": "Potvrdit",
"confirmDelete": "Potvrdit smazání",
"create": "Vytvořit",
"createApp": "Vytvořit aplikaci",
"createSuccess": "Úspěšně vytvořeno",
"defaultVersion": "Výchozí",
"delete": "Smazat",
"deleteWarning": "Tuto akci nelze vrátit zpět",
"describeDescription": "Používá se k popisu aplikace, zobrazuje se v seznamu aplikací",
"description": "Popis",
"downloadLink": "Odkaz ke stažení",
"deleteFailed": "Smazání se nezdařilo",
"deleteSuccess": "Úspěšně smazáno",
"deleteWarning": "Tuto operaci nelze vrátit zpět. Opravdu chcete smazat tohoto klienta?",
"edit": "Upravit",
"editApp": "Upravit aplikaci",
"encryption": "Metoda šifrování",
"encryptionDescription": "Vyberte metodu šifrování pro komunikaci klienta. Pokud je vybrána, klient použije tuto metodu ke komunikaci se serverem",
"nameDescription": "Název aplikace, zobrazuje se v seznamu aplikací",
"platform": "Platforma",
"selectApp": "Vybrat aplikaci",
"selectAppDescription": "Vyberte aplikaci k nastavení, všechna nastavení se použijí na vybranou aplikaci",
"startupPicture": "Úvodní obrázek",
"startupPictureDescription": "Úvodní obrázek, podporuje síťové a lokální obrázky. Pro síťové obrázky zadejte úplnou URL adresu obrázku",
"startupPicturePreview": "Náhled úvodního obrázku",
"startupPictureSkip": "Čas přeskočení úvodního obrázku",
"startupPictureSkipDescription": "Doba zobrazení úvodního obrázku v sekundách, zadejte 0 pro nezobrazení",
"subscriptionProtocol": "Protokol předplatného",
"updateSuccess": "Úspěšně aktualizováno",
"version": "Verze"
"save": "Uložit",
"saveFailed": "Uložení se nezdařilo",
"update": "Aktualizovat",
"updateSuccess": "Úspěšně aktualizováno"
},
"cancel": "Zrušit",
"config": {
"singleSubscriptionMode": "Režim jednorázového předplatného",
"singleSubscriptionModeDescription": "Když je povoleno, všechna uživatelská předplatná budou převedena na zůstatek",
"description": "Spravujte nastavení systému předplatného",
"singleSubscriptionMode": "Režim jednoho předplatného",
"singleSubscriptionModeDescription": "Omezit uživatele na jedno aktivní předplatné. Existující předplatná nejsou ovlivněna",
"subscriptionDomain": "Doména předplatného",
"subscriptionDomainDescription": "Používá se pro předplatné; nechte prázdné pro použití domény webu",
"subscriptionDomainDescription": "Vlastní doména pro odkazy na předplatné",
"subscriptionDomainPlaceholder": "Zadejte doménu předplatného, jednu na řádek",
"subscriptionPath": "Cesta předplatného",
"subscriptionPathDescription": "Používá se pro předplatné; po úpravě nezapomeňte restartovat systém pro optimální výkon",
"subscriptionPathPlaceholder": "Zadejte",
"updateSuccess": "Úspěšně aktualizováno",
"subscriptionPathDescription": "Vlastní cesta pro koncové body předplatného (lepší výkon po restartu systému)",
"subscriptionPathPlaceholder": "Zadejte cestu předplatného",
"title": "Konfigurace předplatného",
"updateError": "Aktualizace se nezdařila",
"updateSuccess": "Nastavení byla úspěšně aktualizována",
"userAgentLimit": "{userAgent} Omezení",
"userAgentLimitDescription": "Povolit omezení přístupu na základě {userAgent}",
"userAgentList": "{userAgent} Bílá listina",
"userAgentListDescription": "Povolené {userAgent} pro přístup k předplatnému, jedna na řádek. Konfigurovaná aplikace {userAgent} bude automaticky zahrnuta",
"userAgentListPlaceholder": "Zadejte povolené {userAgent}, jedna na řádek",
"wildcardResolution": "Řešení zástupných znaků",
"wildcardResolutionDescription": "Používá se pro předplatné"
"wildcardResolutionDescription": "Povolit řešení domény se zástupnými znaky pro předplatná"
},
"confirm": "Potvrdit",
"confirmDelete": "Opravdu chcete smazat?",
"copy": "Kopírovat",
"copySuccess": "Úspěšně zkopírováno",
"create": "Vytvořit",
"createSubscribe": "Vytvořit odběr",
"createSuccess": "Vytvoření úspěšné",
"delete": "smazat",
"deleteSuccess": "Úspěšně odstraněno",
"deleteWarning": "Po odstranění nelze data obnovit, prosím, postupujte opatrně.",
"deviceLimit": "Počet zařízení/ks",
"edit": "Upravit",
"editSubscribe": "Upravit odběr",
"form": {
"Day": "Den",
"Hour": "Hodina",
"Minute": "Minuta",
"Month": "Měsíc",
"NoLimit": "Bez omezení",
"Year": "Rok",
"annualReset": "Roční Reset",
"basic": "Základní",
"cancel": "Zrušit",
"confirm": "Potvrdit",
"deductionRatio": "Automatická/Manuální Konfigurace Odpočtu",
"deductionRatioDescription": "Používá se pro odpočet. Systém standardně používá automatický výpočetní algoritmus. Když je poskytnut manuální poměr, systém vypočítá proporce na základě časového a dopravního poměru, přičemž celkový součet činí 100%.",
"description": "Popis",
"deviceLimit": "Omezení zařízení",
"discount": "Sleva",
"discountDescription": "Nastavit slevu na základě jednotkové ceny",
"discountMonths": "Měsíce",
"discountPercent": "Procento slevy",
"discount_price": "Cena po slevě",
"duration": "Doba trvání (měsíce)",
"groupId": "Skupina předplatného",
"inventory": "Limit předplatného",
"monthlyReset": "Měsíční Reset",
"name": "Název",
"noLimit": "Bez omezení",
"noReset": "Žádný Reset",
"pricing": "Cenotvorba",
"purchaseWithDiscount": "Povolit Odpočet",
"purchaseWithDiscountDescription": "Povolit nebo zakázat funkci odhlášení. Po aktivaci systém provede zpracování odpočtu podle nakonfigurovaných pravidel a poměrů a zbývající hodnota bude vrácena na zůstatek.",
"quota": "Limit nákupu",
"renewalReset": "Reset při Obnovení",
"renewalResetDescription": "Resetovací cyklus při obnovení",
"replacement": "Cena za reset (za každý)",
"resetCycle": "Resetovací Cyklus",
"resetOn1st": "Reset 1. dne",
"selectResetCycle": "Vyberte prosím resetovací cyklus",
"selectSubscribeGroup": "Vyberte prosím skupinu předplatného",
"selectUnitTime": "Vyberte jednotku času",
"server": "Server",
"serverGroup": "Skupina serverů",
"servers": "Servery",
"speedLimit": "Omezení rychlosti ",
"traffic": "Přenos dat",
"unitPrice": "Jednotková cena",
"unitTime": "Jednotka času"
},
"group": {
"actions": "Akce",
"cancel": "Zrušit",
"confirm": "Potvrdit",
"confirmDelete": "Opravdu chcete smazat?",
"create": "Vytvořit",
"createSubscribeGroup": "Vytvořit novou skupinu odběrů",
"createSuccess": "Úspěšně vytvořeno",
"delete": "Smazat",
"deleteSuccess": "Úspěšně smazáno",
"deleteWarning": "Po smazání nelze data obnovit, prosím postupujte opatrně.",
"description": "Popis",
"edit": "Upravit",
"editSubscribeGroup": "Upravit skupinu odběrů",
"form": {
"cancel": "Zrušit",
"confirm": "Potvrdit",
"description": "Popis",
"name": "Název"
"addTitle": "Přidat klienta",
"descriptions": {
"description": "Podrobný popis klienta",
"downloadLink": "odkaz na stažení platformy",
"icon": "URL ikony nebo base64 kódování",
"name": "Název zobrazení klienta",
"outputFormat": "Formát konfiguračního souboru předplatného",
"scheme": {
"base64Encoding": "Kódování Base64",
"functions": "Podporuje funkce:",
"jsonStringify": "JSON objekt na řetězec",
"nameVariable": "název webu",
"title": "Šablona URL schématu",
"urlEncoding": "Kódování URL",
"urlVariable": "URL pro odběr",
"variables": "Podporuje proměnné:"
},
"template": {
"description": "Použijte syntaxi Go šablony k generování konfiguračních souborů předplatného",
"functions": "Funkce šablony:",
"if": "podmínkové příkazy",
"nodes": "seznam proxy uzlů",
"range": "iterovat pole",
"siteName": "název webu",
"sprig": "Knihovna funkcí Sprig (zpracování řetězců, data atd.)",
"subscribeName": "název předplatného",
"title": "Syntaxe Go šablony",
"userInfo": "uživatelské informace (provoz, expirace atd.)",
"variables": "Dostupné proměnné:"
},
"userAgentPrefix": "Identifikátor klienta pro rozlišení různých klientů"
},
"name": "Název",
"title": "Seznam skupin odběrů",
"updateSuccess": "Úspěšně aktualizováno",
"updatedAt": "Čas aktualizace"
"editTitle": "Upravit klienta",
"fields": {
"description": "Popis",
"icon": "Ikona",
"name": "Název",
"outputFormat": "Formát výstupu",
"scheme": "URL schéma",
"template": "Šablona souboru předplatného"
},
"tabs": {
"basic": "Základní informace",
"download": "Stahování",
"template": "Šablony"
},
"validation": {
"nameRequired": "Název klienta je povinný",
"userAgentRequiredSuffix": "je povinný"
}
},
"inventory": "Limit předplatného",
"name": "název",
"quota": "Limit na nákup/čas",
"replacement": "Obnovení ceny/krát",
"sell": "Prodej",
"show": "Zobrazit",
"sold": "Počet předplatných",
"subscribe": "Předplatit",
"subscribeGroup": "Přihlásit se ke skupině",
"tabs": {
"subscribe": "Předplatit",
"subscribeApp": "Konfigurace aplikace",
"subscribeConfig": "Konfigurace předplatného",
"subscribeGroup": "Skupina předplatných"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Čistý text",
"yaml": "YAML"
},
"traffic": "provoz",
"unitPrice": "Jednotková cena",
"updateSuccess": "Aktualizace byla úspěšná"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Správa klientů"
},
"table": {
"columns": {
"default": "Výchozí",
"description": "Popis",
"name": "Název klienta",
"outputFormat": "Formát výstupu",
"supportedPlatforms": "Podporované platformy"
}
},
"templatePreview": {
"base64": {
"decodeError": "Dekódování selhalo: Obsah není platný formát Base64",
"decodedContent": "Dekódovaný obsah",
"originalContent": "Původní obsah (Base64)"
},
"failed": "Náhled selhal",
"loading": "Načítání...",
"preview": "Náhled",
"title": "Náhled šablony"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "den(dny)",
"defaultSubscribe": "Výchozí předplatné",
"defaultSubscribeDescription": "Výchozí plán předplatného pro nové uživatele",
"description": "Nastavte související nastavení registrace uživatelů",
"enableTrial": "Povolit zkušební verzi",
"enableTrialDescription": "Pokud je povoleno, noví uživatelé obdrží zkušební předplatné při registraci",
"hour": "Hodina(y)",
"inputPlaceholder": "Prosím zadejte",
"ipRegistrationLimit": "Limit registrace podle IP",
"ipRegistrationLimitDescription": "Omezení počtu registrací z jedné IP adresy",
"minute": "Minuta(y)",
"month": "Měsíc(e)",
"none": "Žádný",
"registrationLimitCount": "Počet registrací v limitu",
"registrationLimitCountDescription": "Počet registrací povolených na IP během limitního období",
"registrationLimitExpire": "Limitní období",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Zastavit registraci nových uživatelů",
"stopNewUserRegistrationDescription": "Pokud je povoleno, registrace nových uživatelů bude zakázána",
"title": "Nastavení registrace",
"trialDay": "Zkušební dny",
"trialDayDescription": "Zkušební dny poskytnuté novým uživatelům při registraci",
"trialFlow": "Zkušební provoz",
"trialFlowDescription": "Zkušební provoz poskytnutý novým uživatelům při registraci"
"trialConfig": "Nastavení zkušební verze",
"trialConfigDescription": "Nastavte zkušební předplatné, dobu trvání a časovou jednotku pro nové uživatele při registraci",
"year": "Rok(y)"
},
"site": {
"customData": "Vlastní data",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Zusätzlich",
"additionalRecipientEmails": "Zusätzliche Empfänger-E-Mails",
"additionalRecipients": "Zusätzliche Empfänger",
"additionalRecipientsDescription": "Diese E-Mails erhalten die Übertragung zusätzlich zu dem oben genannten Benutzerfilter",
"allUsers": "Alle Benutzer",
"broadcastList": "Übertragungsliste",
"broadcastLogs": "Übertragungsprotokolle",
"cancel": "Abbrechen",
"cannotBeEmpty": "darf nicht leer sein",
"completed": "Abgeschlossen",
"confirm": "Bestätigen",
"confirmDelete": "Löschen bestätigen",
"content": "E-Mail-Inhalt",
"create": "Erstellen",
"createBroadcast": "Übertragung erstellen",
"createNewEmailBroadcastCampaign": "Neue E-Mail-Übertragungskampagne erstellen",
"createSuccess": "Erfolgreich erstellt",
"createdAt": "Erstellt am",
"dailyLimit": "Tägliches Limit muss mindestens 1 betragen",
"dailySendLimit": "Tägliches Sendelimit",
"delete": "Löschen",
"deleteDescription": "Dieser Vorgang kann nicht rückgängig gemacht werden. Sind Sie sicher, dass Sie löschen möchten?",
"deleteSuccess": "Erfolgreich gelöscht",
"edit": "Bearbeiten",
"emailAddedToScheduledQueue": "E-Mail zur geplanten Sendewarteschlange hinzugefügt",
"emailBroadcast": "E-Mail-Übertragung",
"emailBroadcastTaskCreatedSuccessfully": "E-Mail-Übertragungsaufgabe erfolgreich erstellt",
"emailBroadcastTasks": "E-Mail-Übertragungsaufgaben",
"emailContent": "E-Mail-Inhalt",
"emailInterval": "E-Mail-Intervall (Sekunden)",
"emailIntervalMinimum": "E-Mail-Intervall muss mindestens 0,1 Sekunden betragen",
"emailMarketing": "E-Mail-Marketing",
"emailTaskManager": "E-Mail-Aufgabenmanager",
"errorMessage": "Fehlermeldung",
"estimatedRecipients": "Geschätzte Empfänger",
"expiredSubscriptionUsersOnly": "Nur abgelaufene Abonnenten",
"expiredUsers": "Abgelaufene Benutzer",
"failCount": "Fehleranzahl",
"failed": "Fehlgeschlagen",
"failedToRefreshTaskStatus": "Aktualisierung des Aufgabenstatus fehlgeschlagen",
"failedToStopTask": "Beenden der Aufgabe fehlgeschlagen",
"inProgress": "In Bearbeitung",
"includeUsersRegisteredAfter": "Benutzer einbeziehen, die nach diesem Datum registriert sind",
"includeUsersRegisteredBefore": "Benutzer einbeziehen, die vor diesem Datum registriert sind",
"intervalTimeBetweenEmails": "Intervallzeit zwischen jeder E-Mail",
"leaveEmptyForImmediateSend": "Leer lassen für sofortige Sendung",
"logList": "Protokollliste",
"marketingManagement": "Marketing-Management",
"maximumNumberPerDay": "Maximale Anzahl von E-Mails, die pro Tag gesendet werden dürfen",
"noSubscriptionUsersOnly": "Nur keine Abonnenten",
"nonSubscribers": "Nicht-Abonnenten",
"notStarted": "Nicht gestartet",
"onePerLine": "eine pro Zeile",
"only": "nur",
"pending": "Ausstehend",
"pleaseEnter": "Bitte eingeben",
"pleaseEnterValidEmailAddresses": "Bitte geben Sie gültige E-Mail-Adressen ein, eine pro Zeile",
"processing": "Verarbeitung...",
"progress": "Fortschritt",
"recipient": "Empfänger",
"recipientEmail": "Empfänger-E-Mail",
"recipientType": "Empfängertyp",
"registrationEndDate": "Registrierungsenddatum",
"registrationStartDate": "Registrierungsstartdatum",
"scheduleSend": "Sendung planen",
"scheduledSend": "Geplante Sendung",
"scheduledSendTimeMustBeLater": "Die geplante Sendezeit muss später als die aktuelle Zeit sein",
"selectSendScope": "Sendeumfang auswählen",
"selectSendTime": "Sendezeit auswählen, leer lassen für sofortige Sendung",
"sendFailed": "Sendung fehlgeschlagen, bitte erneut versuchen",
"sendNow": "Jetzt senden",
"sendScope": "Sendeumfang",
"sendScopeDescription": "Wählen Sie den Benutzerumfang für den E-Mail-Versand. Wählen Sie \"Nur zusätzliche E-Mails\", um nur an die unten ausgefüllten E-Mail-Adressen zu senden",
"sendSettings": "Sendeinstellungen",
"sendTime": "Sendezeit",
"sending": "Senden",
"sentAt": "Gesendet am",
"specificUsers": "Spezifische Benutzer",
"specificUsersOnly": "Nur zusätzliche E-Mails (Plattformbenutzer überspringen)",
"status": "Status",
"stop": "Stoppen",
"stopped": "Gestoppt",
"subject": "E-Mail-Betreff",
"subscribedUsers": "Abonnierte Benutzer",
"subscribedUsersOnly": "Nur abonnierte Benutzer",
"successCount": "Erfolgsanzahl",
"taskStatusRefreshed": "Aufgabenstatus aktualisiert",
"taskStoppedSuccessfully": "Aufgabe erfolgreich gestoppt",
"totalSent": "Insgesamt gesendet",
"updateSuccess": "Erfolgreich aktualisiert",
"useMarkdownEditor": "Markdown-Editor verwenden, um E-Mail-Inhalte mit Vorschaufunktion zu schreiben",
"users": "Benutzer",
"view": "Anzeigen",
"viewAndManageEmailBroadcastTasks": "E-Mail-Übertragungsaufgaben anzeigen und verwalten",
"viewContent": "Inhalt anzeigen"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "ADS-Konfiguration",
"Announcement Management": "Ankündigungsverwaltung",
"Apple": "Apple-ID",
"Application Management": "Anwendungsverwaltung",
"Auth Control": "Authentifizierungskontrolle",
"Coupon Management": "Gutscheinverwaltung",
"Dashboard": "Armaturenbrett",
"Device": "Gerät",
"Document Management": "Dokumentenverwaltung",
"Email": "E-Mail",
"Facebook": "Facebook",
"Finance": "Finanzen",
"General": "Allgemein",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Marketingmanagement",
"Order Management": "Bestellverwaltung",
"Payment Config": "Zahlungskonfiguration",
"Phone Number": "Telefonnummer",
"Product Management": "Produktmanagement",
"Protocol Management": "Protokollverwaltung",
"Rule Management": "Regelverwaltung",
"Server": "Dienst",
"Server Management": "Serververwaltung",
"Settings": "Einstellungen",
"Subscribe Management": "Abonnementverwaltung",
"Subscribe Config": "Abonnieren-Konfiguration",
"System Config": "Systemkonfiguration",
"System Management": "Systemverwaltung",
"System Tool": "Systemwerkzeug",
"Telegram": "Telegram",
"Ticket Management": "Ticketverwaltung",
"Twitter": "Twitter",
"User": "Benutzer",
"User Detail": "Benutzerdetails",
"User Management": "Benutzerverwaltung"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "Aktionen",
"app": {
"appDownloadURL": "App-Download-URL",
"appIcon": "App-Symbol",
"appList": "App-Liste",
"appName": "App-Name",
"backupDomains": "Liste der Backup-Domains",
"backupDomainsDescription": "Liste der Backup-Domains für die Domain-Auflösung, eine Domain pro Zeile",
"batchDelete": "Stapel löschen",
"cancel": "Abbrechen",
"communicationKey": "Kommunikationsschlüssel",
"communicationKeyDescription": "Schlüssel, der für die Kommunikation mit dem Client verwendet wird",
"config": "Konfiguration",
"configApp": "App-Konfiguration",
"confirm": "Bestätigen",
"confirmDelete": "Löschen bestätigen",
"create": "Erstellen",
"createApp": "App erstellen",
"createSuccess": "Erfolgreich erstellt",
"defaultVersion": "Standard",
"delete": "Löschen",
"deleteWarning": "Diese Aktion kann nicht rückgängig gemacht werden",
"describeDescription": "Wird verwendet, um die Anwendung zu beschreiben, wird in der App-Liste angezeigt",
"description": "Beschreibung",
"downloadLink": "Download-Link",
"edit": "Bearbeiten",
"editApp": "App bearbeiten",
"encryption": "Verschlüsselungsmethode",
"encryptionDescription": "Wählen Sie die Verschlüsselungsmethode für die Kommunikation mit dem Client. Wenn ausgewählt, wird der Client diese Methode verwenden, um mit dem Server zu kommunizieren.",
"nameDescription": "Anwendungsname, wird in der App-Liste angezeigt",
"platform": "Plattform",
"selectApp": "App auswählen",
"selectAppDescription": "Wählen Sie die App aus, die konfiguriert werden soll. Alle Einstellungen gelten für die ausgewählte App.",
"startupPicture": "Startbild",
"startupPictureDescription": "Startbild, unterstützt Netzwerk- und lokale Bilder. Für Netzwerkbilder bitte die vollständige Bild-URL eingeben",
"startupPicturePreview": "Vorschau des Startbildes",
"startupPictureSkip": "Überspringzeit des Startbildes",
"startupPictureSkipDescription": "Anzeigedauer des Startbildes in Sekunden, 0 eingeben, um nicht anzuzeigen",
"subscriptionProtocol": "Abonnementprotokoll",
"updateSuccess": "Erfolgreich aktualisiert",
"version": "Version"
},
"cancel": "Abbrechen",
"config": {
"singleSubscriptionMode": "Einzelabonnement-Modus",
"subscriptionDomain": "Abonnement-Domain",
"subscriptionDomainDescription": "Wird für Abonnements verwendet; leer lassen, um die Site-Domain zu verwenden",
"subscriptionDomainPlaceholder": "Abonnement-Domain eingeben, eine pro Zeile",
"subscriptionPath": "Abonnement-Pfad",
"subscriptionPathDescription": "Wird für Abonnements verwendet; starten Sie das System nach der Änderung neu, um die optimale Leistung zu gewährleisten",
"subscriptionPathPlaceholder": "Eingeben",
"updateSuccess": "Erfolgreich aktualisiert",
"wildcardResolution": "Wildcard-Auflösung",
"wildcardResolutionDescription": "Wird für Abonnements verwendet"
},
"confirm": "Bestätigen",
"confirmDelete": "Möchten Sie wirklich löschen?",
"copy": "Kopieren",
"copySuccess": "Erfolgreich kopiert",
"create": "Erstellen",
"createSubscribe": "Neues Abonnement erstellen",
"createSuccess": "Erstellung erfolgreich",
"delete": "Löschen",
"deleteSuccess": "Erfolgreich gelöscht",
"deleteWarning": "Nach dem Löschen können die Daten nicht wiederhergestellt werden. Bitte gehen Sie vorsichtig vor.",
"deviceLimit": "Geräteanzahl/Stück",
"edit": "Bearbeiten",
"editSubscribe": "Abonnement bearbeiten",
"form": {
"Day": "Tag",
"Hour": "Stunde",
"Minute": "Minute",
"Month": "Monat",
"NoLimit": "Kein Limit",
"Year": "Jahr",
"annualReset": "Jährliches Zurücksetzen",
"basic": "Grundlegend",
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"deductionRatio": "Automatische/Manuelle Abzugskonfiguration",
"deductionRatioDescription": "Wird für Abzüge verwendet. Standardmäßig verwendet das System einen automatischen Berechnungsalgorithmus. Wenn ein manueller Prozentsatz angegeben wird, berechnet das System die Anteile basierend auf dem Zeit- und Verkehrsverhältnis, wobei sichergestellt wird, dass die Summe 100% ergibt.",
"description": "Beschreibung",
"deviceLimit": "Gerätebeschränkung",
"discount": "Rabatt",
"discountDescription": "Rabatt basierend auf Einzelpreis",
"discountMonths": "Monate",
"discountPercent": "Rabattprozentsatz",
"discount_price": "Rabattpreis",
"duration": "Dauer (Monate)",
"groupId": "Abonnementgruppe",
"inventory": "Abonnementslimit",
"monthlyReset": "Monatliches Zurücksetzen",
"name": "Name",
"noLimit": "Keine Begrenzung",
"noReset": "Kein Zurücksetzen",
"pricing": "Preisgestaltung",
"purchaseWithDiscount": "Abzug erlauben",
"purchaseWithDiscountDescription": "Aktivieren oder deaktivieren Sie die Abmeldefunktion. Nach der Aktivierung führt das System die Abzugsverarbeitung gemäß den konfigurierten Regeln und Anteilen durch, und der verbleibende Wert wird dem Guthaben gutgeschrieben.",
"quota": "Kaufbeschränkung",
"renewalReset": "Zurücksetzen bei Erneuerung",
"renewalResetDescription": "Zurücksetzungszyklus bei Erneuerung",
"replacement": "Ersatzpreis (pro Mal)",
"resetCycle": "Zurücksetzungszyklus",
"resetOn1st": "Zurücksetzen am 1.",
"selectResetCycle": "Bitte wählen Sie einen Zurücksetzungszyklus",
"selectSubscribeGroup": "Bitte Abonnementgruppe auswählen",
"selectUnitTime": "Bitte wählen Sie eine Zeiteinheit",
"server": "Dienst",
"serverGroup": "Dienstgruppe",
"servers": "Server",
"speedLimit": "Geschwindigkeitsbegrenzung ",
"traffic": "Datenvolumen",
"unitPrice": "Einheitspreis",
"unitTime": "Zeiteinheit"
},
"group": {
"actions": "Aktionen",
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"confirmDelete": "Löschen bestätigen?",
"create": "Erstellen",
"createSubscribeGroup": "Neue Abonnementgruppe erstellen",
"createSuccess": "Erstellung erfolgreich",
"delete": "Löschen",
"deleteSuccess": "Erfolgreich gelöscht",
"deleteWarning": "Nach dem Löschen können die Daten nicht wiederhergestellt werden, bitte vorsichtig vorgehen.",
"description": "Beschreibung",
"edit": "Bearbeiten",
"editSubscribeGroup": "Abonnementgruppe bearbeiten",
"form": {
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"description": "Beschreibung",
"name": "Name"
},
"name": "Name",
"title": "Liste der Abonnementgruppen",
"updateSuccess": "Erfolgreich aktualisiert",
"updatedAt": "Aktualisierungszeit"
},
"inventory": "Abonnementslimit",
"name": "Name",
"quota": "Kaufbeschränkung/pro Einkauf",
"replacement": "Preis pro Zurücksetzung",
"sell": "Verkauf",
"show": "Anzeigen",
"sold": "Abonnentenzahl",
"subscribe": "Abonnieren",
"subscribeGroup": "Gruppe abonnieren",
"tabs": {
"subscribe": "Abonnieren",
"subscribeApp": "App-Konfiguration",
"subscribeConfig": "Abonnement-Konfiguration",
"subscribeGroup": "Abonnieren Gruppe"
},
"traffic": "Verkehr",
"unitPrice": "Stückpreis",
"updateSuccess": "Aktualisierung erfolgreich"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Typ",
"updateSuccess": "Erfolgreich aktualisiert",
"updatedAt": "Aktualisierungszeit",
"userAccount": "Benutzerkonto",
"user": "Benutzer",
"userDetail": "Benutzerdetails",
"userId": "Benutzer-ID"
},
+120 -149
View File
@@ -1,161 +1,132 @@
{
"actions": "Aktionen",
"app": {
"appDownloadURL": "App-Download-URL",
"appIcon": "App-Symbol",
"appList": "App-Liste",
"appName": "App-Name",
"backupDomains": "Liste der Backup-Domains",
"backupDomainsDescription": "Liste der Backup-Domains für die Domain-Auflösung, eine Domain pro Zeile",
"batchDelete": "Stapel löschen",
"actions": {
"add": "Hinzufügen",
"batchDelete": "Massenlöschung",
"batchDeleteSuccess": "Erfolgreich {count} Clients gelöscht",
"batchDeleteWarning": "Sind Sie sicher, dass Sie die ausgewählten {count} Clients löschen möchten?",
"cancel": "Abbrechen",
"communicationKey": "Kommunikationsschlüssel",
"communicationKeyDescription": "Schlüssel, der für die Kommunikation mit dem Client verwendet wird",
"config": "Konfiguration",
"configApp": "App-Konfiguration",
"confirm": "Bestätigen",
"confirmDelete": "Löschen bestätigen",
"create": "Erstellen",
"createApp": "App erstellen",
"createSuccess": "Erfolgreich erstellt",
"defaultVersion": "Standard",
"delete": "Löschen",
"deleteWarning": "Diese Aktion kann nicht rückgängig gemacht werden",
"describeDescription": "Wird verwendet, um die Anwendung zu beschreiben, wird in der App-Liste angezeigt",
"description": "Beschreibung",
"downloadLink": "Download-Link",
"edit": "Bearbeiten",
"editApp": "App bearbeiten",
"encryption": "Verschlüsselungsmethode",
"encryptionDescription": "Wählen Sie die Verschlüsselungsmethode für die Kommunikation mit dem Client. Wenn ausgewählt, wird der Client diese Methode verwenden, um mit dem Server zu kommunizieren.",
"nameDescription": "Anwendungsname, wird in der App-Liste angezeigt",
"platform": "Plattform",
"selectApp": "App auswählen",
"selectAppDescription": "Wählen Sie die App aus, die konfiguriert werden soll. Alle Einstellungen gelten für die ausgewählte App.",
"startupPicture": "Startbild",
"startupPictureDescription": "Startbild, unterstützt Netzwerk- und lokale Bilder. Für Netzwerkbilder bitte die vollständige Bild-URL eingeben",
"startupPicturePreview": "Vorschau des Startbildes",
"startupPictureSkip": "Überspringzeit des Startbildes",
"startupPictureSkipDescription": "Anzeigedauer des Startbildes in Sekunden, 0 eingeben, um nicht anzuzeigen",
"subscriptionProtocol": "Abonnementprotokoll",
"updateSuccess": "Erfolgreich aktualisiert",
"version": "Version"
},
"cancel": "Abbrechen",
"config": {
"singleSubscriptionMode": "Einzelabonnement-Modus",
"singleSubscriptionModeDescription": "Wenn aktiviert, werden alle Benutzerabonnements in Guthaben umgewandelt",
"subscriptionDomain": "Abonnement-Domain",
"subscriptionDomainDescription": "Wird für Abonnements verwendet; leer lassen, um die Site-Domain zu verwenden",
"subscriptionDomainPlaceholder": "Abonnement-Domain eingeben, eine pro Zeile",
"subscriptionPath": "Abonnement-Pfad",
"subscriptionPathDescription": "Wird für Abonnements verwendet; starten Sie das System nach der Änderung neu, um die optimale Leistung zu gewährleisten",
"subscriptionPathPlaceholder": "Eingeben",
"updateSuccess": "Erfolgreich aktualisiert",
"wildcardResolution": "Wildcard-Auflösung",
"wildcardResolutionDescription": "Wird für Abonnements verwendet"
},
"confirm": "Bestätigen",
"confirmDelete": "Möchten Sie wirklich löschen?",
"copy": "Kopieren",
"copySuccess": "Erfolgreich kopiert",
"create": "Erstellen",
"createSubscribe": "Neues Abonnement erstellen",
"createSuccess": "Erstellung erfolgreich",
"delete": "Löschen",
"deleteSuccess": "Erfolgreich gelöscht",
"deleteWarning": "Nach dem Löschen können die Daten nicht wiederhergestellt werden. Bitte gehen Sie vorsichtig vor.",
"deviceLimit": "Geräteanzahl/Stück",
"edit": "Bearbeiten",
"editSubscribe": "Abonnement bearbeiten",
"form": {
"Day": "Tag",
"Hour": "Stunde",
"Minute": "Minute",
"Month": "Monat",
"NoLimit": "Kein Limit",
"Year": "Jahr",
"annualReset": "Jährliches Zurücksetzen",
"basic": "Grundlegend",
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"deductionRatio": "Automatische/Manuelle Abzugskonfiguration",
"deductionRatioDescription": "Wird für Abzüge verwendet. Standardmäßig verwendet das System einen automatischen Berechnungsalgorithmus. Wenn ein manueller Prozentsatz angegeben wird, berechnet das System die Anteile basierend auf dem Zeit- und Verkehrsverhältnis, wobei sichergestellt wird, dass die Summe 100% ergibt.",
"description": "Beschreibung",
"deviceLimit": "Gerätebeschränkung",
"discount": "Rabatt",
"discountDescription": "Rabatt basierend auf Einzelpreis",
"discountMonths": "Monate",
"discountPercent": "Rabattprozentsatz",
"discount_price": "Rabattpreis",
"duration": "Dauer (Monate)",
"groupId": "Abonnementgruppe",
"inventory": "Abonnementslimit",
"monthlyReset": "Monatliches Zurücksetzen",
"name": "Name",
"noLimit": "Keine Begrenzung",
"noReset": "Kein Zurücksetzen",
"pricing": "Preisgestaltung",
"purchaseWithDiscount": "Abzug erlauben",
"purchaseWithDiscountDescription": "Aktivieren oder deaktivieren Sie die Abmeldefunktion. Nach der Aktivierung führt das System die Abzugsverarbeitung gemäß den konfigurierten Regeln und Anteilen durch, und der verbleibende Wert wird dem Guthaben gutgeschrieben.",
"quota": "Kaufbeschränkung",
"renewalReset": "Zurücksetzen bei Erneuerung",
"renewalResetDescription": "Zurücksetzungszyklus bei Erneuerung",
"replacement": "Ersatzpreis (pro Mal)",
"resetCycle": "Zurücksetzungszyklus",
"resetOn1st": "Zurücksetzen am 1.",
"selectResetCycle": "Bitte wählen Sie einen Zurücksetzungszyklus",
"selectSubscribeGroup": "Bitte Abonnementgruppe auswählen",
"selectUnitTime": "Bitte wählen Sie eine Zeiteinheit",
"server": "Dienst",
"serverGroup": "Dienstgruppe",
"servers": "Server",
"speedLimit": "Geschwindigkeitsbegrenzung ",
"traffic": "Datenvolumen",
"unitPrice": "Einheitspreis",
"unitTime": "Zeiteinheit"
},
"group": {
"actions": "Aktionen",
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"confirmDelete": "Löschen bestätigen?",
"create": "Erstellen",
"createSubscribeGroup": "Neue Abonnementgruppe erstellen",
"createSuccess": "Erstellung erfolgreich",
"delete": "Löschen",
"deleteFailed": "Löschen fehlgeschlagen",
"deleteSuccess": "Erfolgreich gelöscht",
"deleteWarning": "Nach dem Löschen können die Daten nicht wiederhergestellt werden, bitte vorsichtig vorgehen.",
"description": "Beschreibung",
"deleteWarning": "Diese Aktion kann nicht rückgängig gemacht werden. Sind Sie sicher, dass Sie diesen Client löschen möchten?",
"edit": "Bearbeiten",
"editSubscribeGroup": "Abonnementgruppe bearbeiten",
"form": {
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"description": "Beschreibung",
"name": "Name"
"save": "Speichern",
"saveFailed": "Speichern fehlgeschlagen",
"update": "Aktualisieren",
"updateSuccess": "Erfolgreich aktualisiert"
},
"config": {
"description": "Verwalten Sie die Systemeinstellungen für Abonnements",
"singleSubscriptionMode": "Einzelnes Abonnement",
"singleSubscriptionModeDescription": "Benutzer auf ein aktives Abonnement beschränken. Bestehende Abonnements bleiben unberührt",
"subscriptionDomain": "Abonnement-Domain",
"subscriptionDomainDescription": "Benutzerdefinierte Domain für Abonnement-Links",
"subscriptionDomainPlaceholder": "Geben Sie die Abonnement-Domain ein, eine pro Zeile",
"subscriptionPath": "Abonnement-Pfad",
"subscriptionPathDescription": "Benutzerdefinierter Pfad für Abonnement-Endpunkte (bessere Leistung nach Systemneustart)",
"subscriptionPathPlaceholder": "Geben Sie den Abonnement-Pfad ein",
"title": "Abonnementkonfiguration",
"updateError": "Aktualisierung fehlgeschlagen",
"updateSuccess": "Einstellungen erfolgreich aktualisiert",
"userAgentLimit": "{userAgent} Einschränkung",
"userAgentLimitDescription": "Zugriffsbeschränkungen basierend auf {userAgent} aktivieren",
"userAgentList": "{userAgent} Whitelist",
"userAgentListDescription": "Erlaubte {userAgent} für den Abonnementzugriff, eine pro Zeile. Konfigurierte Anwendung {userAgent} wird automatisch hinzugefügt",
"userAgentListPlaceholder": "Geben Sie erlaubte {userAgent} ein, eine pro Zeile",
"wildcardResolution": "Wildcard-Auflösung",
"wildcardResolutionDescription": "Aktivieren Sie die Wildcard-Domainauflösung für Abonnements"
},
"form": {
"addTitle": "Client hinzufügen",
"descriptions": {
"description": "Detaillierte Clientbeschreibung",
"downloadLink": "Plattform-Download-URL",
"icon": "Icon-URL oder Base64-Codierung",
"name": "Anzeigename des Clients",
"outputFormat": "Format der Abonnementkonfigurationsdatei",
"scheme": {
"base64Encoding": "Base64-Codierung",
"functions": "Unterstützt Funktionen:",
"jsonStringify": "JSON-Objekt in String",
"nameVariable": "Seitenname",
"title": "URL-Schema-Vorlage",
"urlEncoding": "URL-Codierung",
"urlVariable": "Abonnement-URL",
"variables": "Unterstützt Variablen:"
},
"template": {
"description": "Verwenden Sie die Go-Template-Syntax zur Erstellung von Abonnementkonfigurationsdateien",
"functions": "Template-Funktionen:",
"if": "Bedingte Anweisungen",
"nodes": "Proxy-Knotenliste",
"range": "Arrays durchlaufen",
"siteName": "Seitenname",
"sprig": "Sprig-Funktionsbibliothek (Stringverarbeitung, Daten usw.)",
"subscribeName": "Abonnementname",
"title": "Go-Template-Syntax",
"userInfo": "Benutzerinformationen (Verkehr, Ablaufdatum usw.)",
"variables": "Verfügbare Variablen:"
},
"userAgentPrefix": "Client-Identifikator zur Unterscheidung verschiedener Clients"
},
"name": "Name",
"title": "Liste der Abonnementgruppen",
"updateSuccess": "Erfolgreich aktualisiert",
"updatedAt": "Aktualisierungszeit"
"editTitle": "Client bearbeiten",
"fields": {
"description": "Beschreibung",
"icon": "Icon",
"name": "Name",
"outputFormat": "Ausgabeformat",
"scheme": "URL-Schema",
"template": "Abonnementdateivorlage"
},
"tabs": {
"basic": "Basisinformationen",
"download": "Downloads",
"template": "Vorlagen"
},
"validation": {
"nameRequired": "Clientname ist erforderlich",
"userAgentRequiredSuffix": "ist erforderlich"
}
},
"inventory": "Abonnementslimit",
"name": "Name",
"quota": "Kaufbeschränkung/pro Einkauf",
"replacement": "Preis pro Zurücksetzung",
"sell": "Verkauf",
"show": "Anzeigen",
"sold": "Abonnentenzahl",
"subscribe": "Abonnieren",
"subscribeGroup": "Gruppe abonnieren",
"tabs": {
"subscribe": "Abonnieren",
"subscribeApp": "App-Konfiguration",
"subscribeConfig": "Abonnement-Konfiguration",
"subscribeGroup": "Abonnieren Gruppe"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Reiner Text",
"yaml": "YAML"
},
"traffic": "Verkehr",
"unitPrice": "Stückpreis",
"updateSuccess": "Aktualisierung erfolgreich"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Client-Management"
},
"table": {
"columns": {
"default": "Standard",
"description": "Beschreibung",
"name": "Clientname",
"outputFormat": "Ausgabeformat",
"supportedPlatforms": "Unterstützte Plattformen"
}
},
"templatePreview": {
"base64": {
"decodeError": "Dekodierung fehlgeschlagen: Inhalt ist kein gültiges Base64-Format",
"decodedContent": "Dekodierter Inhalt",
"originalContent": "Ursprünglicher Inhalt (Base64)"
},
"failed": "Vorschau fehlgeschlagen",
"loading": "Wird geladen...",
"preview": "Vorschau",
"title": "Vorlagenvorschau"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "Tag(e)",
"defaultSubscribe": "Standardabonnement",
"defaultSubscribeDescription": "Standardabonnement für neue Benutzer",
"description": "Konfigurieren Sie die Einstellungen zur Benutzerregistrierung",
"enableTrial": "Testversion aktivieren",
"enableTrialDescription": "Wenn aktiviert, erhalten neue Benutzer bei der Registrierung ein Testabonnement",
"hour": "Stunde(n)",
"inputPlaceholder": "Bitte eingeben",
"ipRegistrationLimit": "IP-Registrierungsgrenze",
"ipRegistrationLimitDescription": "Begrenzen Sie die Anzahl der Registrierungen von einer einzelnen IP-Adresse",
"minute": "Minute(n)",
"month": "Monat(e)",
"none": "Keine",
"registrationLimitCount": "Registrierungsgrenze",
"registrationLimitCountDescription": "Anzahl der Registrierungen, die pro IP innerhalb des Begrenzungszeitraums erlaubt sind",
"registrationLimitExpire": "Begrenzungszeitraum",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Neue Benutzerregistrierung stoppen",
"stopNewUserRegistrationDescription": "Wenn aktiviert, wird die Registrierung neuer Benutzer deaktiviert",
"title": "Registrierungseinstellungen",
"trialDay": "Testtage",
"trialDayDescription": "Testtage, die neuen Benutzern bei der Registrierung gewährt werden",
"trialFlow": "Testverkehr",
"trialFlowDescription": "Testverkehr, der neuen Benutzern bei der Registrierung gewährt wird"
"trialConfig": "Testkonfiguration",
"trialConfigDescription": "Konfigurieren Sie das Testabonnement, die Dauer und die Zeiteinheit für neue Benutzer bei der Registrierung",
"year": "Jahr(e)"
},
"site": {
"customData": "Benutzerdefinierte Daten",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Additional",
"additionalRecipientEmails": "Additional recipient emails",
"additionalRecipients": "Additional Recipients",
"additionalRecipientsDescription": "These emails will receive the broadcast in addition to the user filter above",
"allUsers": "All Users",
"broadcastList": "Broadcast List",
"broadcastLogs": "Broadcast Logs",
"cancel": "Cancel",
"cannotBeEmpty": "cannot be empty",
"completed": "Completed",
"confirm": "Confirm",
"confirmDelete": "Confirm Delete",
"content": "Email Content",
"create": "Create",
"createBroadcast": "Create Broadcast",
"createNewEmailBroadcastCampaign": "Create new email broadcast campaign",
"createSuccess": "Created Successfully",
"createdAt": "Created At",
"dailyLimit": "Daily limit must be at least 1",
"dailySendLimit": "Daily Send Limit",
"delete": "Delete",
"deleteDescription": "This operation cannot be undone. Are you sure you want to delete?",
"deleteSuccess": "Deleted Successfully",
"edit": "Edit",
"emailAddedToScheduledQueue": "Email added to scheduled send queue",
"emailBroadcast": "Email Broadcast",
"emailBroadcastTaskCreatedSuccessfully": "Email broadcast task created successfully",
"emailBroadcastTasks": "Email Broadcast Tasks",
"emailContent": "Email Content",
"emailInterval": "Email Interval (seconds)",
"emailIntervalMinimum": "Email interval must be at least 0.1 seconds",
"emailMarketing": "Email Marketing",
"emailTaskManager": "Email Task Manager",
"errorMessage": "Error Message",
"estimatedRecipients": "Estimated recipients",
"expiredSubscriptionUsersOnly": "Expired subscription users only",
"expiredUsers": "Expired Users",
"failCount": "Fail Count",
"failed": "Failed",
"failedToRefreshTaskStatus": "Failed to refresh task status",
"failedToStopTask": "Failed to stop task",
"inProgress": "In Progress",
"includeUsersRegisteredAfter": "Include users registered on or after this date",
"includeUsersRegisteredBefore": "Include users registered on or before this date",
"intervalTimeBetweenEmails": "Interval time between each email",
"leaveEmptyForImmediateSend": "Leave empty for immediate send",
"logList": "Log List",
"marketingManagement": "Marketing Management",
"maximumNumberPerDay": "Maximum number of emails to send per day",
"noSubscriptionUsersOnly": "No subscription users only",
"nonSubscribers": "Non-subscribers",
"notStarted": "Not Started",
"onePerLine": "one per line",
"only": "only",
"pending": "Pending",
"pleaseEnter": "Please enter",
"pleaseEnterValidEmailAddresses": "Please enter valid email addresses, one per line",
"processing": "Processing...",
"progress": "Progress",
"recipient": "Recipient",
"recipientEmail": "Recipient Email",
"recipientType": "Recipient Type",
"registrationEndDate": "Registration End Date",
"registrationStartDate": "Registration Start Date",
"scheduleSend": "Schedule Send",
"scheduledSend": "Scheduled Send",
"scheduledSendTimeMustBeLater": "Scheduled send time must be later than current time",
"selectSendScope": "Select send scope",
"selectSendTime": "Select send time, leave empty for immediate send",
"sendFailed": "Send failed, please try again",
"sendNow": "Send Now",
"sendScope": "Send Scope",
"sendScopeDescription": "Choose the user scope for email sending. Select \"Additional emails only\" to send only to the email addresses filled below",
"sendSettings": "Send Settings",
"sendTime": "Send Time",
"sending": "Sending",
"sentAt": "Sent At",
"specificUsers": "Specific Users",
"specificUsersOnly": "Additional emails only (skip platform users)",
"status": "Status",
"stop": "Stop",
"stopped": "Stopped",
"subject": "Email Subject",
"subscribedUsers": "Subscribed Users",
"subscribedUsersOnly": "Subscribed users only",
"successCount": "Success Count",
"taskStatusRefreshed": "Task status refreshed",
"taskStoppedSuccessfully": "Task stopped successfully",
"totalSent": "Total Sent",
"updateSuccess": "Updated Successfully",
"useMarkdownEditor": "Use Markdown editor to write email content with preview functionality",
"users": "users",
"view": "View",
"viewAndManageEmailBroadcastTasks": "View and manage email broadcast tasks",
"viewContent": "View Content"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "ADS Config",
"Announcement Management": "Announcement Management",
"Apple": "Apple ID",
"Application Management": "Application Management",
"Auth Control": "Auth Control",
"Coupon Management": "Coupon Management",
"Dashboard": "Dashboard",
"Device": "Device",
"Document Management": "Document Management",
"Email": "Email",
"Facebook": "Facebook",
"Finance": "Finance",
"General": "General",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Marketing Management",
"Order Management": "Order Management",
"Payment Config": "Payment Config",
"Phone Number": "Phone Number",
"Product Management": "Product Management",
"Protocol Management": "Protocol Management",
"Rule Management": "Rule Management",
"Server": "Server",
"Server Management": "Server Management",
"Settings": "Settings",
"Subscribe Management": "Subscribe Management",
"Subscribe Config": "Subscribe Config",
"System Config": "System Config",
"System Management": "System Management",
"System Tool": "System Tool",
"Telegram": "Telegram",
"Ticket Management": "Ticket Management",
"Twitter": "Twitter",
"User": "User",
"User Detail": "User Detail",
"User Management": "User Management"
+146
View File
@@ -0,0 +1,146 @@
{
"actions": "Actions",
"app": {
"appDownloadURL": "App Download URL",
"appIcon": "App Icon",
"appList": "App List",
"appName": "App Name",
"backupDomains": "Backup Domain List",
"backupDomainsDescription": "Backup domain list for domain resolution, one domain per line",
"batchDelete": "Batch Delete",
"cancel": "Cancel",
"communicationKey": "Communication Key",
"communicationKeyDescription": "Key used for client communication",
"config": "Config",
"configApp": "App Configuration",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"create": "Create",
"createApp": "Create App",
"createSuccess": "Created successfully",
"defaultVersion": "Default",
"delete": "Delete",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"describeDescription": "Used to describe the application, displayed in the app list",
"description": "Description",
"downloadLink": "Download Link",
"edit": "Edit",
"editApp": "Edit App",
"encryption": "Encryption Method",
"encryptionDescription": "Choose the encryption method for client communication. If selected, the client will use this method to communicate with the server",
"nameDescription": "Application name, displayed in the app list",
"platform": "Platform",
"selectApp": "Select App",
"selectAppDescription": "Select the app to configure, all settings will apply to the selected app",
"startupPicture": "Startup Picture",
"startupPictureDescription": "Startup picture, supports network and local images. For network images, please enter the complete image URL",
"startupPicturePreview": "Startup Picture Preview",
"startupPictureSkip": "Startup Picture Skip Time",
"startupPictureSkipDescription": "Startup picture display time in seconds, enter 0 to not display",
"subscriptionProtocol": "Subscription Protocol",
"updateSuccess": "Updated successfully",
"version": "Version"
},
"cancel": "Cancel",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"copy": "Copy",
"copySuccess": "Copied successfully",
"create": "Create",
"createSubscribe": "Create Subscription",
"createSuccess": "Create Successful",
"delete": "Delete",
"deleteSuccess": "Delete Successful",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"deviceLimit": "Device Limit/Unit",
"edit": "Edit",
"editSubscribe": "Edit Subscription",
"form": {
"Day": "Day",
"Hour": "Hour",
"Minute": "Minute",
"Month": "Month",
"NoLimit": "No Limit",
"Year": "Year",
"annualReset": "Annual Reset",
"basic": "Basic",
"cancel": "Cancel",
"confirm": "Confirm",
"deductionRatio": "Automatic/Manual Deduction Configuration",
"deductionRatioDescription": "Used for deduction. By default, the system adopts an automatic calculation algorithm. When a manual ratio is provided, the system calculates proportions based on the time and traffic ratio, ensuring the total equals 100%.",
"description": "Description",
"deviceLimit": "Device Limit",
"discount": "Discount",
"discountDescription": "Set discount based on unit price",
"discountMonths": "Months",
"discountPercent": "Discount Percentage",
"discount_price": "Discount Price",
"duration": "Duration (months)",
"groupId": "Subscription Group",
"inventory": "Subscription Limit",
"monthlyReset": "Monthly Reset",
"name": "Name",
"noLimit": "No Limit",
"noReset": "No Reset",
"pricing": "Pricing",
"purchaseWithDiscount": "Allow Deduction",
"purchaseWithDiscountDescription": "Enable or disable unsubscribe functionality. After activation, the system will perform deduction processing according to the configured rules and proportions, and the remaining value will be returned to the balance",
"quota": "Purchase Limit",
"renewalReset": "Renewal Reset",
"renewalResetDescription": "Reset cycle upon renewal",
"replacement": "Reset Price (per time)",
"resetCycle": "Reset Cycle",
"resetOn1st": "Reset on the 1st",
"selectResetCycle": "Please select a reset cycle",
"selectSubscribeGroup": "Select Subscription Group",
"selectUnitTime": "Please select a unit of time",
"server": "Server",
"serverGroup": "Server Group",
"servers": "Servers",
"speedLimit": "Speed Limit ",
"traffic": "Traffic",
"unitPrice": "Unit Price",
"unitTime": "Unit Time"
},
"group": {
"actions": "Actions",
"cancel": "Cancel",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"create": "Create",
"createSubscribeGroup": "Create Subscription Group",
"createSuccess": "Create Successful",
"delete": "Delete",
"deleteSuccess": "Delete Successful",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"description": "Description",
"edit": "Edit",
"editSubscribeGroup": "Edit Subscription Group",
"form": {
"cancel": "Cancel",
"confirm": "Confirm",
"description": "Description",
"name": "Name"
},
"name": "Name",
"title": "Subscription Group List",
"updateSuccess": "Update Successful",
"updatedAt": "Updated At"
},
"inventory": "Subscription Limit",
"name": "Name",
"quota": "Purchase Limit/Time",
"replacement": "Reset Price/Time",
"sell": "Sell",
"show": "Display",
"sold": "Subscription Count",
"subscribe": "Subscribe",
"subscribeGroup": "Subscription Group",
"tabs": {
"subscribe": "Subscribe",
"subscribeGroup": "Subscription Group"
},
"traffic": "Traffic",
"unitPrice": "Unit Price",
"updateSuccess": "Update Successful"
}
+1 -1
View File
@@ -97,7 +97,7 @@
"type": "Type",
"updateSuccess": "Update successful",
"updatedAt": "Updated At",
"userAccount": "User Account",
"user": "User",
"userDetail": "User Detail",
"userId": "User ID",
"expireTime": "Expire Time"
+112 -141
View File
@@ -1,161 +1,132 @@
{
"actions": "Actions",
"app": {
"appDownloadURL": "App Download URL",
"appIcon": "App Icon",
"appList": "App List",
"appName": "App Name",
"backupDomains": "Backup Domain List",
"backupDomainsDescription": "Backup domain list for domain resolution, one domain per line",
"actions": {
"add": "Add",
"batchDelete": "Batch Delete",
"batchDeleteSuccess": "Successfully deleted {count} clients",
"batchDeleteWarning": "Are you sure you want to delete the selected {count} clients?",
"cancel": "Cancel",
"communicationKey": "Communication Key",
"communicationKeyDescription": "Key used for client communication",
"config": "Config",
"configApp": "App Configuration",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"create": "Create",
"createApp": "Create App",
"confirmDelete": "Confirm Delete",
"createSuccess": "Created successfully",
"defaultVersion": "Default",
"delete": "Delete",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"describeDescription": "Used to describe the application, displayed in the app list",
"description": "Description",
"downloadLink": "Download Link",
"deleteFailed": "Delete failed",
"deleteSuccess": "Deleted successfully",
"deleteWarning": "This operation cannot be undone. Are you sure you want to delete this client?",
"edit": "Edit",
"editApp": "Edit App",
"encryption": "Encryption Method",
"encryptionDescription": "Choose the encryption method for client communication. If selected, the client will use this method to communicate with the server",
"nameDescription": "Application name, displayed in the app list",
"platform": "Platform",
"selectApp": "Select App",
"selectAppDescription": "Select the app to configure, all settings will apply to the selected app",
"startupPicture": "Startup Picture",
"startupPictureDescription": "Startup picture, supports network and local images. For network images, please enter the complete image URL",
"startupPicturePreview": "Startup Picture Preview",
"startupPictureSkip": "Startup Picture Skip Time",
"startupPictureSkipDescription": "Startup picture display time in seconds, enter 0 to not display",
"subscriptionProtocol": "Subscription Protocol",
"updateSuccess": "Updated successfully",
"version": "Version"
"save": "Save",
"saveFailed": "Save failed",
"update": "Update",
"updateSuccess": "Updated successfully"
},
"cancel": "Cancel",
"config": {
"title": "Subscription Configuration",
"description": "Manage subscription system settings",
"singleSubscriptionMode": "Single Subscription Mode",
"singleSubscriptionModeDescription": "When enabled, all user subscriptions will be converted to balance",
"singleSubscriptionModeDescription": "Limit users to one active subscription. Existing subscriptions unaffected",
"subscriptionDomain": "Subscription Domain",
"subscriptionDomainDescription": "Used for subscription; leave blank to use site domain",
"subscriptionDomainDescription": "Custom domain for subscription links",
"subscriptionDomainPlaceholder": "Enter subscription domain, one per line",
"subscriptionPath": "Subscription Path",
"subscriptionPathDescription": "Used for subscription; be sure to restart the system after modification for optimal performance",
"subscriptionPathPlaceholder": "Enter",
"updateSuccess": "Updated successfully",
"subscriptionPathDescription": "Custom path for subscription endpoints (better performance after system restart)",
"subscriptionPathPlaceholder": "Enter subscription path",
"updateError": "Update failed",
"updateSuccess": "Settings updated successfully",
"userAgentLimit": "{userAgent} Restriction",
"userAgentLimitDescription": "Enable access restrictions based on {userAgent}",
"userAgentList": "{userAgent} Whitelist",
"userAgentListDescription": "Allowed {userAgent} for subscription access, one per line. Configured application {userAgent} will be automatically included",
"userAgentListPlaceholder": "Enter allowed {userAgent}, one per line",
"wildcardResolution": "Wildcard Resolution",
"wildcardResolutionDescription": "Used for subscription"
"wildcardResolutionDescription": "Enable wildcard domain resolution for subscriptions"
},
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"copy": "Copy",
"copySuccess": "Copied successfully",
"create": "Create",
"createSubscribe": "Create Subscription",
"createSuccess": "Create Successful",
"delete": "Delete",
"deleteSuccess": "Delete Successful",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"deviceLimit": "Device Limit/Unit",
"edit": "Edit",
"editSubscribe": "Edit Subscription",
"form": {
"Day": "Day",
"Hour": "Hour",
"Minute": "Minute",
"Month": "Month",
"NoLimit": "No Limit",
"Year": "Year",
"annualReset": "Annual Reset",
"basic": "Basic",
"cancel": "Cancel",
"confirm": "Confirm",
"deductionRatio": "Automatic/Manual Deduction Configuration",
"deductionRatioDescription": "Used for deduction. By default, the system adopts an automatic calculation algorithm. When a manual ratio is provided, the system calculates proportions based on the time and traffic ratio, ensuring the total equals 100%.",
"description": "Description",
"deviceLimit": "Device Limit",
"discount": "Discount",
"discountDescription": "Set discount based on unit price",
"discountMonths": "Months",
"discountPercent": "Discount Percentage",
"discount_price": "Discount Price",
"duration": "Duration (months)",
"groupId": "Subscription Group",
"inventory": "Subscription Limit",
"monthlyReset": "Monthly Reset",
"name": "Name",
"noLimit": "No Limit",
"noReset": "No Reset",
"pricing": "Pricing",
"purchaseWithDiscount": "Allow Deduction",
"purchaseWithDiscountDescription": "Enable or disable unsubscribe functionality. After activation, the system will perform deduction processing according to the configured rules and proportions, and the remaining value will be returned to the balance",
"quota": "Purchase Limit",
"renewalReset": "Renewal Reset",
"renewalResetDescription": "Reset cycle upon renewal",
"replacement": "Reset Price (per time)",
"resetCycle": "Reset Cycle",
"resetOn1st": "Reset on the 1st",
"selectResetCycle": "Please select a reset cycle",
"selectSubscribeGroup": "Select Subscription Group",
"selectUnitTime": "Please select a unit of time",
"server": "Server",
"serverGroup": "Server Group",
"servers": "Servers",
"speedLimit": "Speed Limit ",
"traffic": "Traffic",
"unitPrice": "Unit Price",
"unitTime": "Unit Time"
},
"group": {
"actions": "Actions",
"cancel": "Cancel",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"create": "Create",
"createSubscribeGroup": "Create Subscription Group",
"createSuccess": "Create Successful",
"delete": "Delete",
"deleteSuccess": "Delete Successful",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"description": "Description",
"edit": "Edit",
"editSubscribeGroup": "Edit Subscription Group",
"form": {
"cancel": "Cancel",
"confirm": "Confirm",
"description": "Description",
"name": "Name"
"addTitle": "Add Client",
"editTitle": "Edit Client",
"tabs": {
"basic": "Basic Info",
"template": "Templates",
"download": "Downloads"
},
"name": "Name",
"title": "Subscription Group List",
"updateSuccess": "Update Successful",
"updatedAt": "Updated At"
"fields": {
"icon": "Icon",
"name": "Name",
"description": "Description",
"outputFormat": "Output Format",
"scheme": "URL Scheme",
"template": "Subscription File Template"
},
"descriptions": {
"icon": "Icon URL or base64 encoding",
"name": "Client display name",
"userAgentPrefix": "Client identifier for distinguishing different clients",
"description": "Detailed client description",
"outputFormat": "Subscription configuration file format",
"scheme": {
"title": "URL Scheme template",
"variables": "Supports variables:",
"urlVariable": "subscription URL",
"nameVariable": "site name",
"functions": "Supports functions:",
"urlEncoding": "URL encoding",
"base64Encoding": "Base64 encoding",
"jsonStringify": "JSON object to string"
},
"template": {
"title": "Go Template Syntax",
"description": "Use Go template syntax to generate subscription configuration files",
"variables": "Available variables:",
"siteName": "site name",
"subscribeName": "subscription name",
"nodes": "proxy nodes list",
"userInfo": "user info (traffic, expiry, etc.)",
"functions": "Template functions:",
"range": "iterate arrays",
"if": "conditional statements",
"sprig": "Sprig function library (string processing, dates, etc.)"
},
"downloadLink": "platform download URL"
},
"validation": {
"nameRequired": "Client name is required",
"userAgentRequiredSuffix": "is required"
}
},
"inventory": "Subscription Limit",
"name": "Name",
"quota": "Purchase Limit/Time",
"replacement": "Reset Price/Time",
"sell": "Sell",
"show": "Display",
"sold": "Subscription Count",
"subscribe": "Subscribe",
"subscribeGroup": "Subscription Group",
"tabs": {
"subscribe": "Subscribe",
"subscribeApp": "App Configuration",
"subscribeConfig": "Subscription Configuration",
"subscribeGroup": "Subscription Group"
"outputFormats": {
"yaml": "YAML",
"json": "JSON",
"base64": "Base64",
"plain": "Plain Text",
"conf": "CONF"
},
"traffic": "Traffic",
"unitPrice": "Unit Price",
"updateSuccess": "Update Successful"
"platforms": {
"windows": "Windows",
"mac": "macOS",
"linux": "Linux",
"ios": "iOS",
"android": "Android",
"harmony": "HarmonyOS"
},
"protocol": {
"title": "Client Management"
},
"table": {
"columns": {
"default": "Default",
"name": "Client Name",
"description": "Description",
"outputFormat": "Output Format",
"supportedPlatforms": "Supported Platforms"
}
},
"templatePreview": {
"title": "Template Preview",
"preview": "Preview",
"loading": "Loading...",
"failed": "Preview failed",
"base64": {
"originalContent": "Original Content (Base64)",
"decodedContent": "Decoded Content",
"decodeError": "Decode failed: Content is not valid Base64 format"
}
}
}
+11 -8
View File
@@ -47,16 +47,19 @@
"registrationLimitCount": "Registration Limit Count",
"registrationLimitCountDescription": "Number of registrations allowed per IP within the limit period",
"registrationLimitExpire": "Limit Period",
"registrationLimitExpireDescription": "Duration for IP registration limit",
"trialFlow": "Trial Traffic",
"trialFlowDescription": "Trial traffic given to new users upon registration",
"trialDay": "Trial Days",
"trialDayDescription": "Trial days given to new users upon registration",
"defaultSubscribe": "Default Subscription",
"defaultSubscribeDescription": "Default subscription plan for new users",
"registrationLimitExpireDescription": "Duration for IP registration limit (minutes)",
"enableTrial": "Enable Trial",
"enableTrialDescription": "When enabled, new users will receive a trial subscription upon registration",
"trialConfig": "Trial Configuration",
"trialConfigDescription": "Configure trial subscription, duration and time unit for new users upon registration",
"inputPlaceholder": "Please enter",
"selectPlaceholder": "Please select",
"day": "day(s)",
"none": "None",
"year": "Year(s)",
"month": "Month(s)",
"day": "Day(s)",
"hour": "Hour(s)",
"minute": "Minute(s)",
"saveSuccess": "Save Successful",
"saveFailed": "Save Failed"
},
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Adicional",
"additionalRecipientEmails": "Correos electrónicos de destinatarios adicionales",
"additionalRecipients": "Destinatarios adicionales",
"additionalRecipientsDescription": "Estos correos electrónicos recibirán la transmisión además del filtro de usuario anterior",
"allUsers": "Todos los usuarios",
"broadcastList": "Lista de difusión",
"broadcastLogs": "Registros de difusión",
"cancel": "Cancelar",
"cannotBeEmpty": "no puede estar vacío",
"completed": "Completado",
"confirm": "Confirmar",
"confirmDelete": "Confirmar eliminación",
"content": "Contenido del correo electrónico",
"create": "Crear",
"createBroadcast": "Crear difusión",
"createNewEmailBroadcastCampaign": "Crear nueva campaña de difusión por correo electrónico",
"createSuccess": "Creado con éxito",
"createdAt": "Creado en",
"dailyLimit": "El límite diario debe ser al menos 1",
"dailySendLimit": "Límite de envío diario",
"delete": "Eliminar",
"deleteDescription": "Esta operación no se puede deshacer. ¿Está seguro de que desea eliminar?",
"deleteSuccess": "Eliminado con éxito",
"edit": "Editar",
"emailAddedToScheduledQueue": "Correo electrónico añadido a la cola de envío programado",
"emailBroadcast": "Difusión por correo electrónico",
"emailBroadcastTaskCreatedSuccessfully": "Tarea de difusión por correo electrónico creada con éxito",
"emailBroadcastTasks": "Tareas de difusión por correo electrónico",
"emailContent": "Contenido del correo electrónico",
"emailInterval": "Intervalo de correo electrónico (segundos)",
"emailIntervalMinimum": "El intervalo de correo electrónico debe ser al menos 0.1 segundos",
"emailMarketing": "Marketing por correo electrónico",
"emailTaskManager": "Administrador de tareas de correo electrónico",
"errorMessage": "Mensaje de error",
"estimatedRecipients": "Destinatarios estimados",
"expiredSubscriptionUsersOnly": "Solo usuarios con suscripción expirada",
"expiredUsers": "Usuarios expirados",
"failCount": "Conteo de fallos",
"failed": "Fallido",
"failedToRefreshTaskStatus": "Error al actualizar el estado de la tarea",
"failedToStopTask": "Error al detener la tarea",
"inProgress": "En progreso",
"includeUsersRegisteredAfter": "Incluir usuarios registrados en o después de esta fecha",
"includeUsersRegisteredBefore": "Incluir usuarios registrados en o antes de esta fecha",
"intervalTimeBetweenEmails": "Tiempo de intervalo entre cada correo electrónico",
"leaveEmptyForImmediateSend": "Dejar vacío para envío inmediato",
"logList": "Lista de registros",
"marketingManagement": "Gestión de marketing",
"maximumNumberPerDay": "Número máximo de correos electrónicos a enviar por día",
"noSubscriptionUsersOnly": "Solo usuarios sin suscripción",
"nonSubscribers": "No suscriptores",
"notStarted": "No iniciado",
"onePerLine": "uno por línea",
"only": "solo",
"pending": "Pendiente",
"pleaseEnter": "Por favor ingrese",
"pleaseEnterValidEmailAddresses": "Por favor ingrese direcciones de correo electrónico válidas, una por línea",
"processing": "Procesando...",
"progress": "Progreso",
"recipient": "Destinatario",
"recipientEmail": "Correo electrónico del destinatario",
"recipientType": "Tipo de destinatario",
"registrationEndDate": "Fecha de finalización de registro",
"registrationStartDate": "Fecha de inicio de registro",
"scheduleSend": "Programar envío",
"scheduledSend": "Envío programado",
"scheduledSendTimeMustBeLater": "La hora de envío programado debe ser posterior a la hora actual",
"selectSendScope": "Seleccionar alcance de envío",
"selectSendTime": "Seleccionar hora de envío, dejar vacío para envío inmediato",
"sendFailed": "Envío fallido, por favor intente de nuevo",
"sendNow": "Enviar ahora",
"sendScope": "Alcance de envío",
"sendScopeDescription": "Elija el alcance de usuarios para el envío de correos electrónicos. Seleccione \"Solo correos electrónicos adicionales\" para enviar solo a las direcciones de correo electrónico completadas a continuación",
"sendSettings": "Configuraciones de envío",
"sendTime": "Hora de envío",
"sending": "Enviando",
"sentAt": "Enviado en",
"specificUsers": "Usuarios específicos",
"specificUsersOnly": "Solo correos electrónicos adicionales (omitir usuarios de la plataforma)",
"status": "Estado",
"stop": "Detener",
"stopped": "Detenido",
"subject": "Asunto del correo electrónico",
"subscribedUsers": "Usuarios suscritos",
"subscribedUsersOnly": "Solo usuarios suscritos",
"successCount": "Conteo de éxitos",
"taskStatusRefreshed": "Estado de la tarea actualizado",
"taskStoppedSuccessfully": "Tarea detenida con éxito",
"totalSent": "Total enviado",
"updateSuccess": "Actualizado con éxito",
"useMarkdownEditor": "Utilice el editor Markdown para escribir el contenido del correo electrónico con funcionalidad de vista previa",
"users": "usuarios",
"view": "Ver",
"viewAndManageEmailBroadcastTasks": "Ver y gestionar tareas de difusión por correo electrónico",
"viewContent": "Ver contenido"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "Configuración de ADS",
"Announcement Management": "Gestión de Anuncios",
"Apple": "ID de Apple",
"Application Management": "Gestión de Aplicaciones",
"Auth Control": "Control de Autenticación",
"Coupon Management": "Gestión de Cupones",
"Dashboard": "Tablero",
"Device": "Dispositivo",
"Document Management": "Gestión de Documentos",
"Email": "Correo electrónico",
"Facebook": "Facebook",
"Finance": "Finanzas",
"General": "General",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Gestión de Marketing",
"Order Management": "Gestión de Pedidos",
"Payment Config": "Configuración de Pago",
"Phone Number": "Número de Teléfono",
"Product Management": "Gestión de Productos",
"Protocol Management": "Gestión de Protocolos",
"Rule Management": "Gestión de Reglas",
"Server": "Servidor",
"Server Management": "Gestión de Servidores",
"Settings": "Configuración",
"Subscribe Management": "Gestión de Suscripciones",
"Subscribe Config": "Configuración de Suscripción",
"System Config": "Configuración del sistema",
"System Management": "Gestión del Sistema",
"System Tool": "Herramienta del sistema",
"Telegram": "Telegram",
"Ticket Management": "Gestión de Tickets",
"Twitter": "Twitter",
"User": "Usuario",
"User Detail": "Detalle del Usuario",
"User Management": "Gestión de Usuarios"
+161
View File
@@ -0,0 +1,161 @@
{
"actions": "acciones",
"app": {
"appDownloadURL": "URL de Descarga de la App",
"appIcon": "Icono de la App",
"appList": "Lista de Aplicaciones",
"appName": "Nombre de la App",
"backupDomains": "Lista de Dominios de Respaldo",
"backupDomainsDescription": "Lista de dominios de respaldo para la resolución de dominios, un dominio por línea",
"batchDelete": "Eliminar en Lote",
"cancel": "Cancelar",
"communicationKey": "Clave de comunicación",
"communicationKeyDescription": "Clave utilizada para la comunicación del cliente",
"config": "Configuración",
"configApp": "Configuración de la Aplicación",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"create": "Crear",
"createApp": "Crear App",
"createSuccess": "Creado con éxito",
"defaultVersion": "Versión Predeterminada",
"delete": "Eliminar",
"deleteWarning": "Esta acción no se puede deshacer",
"describeDescription": "Se utiliza para describir la aplicación, se muestra en la lista de aplicaciones",
"description": "Descripción",
"downloadLink": "Enlace de Descarga",
"edit": "Editar",
"editApp": "Editar App",
"encryption": "Método de encriptación",
"encryptionDescription": "Elija el método de encriptación para la comunicación del cliente. Si se selecciona, el cliente utilizará este método para comunicarse con el servidor",
"nameDescription": "Nombre de la aplicación, se muestra en la lista de aplicaciones",
"platform": "Plataforma",
"selectApp": "Seleccionar aplicación",
"selectAppDescription": "Seleccione la aplicación para configurar, todos los ajustes se aplicarán a la aplicación seleccionada",
"startupPicture": "Imagen de Inicio",
"startupPictureDescription": "Imagen de inicio, admite imágenes de red y locales. Para imágenes de red, ingrese la URL completa de la imagen",
"startupPicturePreview": "Vista Previa de la Imagen de Inicio",
"startupPictureSkip": "Tiempo de Salto de la Imagen de Inicio",
"startupPictureSkipDescription": "Tiempo de visualización de la imagen de inicio en segundos, ingrese 0 para no mostrar",
"subscriptionProtocol": "Protocolo de Suscripción",
"updateSuccess": "Actualizado con éxito",
"version": "Versión"
},
"cancel": "Cancelar",
"config": {
"singleSubscriptionMode": "Modo de Suscripción Única",
"singleSubscriptionModeDescription": "Cuando está habilitado, todas las suscripciones de usuario se convertirán en saldo",
"subscriptionDomain": "Dominio de Suscripción",
"subscriptionDomainDescription": "Usado para suscripción; dejar en blanco para usar el dominio del sitio",
"subscriptionDomainPlaceholder": "Ingrese el dominio de suscripción, uno por línea",
"subscriptionPath": "Ruta de Suscripción",
"subscriptionPathDescription": "Usado para suscripción; asegúrese de reiniciar el sistema después de la modificación para un rendimiento óptimo",
"subscriptionPathPlaceholder": "Ingrese",
"updateSuccess": "Actualizado con éxito",
"wildcardResolution": "Resolución de Comodín",
"wildcardResolutionDescription": "Usado para suscripción"
},
"confirm": "Confirmar",
"confirmDelete": "¿Estás seguro de que deseas eliminar?",
"copy": "Copiar",
"copySuccess": "Copiado con éxito",
"create": "Crear",
"createSubscribe": "Crear suscripción",
"createSuccess": "Creación exitosa",
"delete": "eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Después de eliminar, los datos no se podrán recuperar. Proceda con precaución.",
"deviceLimit": "Número de dispositivos/unidad",
"edit": "editar",
"editSubscribe": "Editar suscripción",
"form": {
"Day": "Día",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"NoLimit": "Sin Límite",
"Year": "Año",
"annualReset": "Reinicio Anual",
"basic": "Básico",
"cancel": "Cancelar",
"confirm": "Confirmar",
"deductionRatio": "Configuración de Deducción Automática/Manual",
"deductionRatioDescription": "Utilizado para deducciones. Por defecto, el sistema adopta un algoritmo de cálculo automático. Cuando se proporciona un ratio manual, el sistema calcula proporciones basadas en el tiempo y el ratio de tráfico, asegurando que el total sea igual al 100%.",
"description": "Descripción",
"deviceLimit": "Límite de dispositivos",
"discount": "Descuento",
"discountDescription": "Descuento basado en el precio unitario",
"discountMonths": "Meses",
"discountPercent": "Porcentaje de descuento",
"discount_price": "Precio con descuento",
"duration": "Duración (meses)",
"groupId": "Grupo de Suscripción",
"inventory": "Límite de suscripción",
"monthlyReset": "Reinicio Mensual",
"name": "Nombre",
"noLimit": "Sin límite",
"noReset": "Sin Reinicio",
"pricing": "Precios",
"purchaseWithDiscount": "Permitir Deducción",
"purchaseWithDiscountDescription": "Habilitar o deshabilitar la funcionalidad de cancelación de suscripción. Después de la activación, el sistema realizará el procesamiento de deducción según las reglas y proporciones configuradas, y el valor restante se devolverá al saldo",
"quota": "Cantidad de compra limitada",
"renewalReset": "Reinicio por Renovación",
"renewalResetDescription": "Reiniciar ciclo al renovar",
"replacement": "Precio de reposición (cada vez)",
"resetCycle": "Ciclo de Reinicio",
"resetOn1st": "Reiniciar el día 1",
"selectResetCycle": "Por favor, seleccione un ciclo de reinicio",
"selectSubscribeGroup": "Por favor, seleccione un grupo de suscripción",
"selectUnitTime": "Por favor, seleccione la unidad de tiempo",
"server": "Servidor",
"serverGroup": "Grupo de servidores",
"servers": "Servidores",
"speedLimit": "Límite de velocidad ",
"traffic": "Tráfico",
"unitPrice": "Precio unitario",
"unitTime": "Unidad de tiempo"
},
"group": {
"actions": "Acciones",
"cancel": "Cancelar",
"confirm": "Confirmar",
"confirmDelete": "¿Confirmar eliminación?",
"create": "Crear",
"createSubscribeGroup": "Crear nuevo grupo de suscripción",
"createSuccess": "Creación exitosa",
"delete": "Eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Los datos no se pueden recuperar después de la eliminación, por favor opere con precaución.",
"description": "Descripción",
"edit": "Editar",
"editSubscribeGroup": "Editar grupo de suscripción",
"form": {
"cancel": "Cancelar",
"confirm": "Confirmar",
"description": "Descripción",
"name": "Nombre"
},
"name": "Nombre",
"title": "Lista de grupos de suscripción",
"updateSuccess": "Actualización exitosa",
"updatedAt": "Fecha de actualización"
},
"inventory": "Límite de suscripción",
"name": "Nombre",
"quota": "Límite de compra/vez",
"replacement": "Restablecer precio/vez",
"sell": "Venta",
"show": "Mostrar",
"sold": "Conteo de Suscripciones",
"subscribe": "Suscribirse",
"subscribeGroup": "Suscribirse al grupo",
"tabs": {
"subscribe": "Suscribirse",
"subscribeApp": "Configuración de la aplicación",
"subscribeConfig": "Configuración de suscripción",
"subscribeGroup": "Grupo de suscripción"
},
"traffic": "tráfico",
"unitPrice": "Precio Unitario",
"updateSuccess": "Actualización exitosa"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Tipo",
"updateSuccess": "Actualización exitosa",
"updatedAt": "Fecha de actualización",
"userAccount": "Cuenta de Usuario",
"user": "Usuario",
"userDetail": "Detalle del Usuario",
"userId": "ID de Usuario"
},
+114 -143
View File
@@ -1,161 +1,132 @@
{
"actions": "acciones",
"app": {
"appDownloadURL": "URL de Descarga de la App",
"appIcon": "Icono de la App",
"appList": "Lista de Aplicaciones",
"appName": "Nombre de la App",
"backupDomains": "Lista de Dominios de Respaldo",
"backupDomainsDescription": "Lista de dominios de respaldo para la resolución de dominios, un dominio por línea",
"batchDelete": "Eliminar en Lote",
"actions": {
"add": "Agregar",
"batchDelete": "Eliminar en lote",
"batchDeleteSuccess": "Se eliminaron correctamente {count} clientes",
"batchDeleteWarning": "¿Está seguro de que desea eliminar los {count} clientes seleccionados?",
"cancel": "Cancelar",
"communicationKey": "Clave de comunicación",
"communicationKeyDescription": "Clave utilizada para la comunicación del cliente",
"config": "Configuración",
"configApp": "Configuración de la Aplicación",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"create": "Crear",
"createApp": "Crear App",
"confirmDelete": "Confirmar eliminación",
"createSuccess": "Creado con éxito",
"defaultVersion": "Versión Predeterminada",
"delete": "Eliminar",
"deleteWarning": "Esta acción no se puede deshacer",
"describeDescription": "Se utiliza para describir la aplicación, se muestra en la lista de aplicaciones",
"description": "Descripción",
"downloadLink": "Enlace de Descarga",
"deleteFailed": "Error al eliminar",
"deleteSuccess": "Eliminado con éxito",
"deleteWarning": "Esta operación no se puede deshacer. ¿Está seguro de que desea eliminar este cliente?",
"edit": "Editar",
"editApp": "Editar App",
"encryption": "Método de encriptación",
"encryptionDescription": "Elija el método de encriptación para la comunicación del cliente. Si se selecciona, el cliente utilizará este método para comunicarse con el servidor",
"nameDescription": "Nombre de la aplicación, se muestra en la lista de aplicaciones",
"platform": "Plataforma",
"selectApp": "Seleccionar aplicación",
"selectAppDescription": "Seleccione la aplicación para configurar, todos los ajustes se aplicarán a la aplicación seleccionada",
"startupPicture": "Imagen de Inicio",
"startupPictureDescription": "Imagen de inicio, admite imágenes de red y locales. Para imágenes de red, ingrese la URL completa de la imagen",
"startupPicturePreview": "Vista Previa de la Imagen de Inicio",
"startupPictureSkip": "Tiempo de Salto de la Imagen de Inicio",
"startupPictureSkipDescription": "Tiempo de visualización de la imagen de inicio en segundos, ingrese 0 para no mostrar",
"subscriptionProtocol": "Protocolo de Suscripción",
"updateSuccess": "Actualizado con éxito",
"version": "Versión"
"save": "Guardar",
"saveFailed": "Error al guardar",
"update": "Actualizar",
"updateSuccess": "Actualizado con éxito"
},
"cancel": "Cancelar",
"config": {
"description": "Gestionar la configuración del sistema de suscripción",
"singleSubscriptionMode": "Modo de Suscripción Única",
"singleSubscriptionModeDescription": "Cuando está habilitado, todas las suscripciones de usuario se convertirán en saldo",
"singleSubscriptionModeDescription": "Limitar a los usuarios a una suscripción activa. Las suscripciones existentes no se ven afectadas",
"subscriptionDomain": "Dominio de Suscripción",
"subscriptionDomainDescription": "Usado para suscripción; dejar en blanco para usar el dominio del sitio",
"subscriptionDomainDescription": "Dominio personalizado para enlaces de suscripción",
"subscriptionDomainPlaceholder": "Ingrese el dominio de suscripción, uno por línea",
"subscriptionPath": "Ruta de Suscripción",
"subscriptionPathDescription": "Usado para suscripción; asegúrese de reiniciar el sistema después de la modificación para un rendimiento óptimo",
"subscriptionPathPlaceholder": "Ingrese",
"updateSuccess": "Actualizado con éxito",
"wildcardResolution": "Resolución de Comodín",
"wildcardResolutionDescription": "Usado para suscripción"
"subscriptionPathDescription": "Ruta personalizada para los puntos finales de suscripción (mejor rendimiento después del reinicio del sistema)",
"subscriptionPathPlaceholder": "Ingrese la ruta de suscripción",
"title": "Configuración de Suscripción",
"updateError": "Error al actualizar",
"updateSuccess": "Configuraciones actualizadas con éxito",
"userAgentLimit": "Restricción de {userAgent}",
"userAgentLimitDescription": "Habilitar restricciones de acceso basadas en {userAgent}",
"userAgentList": "Lista blanca de {userAgent}",
"userAgentListDescription": "Permitir {userAgent} para acceso a suscripción, uno por línea. La aplicación configurada {userAgent} se incluirá automáticamente",
"userAgentListPlaceholder": "Ingrese {userAgent} permitidos, uno por línea",
"wildcardResolution": "Resolución de comodines",
"wildcardResolutionDescription": "Habilitar resolución de dominio comodín para suscripciones"
},
"confirm": "Confirmar",
"confirmDelete": "¿Estás seguro de que deseas eliminar?",
"copy": "Copiar",
"copySuccess": "Copiado con éxito",
"create": "Crear",
"createSubscribe": "Crear suscripción",
"createSuccess": "Creación exitosa",
"delete": "eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Después de eliminar, los datos no se podrán recuperar. Proceda con precaución.",
"deviceLimit": "Número de dispositivos/unidad",
"edit": "editar",
"editSubscribe": "Editar suscripción",
"form": {
"Day": "Día",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"NoLimit": "Sin Límite",
"Year": "Año",
"annualReset": "Reinicio Anual",
"basic": "Básico",
"cancel": "Cancelar",
"confirm": "Confirmar",
"deductionRatio": "Configuración de Deducción Automática/Manual",
"deductionRatioDescription": "Utilizado para deducciones. Por defecto, el sistema adopta un algoritmo de cálculo automático. Cuando se proporciona un ratio manual, el sistema calcula proporciones basadas en el tiempo y el ratio de tráfico, asegurando que el total sea igual al 100%.",
"description": "Descripción",
"deviceLimit": "Límite de dispositivos",
"discount": "Descuento",
"discountDescription": "Descuento basado en el precio unitario",
"discountMonths": "Meses",
"discountPercent": "Porcentaje de descuento",
"discount_price": "Precio con descuento",
"duration": "Duración (meses)",
"groupId": "Grupo de Suscripción",
"inventory": "Límite de suscripción",
"monthlyReset": "Reinicio Mensual",
"name": "Nombre",
"noLimit": "Sin límite",
"noReset": "Sin Reinicio",
"pricing": "Precios",
"purchaseWithDiscount": "Permitir Deducción",
"purchaseWithDiscountDescription": "Habilitar o deshabilitar la funcionalidad de cancelación de suscripción. Después de la activación, el sistema realizará el procesamiento de deducción según las reglas y proporciones configuradas, y el valor restante se devolverá al saldo",
"quota": "Cantidad de compra limitada",
"renewalReset": "Reinicio por Renovación",
"renewalResetDescription": "Reiniciar ciclo al renovar",
"replacement": "Precio de reposición (cada vez)",
"resetCycle": "Ciclo de Reinicio",
"resetOn1st": "Reiniciar el día 1",
"selectResetCycle": "Por favor, seleccione un ciclo de reinicio",
"selectSubscribeGroup": "Por favor, seleccione un grupo de suscripción",
"selectUnitTime": "Por favor, seleccione la unidad de tiempo",
"server": "Servidor",
"serverGroup": "Grupo de servidores",
"servers": "Servidores",
"speedLimit": "Límite de velocidad ",
"traffic": "Tráfico",
"unitPrice": "Precio unitario",
"unitTime": "Unidad de tiempo"
},
"group": {
"actions": "Acciones",
"cancel": "Cancelar",
"confirm": "Confirmar",
"confirmDelete": "¿Confirmar eliminación?",
"create": "Crear",
"createSubscribeGroup": "Crear nuevo grupo de suscripción",
"createSuccess": "Creación exitosa",
"delete": "Eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Los datos no se pueden recuperar después de la eliminación, por favor opere con precaución.",
"description": "Descripción",
"edit": "Editar",
"editSubscribeGroup": "Editar grupo de suscripción",
"form": {
"cancel": "Cancelar",
"confirm": "Confirmar",
"description": "Descripción",
"name": "Nombre"
"addTitle": "Agregar Cliente",
"descriptions": {
"description": "Descripción detallada del cliente",
"downloadLink": "URL de descarga de la plataforma",
"icon": "URL del ícono o codificación base64",
"name": "Nombre para mostrar del cliente",
"outputFormat": "Formato del archivo de configuración de suscripción",
"scheme": {
"base64Encoding": "Codificación Base64",
"functions": "Soporta funciones:",
"jsonStringify": "Objeto JSON a cadena",
"nameVariable": "nombre del sitio",
"title": "Plantilla de esquema de URL",
"urlEncoding": "Codificación de URL",
"urlVariable": "URL de suscripción",
"variables": "Soporta variables:"
},
"template": {
"description": "Utilizar la sintaxis de plantilla Go para generar archivos de configuración de suscripción",
"functions": "Funciones de plantilla:",
"if": "declaraciones condicionales",
"nodes": "lista de nodos proxy",
"range": "iterar arreglos",
"siteName": "nombre del sitio",
"sprig": "Biblioteca de funciones Sprig (procesamiento de cadenas, fechas, etc.)",
"subscribeName": "nombre de la suscripción",
"title": "Sintaxis de Plantilla Go",
"userInfo": "información del usuario (tráfico, expiración, etc.)",
"variables": "Variables disponibles:"
},
"userAgentPrefix": "Identificador del cliente para distinguir diferentes clientes"
},
"name": "Nombre",
"title": "Lista de grupos de suscripción",
"updateSuccess": "Actualización exitosa",
"updatedAt": "Fecha de actualización"
"editTitle": "Editar Cliente",
"fields": {
"description": "Descripción",
"icon": "Ícono",
"name": "Nombre",
"outputFormat": "Formato de Salida",
"scheme": "Esquema de URL",
"template": "Plantilla de Archivo de Suscripción"
},
"tabs": {
"basic": "Información Básica",
"download": "Descargas",
"template": "Plantillas"
},
"validation": {
"nameRequired": "Se requiere el nombre del cliente",
"userAgentRequiredSuffix": "es requerido"
}
},
"inventory": "Límite de suscripción",
"name": "Nombre",
"quota": "Límite de compra/vez",
"replacement": "Restablecer precio/vez",
"sell": "Venta",
"show": "Mostrar",
"sold": "Conteo de Suscripciones",
"subscribe": "Suscribirse",
"subscribeGroup": "Suscribirse al grupo",
"tabs": {
"subscribe": "Suscribirse",
"subscribeApp": "Configuración de la aplicación",
"subscribeConfig": "Configuración de suscripción",
"subscribeGroup": "Grupo de suscripción"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Texto Plano",
"yaml": "YAML"
},
"traffic": "tráfico",
"unitPrice": "Precio Unitario",
"updateSuccess": "Actualización exitosa"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Gestión de Clientes"
},
"table": {
"columns": {
"default": "Predeterminado",
"description": "Descripción",
"name": "Nombre del Cliente",
"outputFormat": "Formato de Salida",
"supportedPlatforms": "Plataformas Soportadas"
}
},
"templatePreview": {
"base64": {
"decodeError": "Error de decodificación: El contenido no es un formato Base64 válido",
"decodedContent": "Contenido decodificado",
"originalContent": "Contenido original (Base64)"
},
"failed": "La vista previa ha fallado",
"loading": "Cargando...",
"preview": "Vista previa",
"title": "Vista previa de la plantilla"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "día(s)",
"defaultSubscribe": "Suscripción Predeterminada",
"defaultSubscribeDescription": "Plan de suscripción predeterminado para nuevos usuarios",
"description": "Configurar ajustes relacionados con el registro de usuarios",
"enableTrial": "Habilitar Prueba",
"enableTrialDescription": "Cuando está habilitado, los nuevos usuarios recibirán una suscripción de prueba al registrarse",
"hour": "Hora(s)",
"inputPlaceholder": "Por favor ingrese",
"ipRegistrationLimit": "Límite de Registro por IP",
"ipRegistrationLimitDescription": "Limitar el número de registros desde una sola dirección IP",
"minute": "Minuto(s)",
"month": "Mes(es)",
"none": "Ninguno",
"registrationLimitCount": "Conteo de Límite de Registro",
"registrationLimitCountDescription": "Número de registros permitidos por IP dentro del período límite",
"registrationLimitExpire": "Período de Límite",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Detener Registro de Nuevos Usuarios",
"stopNewUserRegistrationDescription": "Cuando está habilitado, el registro de nuevos usuarios estará deshabilitado",
"title": "Configuración de Registro",
"trialDay": "Días de Prueba",
"trialDayDescription": "Días de prueba otorgados a nuevos usuarios al registrarse",
"trialFlow": "Tráfico de Prueba",
"trialFlowDescription": "Tráfico de prueba otorgado a nuevos usuarios al registrarse"
"trialConfig": "Configuración de Prueba",
"trialConfigDescription": "Configurar la suscripción de prueba, duración y unidad de tiempo para nuevos usuarios al registrarse",
"year": "Año(s)"
},
"site": {
"customData": "Datos Personalizados",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Adicional",
"additionalRecipientEmails": "Correos electrónicos de destinatarios adicionales",
"additionalRecipients": "Destinatarios Adicionales",
"additionalRecipientsDescription": "Estos correos electrónicos recibirán la transmisión además del filtro de usuario anterior",
"allUsers": "Todos los Usuarios",
"broadcastList": "Lista de Transmisión",
"broadcastLogs": "Registros de Transmisión",
"cancel": "Cancelar",
"cannotBeEmpty": "no puede estar vacío",
"completed": "Completado",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"content": "Contenido del Correo Electrónico",
"create": "Crear",
"createBroadcast": "Crear Transmisión",
"createNewEmailBroadcastCampaign": "Crear nueva campaña de transmisión de correo electrónico",
"createSuccess": "Creado Exitosamente",
"createdAt": "Creado En",
"dailyLimit": "El límite diario debe ser al menos 1",
"dailySendLimit": "Límite de Envío Diario",
"delete": "Eliminar",
"deleteDescription": "Esta operación no se puede deshacer. ¿Está seguro de que desea eliminar?",
"deleteSuccess": "Eliminado Exitosamente",
"edit": "Editar",
"emailAddedToScheduledQueue": "Correo electrónico agregado a la cola de envío programado",
"emailBroadcast": "Transmisión de Correo Electrónico",
"emailBroadcastTaskCreatedSuccessfully": "Tarea de transmisión de correo electrónico creada exitosamente",
"emailBroadcastTasks": "Tareas de Transmisión de Correo Electrónico",
"emailContent": "Contenido del Correo Electrónico",
"emailInterval": "Intervalo de Correo Electrónico (segundos)",
"emailIntervalMinimum": "El intervalo de correo electrónico debe ser al menos 0.1 segundos",
"emailMarketing": "Marketing por Correo Electrónico",
"emailTaskManager": "Administrador de Tareas de Correo Electrónico",
"errorMessage": "Mensaje de Error",
"estimatedRecipients": "Destinatarios Estimados",
"expiredSubscriptionUsersOnly": "Solo usuarios con suscripción expirada",
"expiredUsers": "Usuarios Expirados",
"failCount": "Conteo de Fallos",
"failed": "Fallido",
"failedToRefreshTaskStatus": "Error al actualizar el estado de la tarea",
"failedToStopTask": "Error al detener la tarea",
"inProgress": "En Progreso",
"includeUsersRegisteredAfter": "Incluir usuarios registrados en o después de esta fecha",
"includeUsersRegisteredBefore": "Incluir usuarios registrados en o antes de esta fecha",
"intervalTimeBetweenEmails": "Tiempo de intervalo entre cada correo electrónico",
"leaveEmptyForImmediateSend": "Deje vacío para envío inmediato",
"logList": "Lista de Registros",
"marketingManagement": "Gestión de Marketing",
"maximumNumberPerDay": "Número máximo de correos electrónicos a enviar por día",
"noSubscriptionUsersOnly": "Solo usuarios sin suscripción",
"nonSubscribers": "No suscriptores",
"notStarted": "No Iniciado",
"onePerLine": "uno por línea",
"only": "solo",
"pending": "Pendiente",
"pleaseEnter": "Por favor ingrese",
"pleaseEnterValidEmailAddresses": "Por favor ingrese direcciones de correo electrónico válidas, una por línea",
"processing": "Procesando...",
"progress": "Progreso",
"recipient": "Destinatario",
"recipientEmail": "Correo Electrónico del Destinatario",
"recipientType": "Tipo de Destinatario",
"registrationEndDate": "Fecha de Fin de Registro",
"registrationStartDate": "Fecha de Inicio de Registro",
"scheduleSend": "Programar Envío",
"scheduledSend": "Envío Programado",
"scheduledSendTimeMustBeLater": "La hora de envío programado debe ser posterior a la hora actual",
"selectSendScope": "Seleccionar alcance de envío",
"selectSendTime": "Seleccionar hora de envío, dejar vacío para envío inmediato",
"sendFailed": "Envío fallido, por favor intente de nuevo",
"sendNow": "Enviar Ahora",
"sendScope": "Alcance de Envío",
"sendScopeDescription": "Elija el alcance de usuario para el envío de correos electrónicos. Seleccione \"Solo correos electrónicos adicionales\" para enviar solo a las direcciones de correo electrónico completadas a continuación",
"sendSettings": "Configuraciones de Envío",
"sendTime": "Hora de Envío",
"sending": "Enviando",
"sentAt": "Enviado En",
"specificUsers": "Usuarios Específicos",
"specificUsersOnly": "Solo correos electrónicos adicionales (omitir usuarios de la plataforma)",
"status": "Estado",
"stop": "Detener",
"stopped": "Detenido",
"subject": "Asunto del Correo Electrónico",
"subscribedUsers": "Usuarios Suscritos",
"subscribedUsersOnly": "Solo usuarios suscritos",
"successCount": "Conteo de Éxitos",
"taskStatusRefreshed": "Estado de la tarea actualizado",
"taskStoppedSuccessfully": "Tarea detenida exitosamente",
"totalSent": "Total Enviado",
"updateSuccess": "Actualizado Exitosamente",
"useMarkdownEditor": "Utilice el editor Markdown para escribir contenido de correo electrónico con funcionalidad de vista previa",
"users": "usuarios",
"view": "Ver",
"viewAndManageEmailBroadcastTasks": "Ver y gestionar tareas de transmisión de correo electrónico",
"viewContent": "Ver Contenido"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "Configuración de ADS",
"Announcement Management": "Gestión de Anuncios",
"Apple": "ID de Apple",
"Application Management": "Gestión de Aplicaciones",
"Auth Control": "Control de Autenticación",
"Coupon Management": "Gestión de Cupones",
"Dashboard": "Tablero",
"Device": "Dispositivo",
"Document Management": "Gestión de Documentos",
"Email": "Correo electrónico",
"Facebook": "Facebook",
"Finance": "Finanzas",
"General": "General",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Gestión de Marketing",
"Order Management": "Gestión de Pedidos",
"Payment Config": "Configuración de Pago",
"Phone Number": "Número de Teléfono",
"Product Management": "Gestión de Productos",
"Protocol Management": "Gestión de Protocolos",
"Rule Management": "Gestión de Reglas",
"Server": "Servidor",
"Server Management": "Gestión de Servidores",
"Settings": "Configuración",
"Subscribe Management": "Gestión de Suscripciones",
"Subscribe Config": "Configuración de Suscripción",
"System Config": "Configuración del Sistema",
"System Management": "Gestión del Sistema",
"System Tool": "Herramienta del sistema",
"Telegram": "Telegram",
"Ticket Management": "Gestión de Tickets",
"Twitter": "Twitter",
"User": "Usuario",
"User Detail": "Detalle del Usuario",
"User Management": "Gestión de Usuarios"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "acciones",
"app": {
"appDownloadURL": "URL de Descarga de la App",
"appIcon": "Ícono de la App",
"appList": "Lista de Aplicaciones",
"appName": "Nombre de la App",
"backupDomains": "Lista de Dominios de Respaldo",
"backupDomainsDescription": "Lista de dominios de respaldo para la resolución de dominios, un dominio por línea",
"batchDelete": "Eliminar en Lote",
"cancel": "Cancelar",
"communicationKey": "Clave de Comunicación",
"communicationKeyDescription": "Clave utilizada para la comunicación con el cliente",
"config": "Configuración",
"configApp": "Configuración de la Aplicación",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"create": "Crear",
"createApp": "Crear App",
"createSuccess": "Creado exitosamente",
"defaultVersion": "Versión Predeterminada",
"delete": "Eliminar",
"deleteWarning": "Esta acción no se puede deshacer",
"describeDescription": "Se utiliza para describir la aplicación, se muestra en la lista de aplicaciones",
"description": "Descripción",
"downloadLink": "Enlace de Descarga",
"edit": "Editar",
"editApp": "Editar App",
"encryption": "Método de Cifrado",
"encryptionDescription": "Elige el método de cifrado para la comunicación con el cliente. Si se selecciona, el cliente usará este método para comunicarse con el servidor",
"nameDescription": "Nombre de la aplicación, se muestra en la lista de aplicaciones",
"platform": "Plataforma",
"selectApp": "Seleccionar Aplicación",
"selectAppDescription": "Selecciona la aplicación para configurar, todos los ajustes se aplicarán a la aplicación seleccionada",
"startupPicture": "Imagen de Inicio",
"startupPictureDescription": "Imagen de inicio, admite imágenes de red y locales. Para imágenes de red, ingrese la URL completa de la imagen",
"startupPicturePreview": "Vista Previa de la Imagen de Inicio",
"startupPictureSkip": "Tiempo de Salto de la Imagen de Inicio",
"startupPictureSkipDescription": "Tiempo de visualización de la imagen de inicio en segundos, ingrese 0 para no mostrar",
"subscriptionProtocol": "Protocolo de Suscripción",
"updateSuccess": "Actualizado exitosamente",
"version": "Versión"
},
"cancel": "Cancelar",
"config": {
"singleSubscriptionMode": "Modo de Suscripción Única",
"subscriptionDomain": "Dominio de Suscripción",
"subscriptionDomainDescription": "Usado para suscripción; deje en blanco para usar el dominio del sitio",
"subscriptionDomainPlaceholder": "Ingrese el dominio de suscripción, uno por línea",
"subscriptionPath": "Ruta de Suscripción",
"subscriptionPathDescription": "Usado para suscripción; asegúrese de reiniciar el sistema después de la modificación para un rendimiento óptimo",
"subscriptionPathPlaceholder": "Ingrese",
"updateSuccess": "Actualizado con éxito",
"wildcardResolution": "Resolución de Comodín",
"wildcardResolutionDescription": "Usado para suscripción"
},
"confirm": "Confirmar",
"confirmDelete": "¿Estás seguro de que deseas eliminar?",
"copy": "Copiar",
"copySuccess": "Copiado exitosamente",
"create": "Crear",
"createSubscribe": "Crear suscripción",
"createSuccess": "Creación exitosa",
"delete": "Eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Después de eliminar, los datos no se podrán recuperar. Proceda con precaución.",
"deviceLimit": "Número de dispositivos/unidad",
"edit": "editar",
"editSubscribe": "Editar suscripción",
"form": {
"Day": "Día",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"NoLimit": "Sin Límite",
"Year": "Año",
"annualReset": "Reinicio Anual",
"basic": "Básico",
"cancel": "Cancelar",
"confirm": "Confirmar",
"deductionRatio": "Configuración de Deducción Automática/Manual",
"deductionRatioDescription": "Utilizado para deducciones. Por defecto, el sistema adopta un algoritmo de cálculo automático. Cuando se proporciona un ratio manual, el sistema calcula proporciones basadas en el tiempo y el ratio de tráfico, asegurando que el total sea igual al 100%.",
"description": "Descripción",
"deviceLimit": "Límite de dispositivos",
"discount": "Descuento",
"discountDescription": "Descuento basado en el precio unitario",
"discountMonths": "Meses",
"discountPercent": "Porcentaje de descuento",
"discount_price": "Precio con descuento",
"duration": "Duración (meses)",
"groupId": "Grupo de Suscripción",
"inventory": "Límite de Suscripción",
"monthlyReset": "Reinicio Mensual",
"name": "Nombre",
"noLimit": "Sin límite",
"noReset": "Sin Reinicio",
"pricing": "Precios",
"purchaseWithDiscount": "Permitir Deducción",
"purchaseWithDiscountDescription": "Habilitar o deshabilitar la funcionalidad de cancelación de suscripción. Después de la activación, el sistema realizará el procesamiento de deducción según las reglas y proporciones configuradas, y el valor restante se devolverá al saldo",
"quota": "Cantidad máxima de compra",
"renewalReset": "Reinicio por Renovación",
"renewalResetDescription": "Reiniciar ciclo al renovar",
"replacement": "Precio de reposición (cada vez)",
"resetCycle": "Ciclo de Reinicio",
"resetOn1st": "Reiniciar el día 1",
"selectResetCycle": "Por favor, seleccione un ciclo de reinicio",
"selectSubscribeGroup": "Por favor seleccione un grupo de suscripción",
"selectUnitTime": "Por favor seleccione la unidad de tiempo",
"server": "Servidor",
"serverGroup": "Grupo de servidores",
"servers": "Servidores",
"speedLimit": "Límite de velocidad ",
"traffic": "Tráfico",
"unitPrice": "Precio unitario",
"unitTime": "Unidad de tiempo"
},
"group": {
"actions": "Acciones",
"cancel": "Cancelar",
"confirm": "Confirmar",
"confirmDelete": "¿Confirmar eliminación?",
"create": "Crear",
"createSubscribeGroup": "Crear nuevo grupo de suscripción",
"createSuccess": "Creación exitosa",
"delete": "Eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Los datos no se pueden recuperar después de la eliminación, por favor opere con precaución.",
"description": "Descripción",
"edit": "Editar",
"editSubscribeGroup": "Editar grupo de suscripción",
"form": {
"cancel": "Cancelar",
"confirm": "Confirmar",
"description": "Descripción",
"name": "Nombre"
},
"name": "Nombre",
"title": "Lista de grupos de suscripción",
"updateSuccess": "Actualización exitosa",
"updatedAt": "Fecha de actualización"
},
"inventory": "Límite de Suscripción",
"name": "Nombre",
"quota": "Límite de compra/vez",
"replacement": "Restablecer precio/vez",
"sell": "venta",
"show": "Mostrar",
"sold": "Conteo de Suscripciones",
"subscribe": "Suscribirse",
"subscribeGroup": "Suscribirse al grupo",
"tabs": {
"subscribe": "Suscribirse",
"subscribeApp": "Configuración de la App",
"subscribeConfig": "Configuración de Suscripción",
"subscribeGroup": "Grupo de suscripción"
},
"traffic": "tráfico",
"unitPrice": "Precio Unitario",
"updateSuccess": "Actualización exitosa"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Tipo",
"updateSuccess": "Actualización exitosa",
"updatedAt": "Fecha de actualización",
"userAccount": "Cuenta de Usuario",
"user": "Usuario",
"userDetail": "Detalle del Usuario",
"userId": "ID de Usuario"
},
+111 -140
View File
@@ -1,161 +1,132 @@
{
"actions": "acciones",
"app": {
"appDownloadURL": "URL de Descarga de la App",
"appIcon": "Ícono de la App",
"appList": "Lista de Aplicaciones",
"appName": "Nombre de la App",
"backupDomains": "Lista de Dominios de Respaldo",
"backupDomainsDescription": "Lista de dominios de respaldo para la resolución de dominios, un dominio por línea",
"actions": {
"add": "Agregar",
"batchDelete": "Eliminar en Lote",
"batchDeleteSuccess": "Se eliminaron exitosamente {count} clientes",
"batchDeleteWarning": "¿Está seguro de que desea eliminar los {count} clientes seleccionados?",
"cancel": "Cancelar",
"communicationKey": "Clave de Comunicación",
"communicationKeyDescription": "Clave utilizada para la comunicación con el cliente",
"config": "Configuración",
"configApp": "Configuración de la Aplicación",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"create": "Crear",
"createApp": "Crear App",
"createSuccess": "Creado exitosamente",
"defaultVersion": "Versión Predeterminada",
"delete": "Eliminar",
"deleteWarning": "Esta acción no se puede deshacer",
"describeDescription": "Se utiliza para describir la aplicación, se muestra en la lista de aplicaciones",
"description": "Descripción",
"downloadLink": "Enlace de Descarga",
"deleteFailed": "Error al eliminar",
"deleteSuccess": "Eliminado exitosamente",
"deleteWarning": "Esta operación no se puede deshacer. ¿Está seguro de que desea eliminar este cliente?",
"edit": "Editar",
"editApp": "Editar App",
"encryption": "Método de Cifrado",
"encryptionDescription": "Elige el método de cifrado para la comunicación con el cliente. Si se selecciona, el cliente usará este método para comunicarse con el servidor",
"nameDescription": "Nombre de la aplicación, se muestra en la lista de aplicaciones",
"platform": "Plataforma",
"selectApp": "Seleccionar Aplicación",
"selectAppDescription": "Selecciona la aplicación para configurar, todos los ajustes se aplicarán a la aplicación seleccionada",
"startupPicture": "Imagen de Inicio",
"startupPictureDescription": "Imagen de inicio, admite imágenes de red y locales. Para imágenes de red, ingrese la URL completa de la imagen",
"startupPicturePreview": "Vista Previa de la Imagen de Inicio",
"startupPictureSkip": "Tiempo de Salto de la Imagen de Inicio",
"startupPictureSkipDescription": "Tiempo de visualización de la imagen de inicio en segundos, ingrese 0 para no mostrar",
"subscriptionProtocol": "Protocolo de Suscripción",
"updateSuccess": "Actualizado exitosamente",
"version": "Versión"
"save": "Guardar",
"saveFailed": "Error al guardar",
"update": "Actualizar",
"updateSuccess": "Actualizado exitosamente"
},
"cancel": "Cancelar",
"config": {
"description": "Gestionar la configuración del sistema de suscripción",
"singleSubscriptionMode": "Modo de Suscripción Única",
"singleSubscriptionModeDescription": "Cuando está habilitado, todas las suscripciones de usuarios se convertirán en saldo",
"singleSubscriptionModeDescription": "Limitar a los usuarios a una suscripción activa. Las suscripciones existentes no se ven afectadas",
"subscriptionDomain": "Dominio de Suscripción",
"subscriptionDomainDescription": "Usado para suscripción; deje en blanco para usar el dominio del sitio",
"subscriptionDomainDescription": "Dominio personalizado para enlaces de suscripción",
"subscriptionDomainPlaceholder": "Ingrese el dominio de suscripción, uno por línea",
"subscriptionPath": "Ruta de Suscripción",
"subscriptionPathDescription": "Usado para suscripción; asegúrese de reiniciar el sistema después de la modificación para un rendimiento óptimo",
"subscriptionPathPlaceholder": "Ingrese",
"updateSuccess": "Actualizado con éxito",
"subscriptionPathDescription": "Ruta personalizada para los puntos finales de suscripción (mejor rendimiento después del reinicio del sistema)",
"subscriptionPathPlaceholder": "Ingrese la ruta de suscripción",
"title": "Configuración de Suscripción",
"updateError": "Error al actualizar",
"updateSuccess": "Configuraciones actualizadas exitosamente",
"userAgentLimit": "Restricción de {userAgent}",
"userAgentLimitDescription": "Habilitar restricciones de acceso basadas en {userAgent}",
"userAgentList": "Lista Blanca de {userAgent}",
"userAgentListDescription": "Permitir {userAgent} para acceso a suscripción, uno por línea. La aplicación configurada {userAgent} se incluirá automáticamente",
"userAgentListPlaceholder": "Ingrese {userAgent} permitidos, uno por línea",
"wildcardResolution": "Resolución de Comodín",
"wildcardResolutionDescription": "Usado para suscripción"
"wildcardResolutionDescription": "Habilitar resolución de dominio comodín para suscripciones"
},
"confirm": "Confirmar",
"confirmDelete": "¿Estás seguro de que deseas eliminar?",
"copy": "Copiar",
"copySuccess": "Copiado exitosamente",
"create": "Crear",
"createSubscribe": "Crear suscripción",
"createSuccess": "Creación exitosa",
"delete": "Eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Después de eliminar, los datos no se podrán recuperar. Proceda con precaución.",
"deviceLimit": "Número de dispositivos/unidad",
"edit": "editar",
"editSubscribe": "Editar suscripción",
"form": {
"Day": "Día",
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mes",
"NoLimit": "Sin Límite",
"Year": "Año",
"annualReset": "Reinicio Anual",
"basic": "Básico",
"cancel": "Cancelar",
"confirm": "Confirmar",
"deductionRatio": "Configuración de Deducción Automática/Manual",
"deductionRatioDescription": "Utilizado para deducciones. Por defecto, el sistema adopta un algoritmo de cálculo automático. Cuando se proporciona un ratio manual, el sistema calcula proporciones basadas en el tiempo y el ratio de tráfico, asegurando que el total sea igual al 100%.",
"description": "Descripción",
"deviceLimit": "Límite de dispositivos",
"discount": "Descuento",
"discountDescription": "Descuento basado en el precio unitario",
"discountMonths": "Meses",
"discountPercent": "Porcentaje de descuento",
"discount_price": "Precio con descuento",
"duration": "Duración (meses)",
"groupId": "Grupo de Suscripción",
"inventory": "Límite de Suscripción",
"monthlyReset": "Reinicio Mensual",
"name": "Nombre",
"noLimit": "Sin límite",
"noReset": "Sin Reinicio",
"pricing": "Precios",
"purchaseWithDiscount": "Permitir Deducción",
"purchaseWithDiscountDescription": "Habilitar o deshabilitar la funcionalidad de cancelación de suscripción. Después de la activación, el sistema realizará el procesamiento de deducción según las reglas y proporciones configuradas, y el valor restante se devolverá al saldo",
"quota": "Cantidad máxima de compra",
"renewalReset": "Reinicio por Renovación",
"renewalResetDescription": "Reiniciar ciclo al renovar",
"replacement": "Precio de reposición (cada vez)",
"resetCycle": "Ciclo de Reinicio",
"resetOn1st": "Reiniciar el día 1",
"selectResetCycle": "Por favor, seleccione un ciclo de reinicio",
"selectSubscribeGroup": "Por favor seleccione un grupo de suscripción",
"selectUnitTime": "Por favor seleccione la unidad de tiempo",
"server": "Servidor",
"serverGroup": "Grupo de servidores",
"servers": "Servidores",
"speedLimit": "Límite de velocidad ",
"traffic": "Tráfico",
"unitPrice": "Precio unitario",
"unitTime": "Unidad de tiempo"
},
"group": {
"actions": "Acciones",
"cancel": "Cancelar",
"confirm": "Confirmar",
"confirmDelete": "¿Confirmar eliminación?",
"create": "Crear",
"createSubscribeGroup": "Crear nuevo grupo de suscripción",
"createSuccess": "Creación exitosa",
"delete": "Eliminar",
"deleteSuccess": "Eliminación exitosa",
"deleteWarning": "Los datos no se pueden recuperar después de la eliminación, por favor opere con precaución.",
"description": "Descripción",
"edit": "Editar",
"editSubscribeGroup": "Editar grupo de suscripción",
"form": {
"cancel": "Cancelar",
"confirm": "Confirmar",
"description": "Descripción",
"name": "Nombre"
"addTitle": "Agregar Cliente",
"descriptions": {
"description": "Descripción detallada del cliente",
"downloadLink": "URL de descarga de la plataforma",
"icon": "URL del ícono o codificación base64",
"name": "Nombre para mostrar del cliente",
"outputFormat": "Formato del archivo de configuración de suscripción",
"scheme": {
"base64Encoding": "Codificación Base64",
"functions": "Soporta funciones:",
"jsonStringify": "Objeto JSON a cadena",
"nameVariable": "nombre del sitio",
"title": "Plantilla de esquema de URL",
"urlEncoding": "Codificación de URL",
"urlVariable": "URL de suscripción",
"variables": "Soporta variables:"
},
"template": {
"description": "Usar sintaxis de plantilla Go para generar archivos de configuración de suscripción",
"functions": "Funciones de plantilla:",
"if": "declaraciones condicionales",
"nodes": "lista de nodos proxy",
"range": "iterar arreglos",
"siteName": "nombre del sitio",
"sprig": "Biblioteca de funciones Sprig (procesamiento de cadenas, fechas, etc.)",
"subscribeName": "nombre de la suscripción",
"title": "Sintaxis de Plantilla Go",
"userInfo": "información del usuario (tráfico, expiración, etc.)",
"variables": "Variables disponibles:"
},
"userAgentPrefix": "Identificador del cliente para distinguir diferentes clientes"
},
"name": "Nombre",
"title": "Lista de grupos de suscripción",
"updateSuccess": "Actualización exitosa",
"updatedAt": "Fecha de actualización"
"editTitle": "Editar Cliente",
"fields": {
"description": "Descripción",
"icon": "Ícono",
"name": "Nombre",
"outputFormat": "Formato de Salida",
"scheme": "Esquema de URL",
"template": "Plantilla de Archivo de Suscripción"
},
"tabs": {
"basic": "Información Básica",
"download": "Descargas",
"template": "Plantillas"
},
"validation": {
"nameRequired": "Se requiere el nombre del cliente",
"userAgentRequiredSuffix": "es requerido"
}
},
"inventory": "Límite de Suscripción",
"name": "Nombre",
"quota": "Límite de compra/vez",
"replacement": "Restablecer precio/vez",
"sell": "venta",
"show": "Mostrar",
"sold": "Conteo de Suscripciones",
"subscribe": "Suscribirse",
"subscribeGroup": "Suscribirse al grupo",
"tabs": {
"subscribe": "Suscribirse",
"subscribeApp": "Configuración de la App",
"subscribeConfig": "Configuración de Suscripción",
"subscribeGroup": "Grupo de suscripción"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Texto Plano",
"yaml": "YAML"
},
"traffic": "tráfico",
"unitPrice": "Precio Unitario",
"updateSuccess": "Actualización exitosa"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Gestión de Clientes"
},
"table": {
"columns": {
"default": "Predeterminado",
"description": "Descripción",
"name": "Nombre del Cliente",
"outputFormat": "Formato de Salida",
"supportedPlatforms": "Plataformas Soportadas"
}
},
"templatePreview": {
"base64": {
"decodeError": "Error de decodificación: El contenido no es un formato Base64 válido",
"decodedContent": "Contenido decodificado",
"originalContent": "Contenido original (Base64)"
},
"failed": "La vista previa falló",
"loading": "Cargando...",
"preview": "Vista previa",
"title": "Vista previa de la plantilla"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "día(s)",
"defaultSubscribe": "Suscripción Predeterminada",
"defaultSubscribeDescription": "Plan de suscripción predeterminado para nuevos usuarios",
"description": "Configurar ajustes relacionados con el registro de usuarios",
"enableTrial": "Habilitar Prueba",
"enableTrialDescription": "Cuando está habilitado, los nuevos usuarios recibirán una suscripción de prueba al registrarse",
"hour": "Hora(s)",
"inputPlaceholder": "Por favor ingrese",
"ipRegistrationLimit": "Límite de Registro por IP",
"ipRegistrationLimitDescription": "Limitar el número de registros desde una sola dirección IP",
"minute": "Minuto(s)",
"month": "Mes(es)",
"none": "Ninguno",
"registrationLimitCount": "Conteo de Límite de Registro",
"registrationLimitCountDescription": "Número de registros permitidos por IP dentro del período límite",
"registrationLimitExpire": "Período de Límite",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Detener Registro de Nuevos Usuarios",
"stopNewUserRegistrationDescription": "Cuando está habilitado, el registro de nuevos usuarios estará deshabilitado",
"title": "Configuración de Registro",
"trialDay": "Días de Prueba",
"trialDayDescription": "Días de prueba otorgados a nuevos usuarios al registrarse",
"trialFlow": "Tráfico de Prueba",
"trialFlowDescription": "Tráfico de prueba otorgado a nuevos usuarios al registrarse"
"trialConfig": "Configuración de Prueba",
"trialConfigDescription": "Configura la suscripción de prueba, duración y unidad de tiempo para nuevos usuarios al registrarse",
"year": "Año(s)"
},
"site": {
"customData": "Datos Personalizados",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "اضافی",
"additionalRecipientEmails": "ایمیل‌های اضافی گیرندگان",
"additionalRecipients": "گیرندگان اضافی",
"additionalRecipientsDescription": "این ایمیل‌ها به همراه فیلتر کاربر بالا، پخش را دریافت خواهند کرد",
"allUsers": "تمام کاربران",
"broadcastList": "لیست پخش",
"broadcastLogs": "گزارش‌های پخش",
"cancel": "لغو",
"cannotBeEmpty": "نمی‌تواند خالی باشد",
"completed": "تکمیل شده",
"confirm": "تأیید",
"confirmDelete": "تأیید حذف",
"content": "محتوای ایمیل",
"create": "ایجاد",
"createBroadcast": "ایجاد پخش",
"createNewEmailBroadcastCampaign": "ایجاد کمپین جدید پخش ایمیل",
"createSuccess": "با موفقیت ایجاد شد",
"createdAt": "تاریخ ایجاد",
"dailyLimit": "حداکثر روزانه باید حداقل ۱ باشد",
"dailySendLimit": "حداکثر ارسال روزانه",
"delete": "حذف",
"deleteDescription": "این عملیات قابل بازگشت نیست. آیا مطمئن هستید که می‌خواهید حذف کنید؟",
"deleteSuccess": "با موفقیت حذف شد",
"edit": "ویرایش",
"emailAddedToScheduledQueue": "ایمیل به صف ارسال زمان‌بندی شده اضافه شد",
"emailBroadcast": "پخش ایمیل",
"emailBroadcastTaskCreatedSuccessfully": "وظیفه پخش ایمیل با موفقیت ایجاد شد",
"emailBroadcastTasks": "وظایف پخش ایمیل",
"emailContent": "محتوای ایمیل",
"emailInterval": "فاصله زمانی ایمیل (ثانیه)",
"emailIntervalMinimum": "فاصله زمانی ایمیل باید حداقل ۰.۱ ثانیه باشد",
"emailMarketing": "بازاریابی ایمیلی",
"emailTaskManager": "مدیر وظایف ایمیل",
"errorMessage": "پیام خطا",
"estimatedRecipients": "گیرندگان تخمینی",
"expiredSubscriptionUsersOnly": "فقط کاربران با اشتراک منقضی شده",
"expiredUsers": "کاربران منقضی شده",
"failCount": "تعداد شکست‌ها",
"failed": "شکست خورده",
"failedToRefreshTaskStatus": "عدم توانایی در به‌روزرسانی وضعیت وظیفه",
"failedToStopTask": "عدم توانایی در متوقف کردن وظیفه",
"inProgress": "در حال انجام",
"includeUsersRegisteredAfter": "شامل کاربران ثبت‌نام شده در یا بعد از این تاریخ",
"includeUsersRegisteredBefore": "شامل کاربران ثبت‌نام شده در یا قبل از این تاریخ",
"intervalTimeBetweenEmails": "فاصله زمانی بین هر ایمیل",
"leaveEmptyForImmediateSend": "برای ارسال فوری خالی بگذارید",
"logList": "لیست گزارش‌ها",
"marketingManagement": "مدیریت بازاریابی",
"maximumNumberPerDay": "حداکثر تعداد ایمیل‌ها برای ارسال در روز",
"noSubscriptionUsersOnly": "فقط کاربران بدون اشتراک",
"nonSubscribers": "غیر مشترکین",
"notStarted": "شروع نشده",
"onePerLine": "یکی در هر خط",
"only": "فقط",
"pending": "در انتظار",
"pleaseEnter": "لطفاً وارد کنید",
"pleaseEnterValidEmailAddresses": "لطفاً آدرس‌های ایمیل معتبر را وارد کنید، یکی در هر خط",
"processing": "در حال پردازش...",
"progress": "پیشرفت",
"recipient": "گیرنده",
"recipientEmail": "ایمیل گیرنده",
"recipientType": "نوع گیرنده",
"registrationEndDate": "تاریخ پایان ثبت‌نام",
"registrationStartDate": "تاریخ شروع ثبت‌نام",
"scheduleSend": "زمان‌بندی ارسال",
"scheduledSend": "ارسال زمان‌بندی شده",
"scheduledSendTimeMustBeLater": "زمان ارسال زمان‌بندی شده باید بعد از زمان کنونی باشد",
"selectSendScope": "دامنه ارسال را انتخاب کنید",
"selectSendTime": "زمان ارسال را انتخاب کنید، برای ارسال فوری خالی بگذارید",
"sendFailed": "ارسال ناموفق بود، لطفاً دوباره تلاش کنید",
"sendNow": "اکنون ارسال کنید",
"sendScope": "دامنه ارسال",
"sendScopeDescription": "دامنه کاربری برای ارسال ایمیل را انتخاب کنید. برای ارسال فقط به آدرس‌های ایمیل پر شده در زیر، \"فقط ایمیل‌های اضافی\" را انتخاب کنید",
"sendSettings": "تنظیمات ارسال",
"sendTime": "زمان ارسال",
"sending": "در حال ارسال",
"sentAt": "در تاریخ ارسال شد",
"specificUsers": "کاربران خاص",
"specificUsersOnly": "فقط ایمیل‌های اضافی (کاربران پلتفرم را نادیده بگیرید)",
"status": "وضعیت",
"stop": "متوقف کردن",
"stopped": "متوقف شده",
"subject": "موضوع ایمیل",
"subscribedUsers": "کاربران مشترک",
"subscribedUsersOnly": "فقط کاربران مشترک",
"successCount": "تعداد موفقیت‌ها",
"taskStatusRefreshed": "وضعیت وظیفه به‌روزرسانی شد",
"taskStoppedSuccessfully": "وظیفه با موفقیت متوقف شد",
"totalSent": "مجموع ارسال شده",
"updateSuccess": "با موفقیت به‌روزرسانی شد",
"useMarkdownEditor": "از ویرایشگر Markdown برای نوشتن محتوای ایمیل با قابلیت پیش‌نمایش استفاده کنید",
"users": "کاربران",
"view": "مشاهده",
"viewAndManageEmailBroadcastTasks": "مشاهده و مدیریت وظایف پخش ایمیل",
"viewContent": "مشاهده محتوا"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "تنظیمات ADS",
"Announcement Management": "مدیریت اطلاعیه‌ها",
"Apple": "شناسه اپل",
"Application Management": "مدیریت برنامه",
"Auth Control": "کنترل احراز هویت",
"Coupon Management": "مدیریت کوپن",
"Dashboard": "داشبورد",
"Device": "دستگاه",
"Document Management": "مدیریت اسناد",
"Email": "ایمیل",
"Facebook": "فیس‌بوک",
"Finance": "امور مالی",
"General": "عمومی",
"GitHub": "گیت‌هاب",
"Google": "گوگل",
"Marketing Management": "مدیریت بازاریابی",
"Order Management": "مدیریت سفارش",
"Payment Config": "پیکربندی پرداخت",
"Phone Number": "شماره تلفن",
"Product Management": "مدیریت محصول",
"Protocol Management": "مدیریت پروتکل",
"Rule Management": "مدیریت قوانین",
"Server": "سرور",
"Server Management": "مدیریت سرور",
"Settings": "تنظیمات",
"Subscribe Management": "مدیریت اشتراک",
"Subscribe Config": "تنظیمات اشتراک",
"System Config": "پیکربندی سیستم",
"System Management": "مدیریت سیستم",
"System Tool": "ابزار سیستم",
"Telegram": "تلگرام",
"Ticket Management": "مدیریت بلیط",
"Twitter": "توییتر",
"User": "کاربر",
"User Detail": "جزئیات کاربر",
"User Management": "مدیریت کاربران"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "اقدامات",
"app": {
"appDownloadURL": "آدرس دانلود اپلیکیشن",
"appIcon": "آیکون اپلیکیشن",
"appList": "لیست برنامه‌ها",
"appName": "نام اپلیکیشن",
"backupDomains": "لیست دامنه‌های پشتیبان",
"backupDomainsDescription": "لیست دامنه‌های پشتیبان برای حل دامنه، هر دامنه در یک خط",
"batchDelete": "حذف گروهی",
"cancel": "لغو",
"communicationKey": "کلید ارتباطی",
"communicationKeyDescription": "کلیدی که برای ارتباط با مشتری استفاده می‌شود",
"config": "پیکربندی",
"configApp": "پیکربندی برنامه",
"confirm": "تأیید",
"confirmDelete": "تأیید حذف",
"create": "ایجاد",
"createApp": "ایجاد اپلیکیشن",
"createSuccess": "با موفقیت ایجاد شد",
"defaultVersion": "پیش‌فرض",
"delete": "حذف",
"deleteWarning": "این عمل قابل بازگشت نیست",
"describeDescription": "برای توصیف برنامه استفاده می‌شود، در لیست برنامه‌ها نمایش داده می‌شود",
"description": "توضیحات",
"downloadLink": "لینک دانلود",
"edit": "ویرایش",
"editApp": "ویرایش اپلیکیشن",
"encryption": "روش رمزنگاری",
"encryptionDescription": "روش رمزنگاری برای ارتباط با مشتری را انتخاب کنید. در صورت انتخاب، مشتری از این روش برای ارتباط با سرور استفاده خواهد کرد",
"nameDescription": "نام برنامه، در لیست برنامه‌ها نمایش داده می‌شود",
"platform": "پلتفرم",
"selectApp": "انتخاب برنامه",
"selectAppDescription": "برنامه‌ای را برای پیکربندی انتخاب کنید، تمام تنظیمات به برنامه انتخاب شده اعمال خواهد شد",
"startupPicture": "تصویر شروع",
"startupPictureDescription": "تصویر شروع، از تصاویر شبکه و محلی پشتیبانی می‌کند. برای تصاویر شبکه، لطفاً آدرس کامل تصویر را وارد کنید",
"startupPicturePreview": "پیش‌نمایش تصویر شروع",
"startupPictureSkip": "زمان عبور از تصویر شروع",
"startupPictureSkipDescription": "زمان نمایش تصویر شروع به ثانیه، برای عدم نمایش 0 وارد کنید",
"subscriptionProtocol": "پروتکل اشتراک",
"updateSuccess": "با موفقیت به‌روزرسانی شد",
"version": "نسخه"
},
"cancel": "لغو",
"config": {
"singleSubscriptionMode": "حالت اشتراک تکی",
"subscriptionDomain": "دامنه اشتراک",
"subscriptionDomainDescription": "برای اشتراک استفاده می‌شود؛ برای استفاده از دامنه سایت، خالی بگذارید",
"subscriptionDomainPlaceholder": "دامنه اشتراک را وارد کنید، هر خط یک دامنه",
"subscriptionPath": "مسیر اشتراک",
"subscriptionPathDescription": "برای اشتراک استفاده می‌شود؛ حتماً پس از تغییر، سیستم را برای عملکرد بهینه راه‌اندازی مجدد کنید",
"subscriptionPathPlaceholder": "وارد کنید",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد",
"wildcardResolution": "حل و فصل کاراکترهای جایگزین",
"wildcardResolutionDescription": "برای اشتراک استفاده می‌شود"
},
"confirm": "تأیید",
"confirmDelete": "آیا مطمئن هستید که می‌خواهید حذف کنید؟",
"copy": "کپی",
"copySuccess": "با موفقیت کپی شد",
"create": "ایجاد",
"createSubscribe": "ایجاد اشتراک",
"createSuccess": "ایجاد با موفقیت انجام شد",
"delete": "حذف",
"deleteSuccess": "حذف با موفقیت انجام شد",
"deleteWarning": "پس از حذف، داده‌ها قابل بازیابی نیستند. لطفاً با احتیاط ادامه دهید.",
"deviceLimit": "محدودیت دستگاه/واحد",
"edit": "ویرایش",
"editSubscribe": "ویرایش اشتراک",
"form": {
"Day": "روز",
"Hour": "ساعت",
"Minute": "دقیقه",
"Month": "ماه",
"NoLimit": "بدون محدودیت",
"Year": "سال",
"annualReset": "بازنشانی سالانه",
"basic": "پایه",
"cancel": "لغو",
"confirm": "تأیید",
"deductionRatio": "پیکربندی کسر خودکار/دستی",
"deductionRatioDescription": "برای کسر استفاده می‌شود. به طور پیش‌فرض، سیستم از یک الگوریتم محاسبه خودکار استفاده می‌کند. هنگامی که نسبت دستی ارائه می‌شود، سیستم نسبت‌ها را بر اساس زمان و نسبت ترافیک محاسبه می‌کند و اطمینان حاصل می‌کند که مجموع به ۱۰۰٪ می‌رسد.",
"description": "توضیحات",
"deviceLimit": "محدودیت دستگاه",
"discount": "تخفیف",
"discountDescription": "تعیین تخفیف بر اساس قیمت واحد",
"discountMonths": "ماه‌ها",
"discountPercent": "درصد تخفیف",
"discount_price": "قیمت تخفیف",
"duration": "مدت زمان (ماه‌ها)",
"groupId": "گروه اشتراک",
"inventory": "محدودیت اشتراک",
"monthlyReset": "بازنشانی ماهانه",
"name": "نام",
"noLimit": "بدون محدودیت",
"noReset": "بدون بازنشانی",
"pricing": "قیمت‌گذاری",
"purchaseWithDiscount": "اجازه کسر",
"purchaseWithDiscountDescription": "فعال یا غیرفعال کردن قابلیت لغو اشتراک. پس از فعال‌سازی، سیستم بر اساس قوانین و نسبت‌های تنظیم‌شده، پردازش کسر را انجام می‌دهد و مقدار باقی‌مانده به موجودی بازگردانده می‌شود.",
"quota": "محدودیت خرید",
"renewalReset": "بازنشانی تمدید",
"renewalResetDescription": "بازنشانی چرخه در زمان تمدید",
"replacement": "تنظیم مجدد قیمت (هر بار)",
"resetCycle": "چرخه بازنشانی",
"resetOn1st": "بازنشانی در روز اول",
"selectResetCycle": "لطفاً یک چرخه بازنشانی انتخاب کنید",
"selectSubscribeGroup": "گروه اشتراک را انتخاب کنید",
"selectUnitTime": "لطفاً واحد زمان را انتخاب کنید",
"server": "سرور",
"serverGroup": "گروه سرور",
"servers": "سرورها",
"speedLimit": "محدودیت سرعت (مگابیت بر ثانیه)",
"traffic": "ترافیک",
"unitPrice": "قیمت واحد",
"unitTime": "واحد زمان"
},
"group": {
"actions": "اقدامات",
"cancel": "لغو",
"confirm": "تأیید",
"confirmDelete": "آیا مطمئن هستید که می‌خواهید حذف کنید؟",
"create": "ایجاد",
"createSubscribeGroup": "ایجاد گروه اشتراک",
"createSuccess": "ایجاد با موفقیت انجام شد",
"delete": "حذف",
"deleteSuccess": "حذف با موفقیت انجام شد",
"deleteWarning": "پس از حذف، داده‌ها قابل بازیابی نیستند. لطفاً با احتیاط ادامه دهید.",
"description": "توضیحات",
"edit": "ویرایش",
"editSubscribeGroup": "ویرایش گروه اشتراک",
"form": {
"cancel": "لغو",
"confirm": "تأیید",
"description": "توضیحات",
"name": "نام"
},
"name": "نام",
"title": "فهرست گروه‌های اشتراک",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد",
"updatedAt": "به‌روزرسانی در"
},
"inventory": "محدودیت اشتراک",
"name": "نام",
"quota": "محدودیت خرید/زمان",
"replacement": "تنظیم مجدد قیمت/زمان",
"sell": "فروش",
"show": "نمایش",
"sold": "تعداد اشتراک",
"subscribe": "اشتراک",
"subscribeGroup": "گروه اشتراک",
"tabs": {
"subscribe": "اشتراک",
"subscribeApp": "پیکربندی اپلیکیشن",
"subscribeConfig": "پیکربندی اشتراک",
"subscribeGroup": "گروه اشتراک"
},
"traffic": "ترافیک",
"unitPrice": "قیمت واحد",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "نوع",
"updateSuccess": "به‌روزرسانی موفقیت‌آمیز بود",
"updatedAt": "به‌روزرسانی در",
"userAccount": "حساب کاربری",
"user": "کاربر",
"userDetail": "جزئیات کاربر",
"userId": "شناسه کاربر"
},
+114 -143
View File
@@ -1,161 +1,132 @@
{
"actions": "اقدامات",
"app": {
"appDownloadURL": "آدرس دانلود اپلیکیشن",
"appIcon": "آیکون اپلیکیشن",
"appList": "لیست برنامه‌ها",
"appName": "نام اپلیکیشن",
"backupDomains": "لیست دامنه‌های پشتیبان",
"backupDomainsDescription": "لیست دامنه‌های پشتیبان برای حل دامنه، هر دامنه در یک خط",
"batchDelete": "حذف گروهی",
"actions": {
"add": "اضافه کردن",
"batchDelete": "حذف دسته‌ای",
"batchDeleteSuccess": "با موفقیت {count} مشتری حذف شد",
"batchDeleteWarning": "آیا مطمئن هستید که می‌خواهید {count} مشتری انتخاب شده را حذف کنید؟",
"cancel": "لغو",
"communicationKey": "کلید ارتباطی",
"communicationKeyDescription": "کلیدی که برای ارتباط با مشتری استفاده می‌شود",
"config": "پیکربندی",
"configApp": "پیکربندی برنامه",
"confirm": "تأیید",
"confirmDelete": "تأیید حذف",
"create": "ایجاد",
"createApp": "ایجاد اپلیکیشن",
"createSuccess": "با موفقیت ایجاد شد",
"defaultVersion": "پیش‌فرض",
"delete": "حذف",
"deleteWarning": "این عمل قابل بازگشت نیست",
"describeDescription": "برای توصیف برنامه استفاده می‌شود، در لیست برنامه‌ها نمایش داده می‌شود",
"description": "توضیحات",
"downloadLink": "لینک دانلود",
"deleteFailed": "حذف ناموفق بود",
"deleteSuccess": "با موفقیت حذف شد",
"deleteWarning": "این عملیات قابل بازگشت نیست. آیا مطمئن هستید که می‌خواهید این مشتری را حذف کنید؟",
"edit": "ویرایش",
"editApp": "ویرایش اپلیکیشن",
"encryption": "روش رمزنگاری",
"encryptionDescription": "روش رمزنگاری برای ارتباط با مشتری را انتخاب کنید. در صورت انتخاب، مشتری از این روش برای ارتباط با سرور استفاده خواهد کرد",
"nameDescription": "نام برنامه، در لیست برنامه‌ها نمایش داده می‌شود",
"platform": "پلتفرم",
"selectApp": "انتخاب برنامه",
"selectAppDescription": "برنامه‌ای را برای پیکربندی انتخاب کنید، تمام تنظیمات به برنامه انتخاب شده اعمال خواهد شد",
"startupPicture": "تصویر شروع",
"startupPictureDescription": "تصویر شروع، از تصاویر شبکه و محلی پشتیبانی می‌کند. برای تصاویر شبکه، لطفاً آدرس کامل تصویر را وارد کنید",
"startupPicturePreview": "پیش‌نمایش تصویر شروع",
"startupPictureSkip": "زمان عبور از تصویر شروع",
"startupPictureSkipDescription": "زمان نمایش تصویر شروع به ثانیه، برای عدم نمایش 0 وارد کنید",
"subscriptionProtocol": "پروتکل اشتراک",
"updateSuccess": "با موفقیت به‌روزرسانی شد",
"version": "نسخه"
"save": "ذخیره",
"saveFailed": "ذخیره ناموفق بود",
"update": "به‌روزرسانی",
"updateSuccess": "با موفقیت به‌روزرسانی شد"
},
"cancel": "لغو",
"config": {
"description": "مدیریت تنظیمات سیستم اشتراک",
"singleSubscriptionMode": "حالت اشتراک تکی",
"singleSubscriptionModeDescription": "هنگامی که فعال شود، تمام اشتراک‌های کاربر به موجودی تبدیل می‌شوند",
"singleSubscriptionModeDescription": "محدود کردن کاربران به یک اشتراک فعال. اشتراک‌های موجود تحت تأثیر قرار نمی‌گیرند",
"subscriptionDomain": "دامنه اشتراک",
"subscriptionDomainDescription": "برای اشتراک استفاده می‌شود؛ برای استفاده از دامنه سایت، خالی بگذارید",
"subscriptionDomainPlaceholder": "دامنه اشتراک را وارد کنید، هر خط یک دامنه",
"subscriptionDomainDescription": "دامنه سفارشی برای لینک‌های اشتراک",
"subscriptionDomainPlaceholder": "دامنه اشتراک را وارد کنید، هر کدام در یک خط",
"subscriptionPath": "مسیر اشتراک",
"subscriptionPathDescription": "برای اشتراک استفاده می‌شود؛ حتماً پس از تغییر، سیستم را برای عملکرد بهینه راه‌اندازی مجدد کنید",
"subscriptionPathPlaceholder": "وارد کنید",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد",
"wildcardResolution": "حل و فصل کاراکترهای جایگزین",
"wildcardResolutionDescription": "برای اشتراک استفاده می‌شود"
"subscriptionPathDescription": "مسیر سفارشی برای نقاط پایانی اشتراک (عملکرد بهتر پس از راه‌اندازی مجدد سیستم)",
"subscriptionPathPlaceholder": "مسیر اشتراک را وارد کنید",
"title": "پیکربندی اشتراک",
"updateError": "به‌روزرسانی ناموفق بود",
"updateSuccess": "تنظیمات با موفقیت به‌روزرسانی شد",
"userAgentLimit": "{userAgent} محدودیت",
"userAgentLimitDescription": "فعال‌سازی محدودیت‌های دسترسی بر اساس {userAgent}",
"userAgentList": "{userAgent} لیست سفید",
"userAgentListDescription": "اجازه دسترسی {userAgent} برای اشتراک، هر کدام در یک خط. برنامه پیکربندی شده {userAgent} به‌طور خودکار شامل خواهد شد",
"userAgentListPlaceholder": "اجازه {userAgent} را وارد کنید، هر کدام در یک خط",
"wildcardResolution": "حل wildcard",
"wildcardResolutionDescription": "فعال‌سازی حل دامنه wildcard برای اشتراک‌ها"
},
"confirm": "تأیید",
"confirmDelete": "آیا مطمئن هستید که می‌خواهید حذف کنید؟",
"copy": "کپی",
"copySuccess": "با موفقیت کپی شد",
"create": "ایجاد",
"createSubscribe": "ایجاد اشتراک",
"createSuccess": "ایجاد با موفقیت انجام شد",
"delete": "حذف",
"deleteSuccess": "حذف با موفقیت انجام شد",
"deleteWarning": "پس از حذف، داده‌ها قابل بازیابی نیستند. لطفاً با احتیاط ادامه دهید.",
"deviceLimit": "محدودیت دستگاه/واحد",
"edit": "ویرایش",
"editSubscribe": "ویرایش اشتراک",
"form": {
"Day": "روز",
"Hour": "ساعت",
"Minute": "دقیقه",
"Month": "ماه",
"NoLimit": "بدون محدودیت",
"Year": "سال",
"annualReset": "بازنشانی سالانه",
"basic": "پایه",
"cancel": "لغو",
"confirm": "تأیید",
"deductionRatio": "پیکربندی کسر خودکار/دستی",
"deductionRatioDescription": "برای کسر استفاده می‌شود. به طور پیش‌فرض، سیستم از یک الگوریتم محاسبه خودکار استفاده می‌کند. هنگامی که نسبت دستی ارائه می‌شود، سیستم نسبت‌ها را بر اساس زمان و نسبت ترافیک محاسبه می‌کند و اطمینان حاصل می‌کند که مجموع به ۱۰۰٪ می‌رسد.",
"description": "توضیحات",
"deviceLimit": "محدودیت دستگاه",
"discount": "تخفیف",
"discountDescription": "تعیین تخفیف بر اساس قیمت واحد",
"discountMonths": "ماه‌ها",
"discountPercent": "درصد تخفیف",
"discount_price": "قیمت تخفیف",
"duration": "مدت زمان (ماه‌ها)",
"groupId": "گروه اشتراک",
"inventory": "محدودیت اشتراک",
"monthlyReset": "بازنشانی ماهانه",
"name": "نام",
"noLimit": "بدون محدودیت",
"noReset": "بدون بازنشانی",
"pricing": "قیمت‌گذاری",
"purchaseWithDiscount": "اجازه کسر",
"purchaseWithDiscountDescription": "فعال یا غیرفعال کردن قابلیت لغو اشتراک. پس از فعال‌سازی، سیستم بر اساس قوانین و نسبت‌های تنظیم‌شده، پردازش کسر را انجام می‌دهد و مقدار باقی‌مانده به موجودی بازگردانده می‌شود.",
"quota": "محدودیت خرید",
"renewalReset": "بازنشانی تمدید",
"renewalResetDescription": "بازنشانی چرخه در زمان تمدید",
"replacement": "تنظیم مجدد قیمت (هر بار)",
"resetCycle": "چرخه بازنشانی",
"resetOn1st": "بازنشانی در روز اول",
"selectResetCycle": "لطفاً یک چرخه بازنشانی انتخاب کنید",
"selectSubscribeGroup": "گروه اشتراک را انتخاب کنید",
"selectUnitTime": "لطفاً واحد زمان را انتخاب کنید",
"server": "سرور",
"serverGroup": "گروه سرور",
"servers": "سرورها",
"speedLimit": "محدودیت سرعت (مگابیت بر ثانیه)",
"traffic": "ترافیک",
"unitPrice": "قیمت واحد",
"unitTime": "واحد زمان"
},
"group": {
"actions": "اقدامات",
"cancel": "لغو",
"confirm": "تأیید",
"confirmDelete": "آیا مطمئن هستید که می‌خواهید حذف کنید؟",
"create": "ایجاد",
"createSubscribeGroup": "ایجاد گروه اشتراک",
"createSuccess": "ایجاد با موفقیت انجام شد",
"delete": "حذف",
"deleteSuccess": "حذف با موفقیت انجام شد",
"deleteWarning": "پس از حذف، داده‌ها قابل بازیابی نیستند. لطفاً با احتیاط ادامه دهید.",
"description": "توضیحات",
"edit": "ویرایش",
"editSubscribeGroup": "ویرایش گروه اشتراک",
"form": {
"cancel": "لغو",
"confirm": "تأیید",
"description": "توضیحات",
"name": "نام"
"addTitle": "اضافه کردن مشتری",
"descriptions": {
"description": "توضیحات دقیق مشتری",
"downloadLink": "URL دانلود پلتفرم",
"icon": "URL آیکون یا کدگذاری base64",
"name": "نام نمایشی مشتری",
"outputFormat": "فرمت فایل پیکربندی اشتراک",
"scheme": {
"base64Encoding": "کدگذاری Base64",
"functions": "توابع را پشتیبانی می‌کند:",
"jsonStringify": "شی JSON به رشته",
"nameVariable": "نام سایت",
"title": "الگوی طرح URL",
"urlEncoding": "کدگذاری URL",
"urlVariable": "URL اشتراک",
"variables": "متغیرها را پشتیبانی می‌کند:"
},
"template": {
"description": "استفاده از نحو قالب Go برای تولید فایل‌های پیکربندی اشتراک",
"functions": "توابع قالب:",
"if": "عبارات شرطی",
"nodes": "لیست گره‌های پروکسی",
"range": "تکرار آرایه‌ها",
"siteName": "نام سایت",
"sprig": "کتابخانه توابع Sprig (پردازش رشته، تاریخ‌ها و غیره)",
"subscribeName": "نام اشتراک",
"title": "نحو قالب Go",
"userInfo": "اطلاعات کاربر (ترافیک، انقضا و غیره)",
"variables": "متغیرهای موجود:"
},
"userAgentPrefix": "شناسایی مشتری برای تمایز مشتریان مختلف"
},
"name": "نام",
"title": "فهرست گروه‌های اشتراک",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد",
"updatedAt": "به‌روزرسانی در"
"editTitle": "ویرایش مشتری",
"fields": {
"description": "توضیحات",
"icon": "آیکون",
"name": "نام",
"outputFormat": "فرمت خروجی",
"scheme": "طرح URL",
"template": "قالب فایل اشتراک"
},
"tabs": {
"basic": "اطلاعات پایه",
"download": "دانلودها",
"template": "قالب‌ها"
},
"validation": {
"nameRequired": "نام مشتری الزامی است",
"userAgentRequiredSuffix": "الزامی است"
}
},
"inventory": "محدودیت اشتراک",
"name": "نام",
"quota": "محدودیت خرید/زمان",
"replacement": "تنظیم مجدد قیمت/زمان",
"sell": "فروش",
"show": "نمایش",
"sold": "تعداد اشتراک",
"subscribe": "اشتراک",
"subscribeGroup": "گروه اشتراک",
"tabs": {
"subscribe": "اشتراک",
"subscribeApp": "پیکربندی اپلیکیشن",
"subscribeConfig": "پیکربندی اشتراک",
"subscribeGroup": "گروه اشتراک"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "متن ساده",
"yaml": "YAML"
},
"traffic": "ترافیک",
"unitPrice": "قیمت واحد",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد"
"platforms": {
"android": "اندروید",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "لینوکس",
"mac": "macOS",
"windows": "ویندوز"
},
"protocol": {
"title": "مدیریت مشتری"
},
"table": {
"columns": {
"default": "پیش‌فرض",
"description": "توضیحات",
"name": "نام مشتری",
"outputFormat": "فرمت خروجی",
"supportedPlatforms": "پلتفرم‌های پشتیبانی شده"
}
},
"templatePreview": {
"base64": {
"decodeError": "خطا در رمزگشایی: محتوا فرمت Base64 معتبر نیست",
"decodedContent": "محتوای رمزگشایی شده",
"originalContent": "محتوای اصلی (Base64)"
},
"failed": "پیش‌نمایش ناموفق بود",
"loading": "در حال بارگذاری...",
"preview": "پیش‌نمایش",
"title": "پیش‌نمایش الگو"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "روز(ها)",
"defaultSubscribe": "اشتراک پیش‌فرض",
"defaultSubscribeDescription": "طرح اشتراک پیش‌فرض برای کاربران جدید",
"description": "تنظیمات مربوط به ثبت‌نام کاربران را پیکربندی کنید",
"enableTrial": "فعال‌سازی دوره آزمایشی",
"enableTrialDescription": "با فعال‌سازی این گزینه، کاربران جدید در زمان ثبت‌نام یک اشتراک آزمایشی دریافت خواهند کرد",
"hour": "ساعت(ها)",
"inputPlaceholder": "لطفاً وارد کنید",
"ipRegistrationLimit": "محدودیت ثبت‌نام IP",
"ipRegistrationLimitDescription": "تعداد ثبت‌نام‌ها از یک آدرس IP را محدود کنید",
"minute": "دقیقه(ها)",
"month": "ماه(ها)",
"none": "هیچ",
"registrationLimitCount": "تعداد محدودیت ثبت‌نام",
"registrationLimitCountDescription": "تعداد ثبت‌نام‌های مجاز در هر IP در دوره محدودیت",
"registrationLimitExpire": "دوره محدودیت",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "متوقف کردن ثبت‌نام کاربران جدید",
"stopNewUserRegistrationDescription": "با فعال‌سازی، ثبت‌نام کاربران جدید غیرفعال خواهد شد",
"title": "تنظیمات ثبت‌نام",
"trialDay": "روزهای آزمایشی",
"trialDayDescription": "روزهای آزمایشی به کاربران جدید در زمان ثبت‌نام داده می‌شود",
"trialFlow": "ترافیک آزمایشی",
"trialFlowDescription": "ترافیک آزمایشی به کاربران جدید در زمان ثبت‌نام داده می‌شود"
"trialConfig": "پیکربندی آزمایشی",
"trialConfigDescription": "پیکربندی اشتراک آزمایشی، مدت و واحد زمانی برای کاربران جدید در زمان ثبت‌نام",
"year": "سال(ها)"
},
"site": {
"customData": "داده‌های سفارشی",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Lisä",
"additionalRecipientEmails": "Lisä vastaanottaja sähköpostit",
"additionalRecipients": "Lisä vastaanottajat",
"additionalRecipientsDescription": "Nämä sähköpostit saavat lähetyksen lisäksi yllä olevaan käyttäjäsuodattimeen",
"allUsers": "Kaikki käyttäjät",
"broadcastList": "Lähetyslista",
"broadcastLogs": "Lähetyspäiväkirjat",
"cancel": "Peruuta",
"cannotBeEmpty": "ei voi olla tyhjää",
"completed": "Valmis",
"confirm": "Vahvista",
"confirmDelete": "Vahvista poisto",
"content": "Sähköpostin sisältö",
"create": "Luo",
"createBroadcast": "Luo lähetys",
"createNewEmailBroadcastCampaign": "Luo uusi sähköpostilähetyskampanja",
"createSuccess": "Luotiin onnistuneesti",
"createdAt": "Luotu",
"dailyLimit": "Päivittäinen raja on oltava vähintään 1",
"dailySendLimit": "Päivittäinen lähetysraja",
"delete": "Poista",
"deleteDescription": "Tätä toimintoa ei voi peruuttaa. Oletko varma, että haluat poistaa?",
"deleteSuccess": "Poistettu onnistuneesti",
"edit": "Muokkaa",
"emailAddedToScheduledQueue": "Sähköposti lisätty aikataulutettujen lähetyksien jonoon",
"emailBroadcast": "Sähköpostilähetys",
"emailBroadcastTaskCreatedSuccessfully": "Sähköpostilähetystehtävä luotiin onnistuneesti",
"emailBroadcastTasks": "Sähköpostilähetystehtävät",
"emailContent": "Sähköpostin sisältö",
"emailInterval": "Sähköpostiväli (sekunteina)",
"emailIntervalMinimum": "Sähköpostivälin on oltava vähintään 0,1 sekuntia",
"emailMarketing": "Sähköpostimarkkinointi",
"emailTaskManager": "Sähköpostitehtävien hallinta",
"errorMessage": "Virheviesti",
"estimatedRecipients": "Arvioidut vastaanottajat",
"expiredSubscriptionUsersOnly": "Vain vanhentuneen tilauksen käyttäjät",
"expiredUsers": "Vanhentuneet käyttäjät",
"failCount": "Epäonnistumisten määrä",
"failed": "Epäonnistui",
"failedToRefreshTaskStatus": "Tehtävän tilan päivittäminen epäonnistui",
"failedToStopTask": "Tehtävän pysäyttäminen epäonnistui",
"inProgress": "Käynnissä",
"includeUsersRegisteredAfter": "Sisällytä käyttäjät, jotka on rekisteröity tämän päivämäärän jälkeen",
"includeUsersRegisteredBefore": "Sisällytä käyttäjät, jotka on rekisteröity tämän päivämäärän ennen",
"intervalTimeBetweenEmails": "Väli sähköpostien välillä",
"leaveEmptyForImmediateSend": "Jätä tyhjäksi välittömäksi lähetykseksi",
"logList": "Päiväkirjalista",
"marketingManagement": "Markkinoinnin hallinta",
"maximumNumberPerDay": "Suurin määrä sähköposteja lähetettäväksi päivässä",
"noSubscriptionUsersOnly": "Vain ei-tilauksen käyttäjät",
"nonSubscribers": "Ei-tilaajat",
"notStarted": "Ei aloitettu",
"onePerLine": "yksi per rivi",
"only": "vain",
"pending": "Odottaa",
"pleaseEnter": "Ole hyvä ja syötä",
"pleaseEnterValidEmailAddresses": "Ole hyvä ja syötä voimassa olevat sähköpostiosoitteet, yksi per rivi",
"processing": "Käsitellään...",
"progress": "Edistyminen",
"recipient": "Vastaanottaja",
"recipientEmail": "Vastaanottajan sähköposti",
"recipientType": "Vastaanottajan tyyppi",
"registrationEndDate": "Rekisteröinnin päättymispäivämäärä",
"registrationStartDate": "Rekisteröinnin aloituspäivämäärä",
"scheduleSend": "Aikatauluta lähetys",
"scheduledSend": "Aikataulutettu lähetys",
"scheduledSendTimeMustBeLater": "Aikataulutetun lähetyksen ajan on oltava myöhemmin kuin nykyinen aika",
"selectSendScope": "Valitse lähetyksen laajuus",
"selectSendTime": "Valitse lähetysaika, jätä tyhjäksi välittömäksi lähetykseksi",
"sendFailed": "Lähetys epäonnistui, yritä uudelleen",
"sendNow": "Lähetä nyt",
"sendScope": "Lähetyksen laajuus",
"sendScopeDescription": "Valitse käyttäjälaajuus sähköpostin lähettämiseen. Valitse \"Vain lisäsähköpostit\" lähettääksesi vain alla täytettyihin sähköpostiosoitteisiin",
"sendSettings": "Lähetyksen asetukset",
"sendTime": "Lähetysaika",
"sending": "Lähetetään",
"sentAt": "Lähetetty",
"specificUsers": "Erityiset käyttäjät",
"specificUsersOnly": "Vain lisäsähköpostit (ohita alustan käyttäjät)",
"status": "Tila",
"stop": "Pysäytä",
"stopped": "Pysäytetty",
"subject": "Sähköpostin aihe",
"subscribedUsers": "Tilatut käyttäjät",
"subscribedUsersOnly": "Vain tilatut käyttäjät",
"successCount": "Onnistumisten määrä",
"taskStatusRefreshed": "Tehtävän tila päivitetty",
"taskStoppedSuccessfully": "Tehtävä pysäytetty onnistuneesti",
"totalSent": "Yhteensä lähetetty",
"updateSuccess": "Päivitetty onnistuneesti",
"useMarkdownEditor": "Käytä Markdown-editoria sähköpostin sisällön kirjoittamiseen esikatselutoiminnolla",
"users": "käyttäjät",
"view": "Näytä",
"viewAndManageEmailBroadcastTasks": "Näytä ja hallitse sähköpostilähetystehtäviä",
"viewContent": "Näytä sisältö"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "ADS-asetukset",
"Announcement Management": "Ilmoitusten hallinta",
"Apple": "Apple ID",
"Application Management": "Sovellushallinta",
"Auth Control": "Todennuksen hallinta",
"Coupon Management": "Kuponkien hallinta",
"Dashboard": "Kojelauta",
"Device": "Laite",
"Document Management": "Asiakirjojen hallinta",
"Email": "Sähköposti",
"Facebook": "Facebook",
"Finance": "Rahoitus",
"General": "Yleinen",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Markkinoinnin Hallinta",
"Order Management": "Tilausten hallinta",
"Payment Config": "Maksukonfiguraatio",
"Phone Number": "Puhelinnumero",
"Product Management": "Tuotteen hallinta",
"Protocol Management": "Protokollan hallinta",
"Rule Management": "Sääntöhallinta",
"Server": "Palvelu",
"Server Management": "Palvelimen hallinta",
"Settings": "Asetukset",
"Subscribe Management": "Tilauksen hallinta",
"Subscribe Config": "Tilauksen asetukset",
"System Config": "Järjestelmän asetukset",
"System Management": "Järjestelmän hallinta",
"System Tool": "Järjestelmätyökalu",
"Telegram": "Telegram",
"Ticket Management": "Lipputoiminta",
"Twitter": "Twitter",
"User": "Käyttäjä",
"User Detail": "Käyttäjän tiedot",
"User Management": "Käyttäjien hallinta"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "toiminnot",
"app": {
"appDownloadURL": "Sovelluksen lataus-URL",
"appIcon": "Sovelluksen kuvake",
"appList": "Sovellusluettelo",
"appName": "Sovelluksen nimi",
"backupDomains": "Varmuuskopiodomainien luettelo",
"backupDomainsDescription": "Varmuuskopiodomainien luettelo domainin resoluutiota varten, yksi domain per rivi",
"batchDelete": "Poista erä",
"cancel": "Peruuta",
"communicationKey": "Viestintäavain",
"communicationKeyDescription": "Avain, jota käytetään asiakasviestintään",
"config": "Asetukset",
"configApp": "Sovelluksen asetukset",
"confirm": "Vahvista",
"confirmDelete": "Vahvista poisto",
"create": "Luo",
"createApp": "Luo sovellus",
"createSuccess": "Luotu onnistuneesti",
"defaultVersion": "Oletus",
"delete": "Poista",
"deleteWarning": "Tätä toimintoa ei voi peruuttaa",
"describeDescription": "Käytetään sovelluksen kuvaamiseen, näytetään sovellusluettelossa",
"description": "Kuvaus",
"downloadLink": "Latauslinkki",
"edit": "Muokkaa",
"editApp": "Muokkaa sovellusta",
"encryption": "Salausmenetelmä",
"encryptionDescription": "Valitse salausmenetelmä asiakasviestintään. Jos valittu, asiakas käyttää tätä menetelmää kommunikoidessaan palvelimen kanssa",
"nameDescription": "Sovelluksen nimi, näytetään sovellusluettelossa",
"platform": "Alusta",
"selectApp": "Valitse Sovellus",
"selectAppDescription": "Valitse sovellus, jota haluat konfiguroida. Kaikki asetukset koskevat valittua sovellusta",
"startupPicture": "Käynnistyskuva",
"startupPictureDescription": "Käynnistyskuva, tukee verkko- ja paikallisia kuvia. Verkkokuville, syötä täydellinen kuvan URL-osoite",
"startupPicturePreview": "Käynnistyskuvan esikatselu",
"startupPictureSkip": "Käynnistyskuvan ohitusaika",
"startupPictureSkipDescription": "Käynnistyskuvan näyttöaika sekunteina, syötä 0, jos ei näytetä",
"subscriptionProtocol": "Tilausprotokolla",
"updateSuccess": "Päivitetty onnistuneesti",
"version": "Versio"
},
"cancel": "Peruuta",
"config": {
"singleSubscriptionMode": "Yhden tilauksen tila",
"subscriptionDomain": "Tilausalue",
"subscriptionDomainDescription": "Käytetään tilaukseen; jätä tyhjäksi käyttääksesi sivuston verkkotunnusta",
"subscriptionDomainPlaceholder": "Syötä tilausalue, yksi per rivi",
"subscriptionPath": "Tilauspolku",
"subscriptionPathDescription": "Käytetään tilaukseen; varmista, että käynnistät järjestelmän uudelleen muutoksen jälkeen parhaan suorituskyvyn saavuttamiseksi",
"subscriptionPathPlaceholder": "Syötä",
"updateSuccess": "Päivitys onnistui",
"wildcardResolution": "Yleismerkkien ratkaisu",
"wildcardResolutionDescription": "Käytetään tilaukseen"
},
"confirm": "Vahvista",
"confirmDelete": "Haluatko varmasti poistaa?",
"copy": "Kopioi",
"copySuccess": "Kopioitu onnistuneesti",
"create": "Luo",
"createSubscribe": "Luo uusi tilaus",
"createSuccess": "Luonti onnistui",
"delete": "poista",
"deleteSuccess": "Poisto onnistui",
"deleteWarning": "Poiston jälkeen tietoja ei voi palauttaa, ole varovainen.",
"deviceLimit": "Laitemäärä/kpl",
"edit": "muokkaa",
"editSubscribe": "Muokkaa tilausta",
"form": {
"Day": "Päivä",
"Hour": "Tunti",
"Minute": "Minuutti",
"Month": "Kuukausi",
"NoLimit": "Ei rajoitusta",
"Year": "Vuosi",
"annualReset": "Vuosittainen Nollaus",
"basic": "Perus",
"cancel": "Peruuta",
"confirm": "Vahvista",
"deductionRatio": "Automaattinen/Manuaalinen Vähennyskonfiguraatio",
"deductionRatioDescription": "Käytetään vähennyksiin. Oletuksena järjestelmä käyttää automaattista laskenta-algoritmia. Kun manuaalinen suhde on annettu, järjestelmä laskee osuudet ajan ja liikenteen suhteen perusteella varmistaen, että kokonaismäärä on 100%.",
"description": "Kuvaus",
"deviceLimit": "Laiterajoitus",
"discount": "Alennus",
"discountDescription": "Aseta alennus yksikköhinnan perusteella",
"discountMonths": "Kuukautta",
"discountPercent": "Alennusprosentti",
"discount_price": "Alennettu hinta",
"duration": "Kesto (kuukautta)",
"groupId": "Tilausryhmä",
"inventory": "Tilausraja",
"monthlyReset": "Kuukausittainen Nollaus",
"name": "Nimi",
"noLimit": "Ei rajoitusta",
"noReset": "Ei Nollausta",
"pricing": "Hinnoittelu",
"purchaseWithDiscount": "Salli Vähennys",
"purchaseWithDiscountDescription": "Ota käyttöön tai poista käytöstä peruutustoiminto. Aktivoinnin jälkeen järjestelmä suorittaa vähennyskäsittelyn määritettyjen sääntöjen ja osuuksien mukaisesti, ja jäljelle jäävä arvo palautetaan saldolle.",
"quota": "Ostorajoitus",
"renewalReset": "Uusimisen Nollaus",
"renewalResetDescription": "Nollaa jakso uusimisen yhteydessä",
"replacement": "Uudelleenhinnan asetus (kerta)",
"resetCycle": "Nollausjakso",
"resetOn1st": "Nollaus 1. päivänä",
"selectResetCycle": "Valitse nollausjakso",
"selectSubscribeGroup": "Valitse tilausryhmä",
"selectUnitTime": "Valitse aikayksikkö",
"server": "Palvelin",
"serverGroup": "Palvelinryhmä",
"servers": "Palvelimet",
"speedLimit": "Nopeusrajoitus ",
"traffic": "Liikenne",
"unitPrice": "Yksikköhinta",
"unitTime": "Aikayksikkö"
},
"group": {
"actions": "Toiminnot",
"cancel": "Peruuta",
"confirm": "Vahvista",
"confirmDelete": "Haluatko varmasti poistaa?",
"create": "Luo",
"createSubscribeGroup": "Luo uusi tilausryhmä",
"createSuccess": "Luonti onnistui",
"delete": "Poista",
"deleteSuccess": "Poisto onnistui",
"deleteWarning": "Poiston jälkeen tietoja ei voi palauttaa, ole varovainen.",
"description": "Kuvaus",
"edit": "Muokkaa",
"editSubscribeGroup": "Muokkaa tilausryhmää",
"form": {
"cancel": "Peruuta",
"confirm": "Vahvista",
"description": "Kuvaus",
"name": "Nimi"
},
"name": "Nimi",
"title": "Tilausryhmien lista",
"updateSuccess": "Päivitys onnistui",
"updatedAt": "Päivitetty"
},
"inventory": "Tilausraja",
"name": "Nimi",
"quota": "Ostorajoitus/kerta",
"replacement": "Nollaa hinta/kerta",
"sell": "myydä",
"show": "Näytä",
"sold": "Tilausmäärä",
"subscribe": "Tilaa",
"subscribeGroup": "Tilaa ryhmä",
"tabs": {
"subscribe": "Tilaa",
"subscribeApp": "Sovelluksen asetukset",
"subscribeConfig": "Tilausasetukset",
"subscribeGroup": "Tilaa ryhmä"
},
"traffic": "liikenne",
"unitPrice": "Yksikköhinta",
"updateSuccess": "Päivitys onnistui"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Tyyppi",
"updateSuccess": "Päivitys onnistui",
"updatedAt": "Päivitetty",
"userAccount": "Käyttäjätili",
"user": "Käyttäjä",
"userDetail": "Käyttäjän tiedot",
"userId": "Käyttäjän ID"
},
+118 -147
View File
@@ -1,161 +1,132 @@
{
"actions": "toiminnot",
"app": {
"appDownloadURL": "Sovelluksen lataus-URL",
"appIcon": "Sovelluksen kuvake",
"appList": "Sovellusluettelo",
"appName": "Sovelluksen nimi",
"backupDomains": "Varmuuskopiodomainien luettelo",
"backupDomainsDescription": "Varmuuskopiodomainien luettelo domainin resoluutiota varten, yksi domain per rivi",
"batchDelete": "Poista erä",
"actions": {
"add": "Lisää",
"batchDelete": "Ryhmän poistaminen",
"batchDeleteSuccess": "Poistettiin onnistuneesti {count} asiakasta",
"batchDeleteWarning": "Oletko varma, että haluat poistaa valitut {count} asiakasta?",
"cancel": "Peruuta",
"communicationKey": "Viestintäavain",
"communicationKeyDescription": "Avain, jota käytetään asiakasviestintään",
"config": "Asetukset",
"configApp": "Sovelluksen asetukset",
"confirm": "Vahvista",
"confirmDelete": "Vahvista poisto",
"create": "Luo",
"createApp": "Luo sovellus",
"createSuccess": "Luotu onnistuneesti",
"defaultVersion": "Oletus",
"createSuccess": "Luotiin onnistuneesti",
"delete": "Poista",
"deleteWarning": "Tätä toimintoa ei voi peruuttaa",
"describeDescription": "Käytetään sovelluksen kuvaamiseen, näytetään sovellusluettelossa",
"description": "Kuvaus",
"downloadLink": "Latauslinkki",
"deleteFailed": "Poisto epäonnistui",
"deleteSuccess": "Poistettu onnistuneesti",
"deleteWarning": "Tätä toimintoa ei voi peruuttaa. Oletko varma, että haluat poistaa tämän asiakkaan?",
"edit": "Muokkaa",
"editApp": "Muokkaa sovellusta",
"encryption": "Salausmenetelmä",
"encryptionDescription": "Valitse salausmenetelmä asiakasviestintään. Jos valittu, asiakas käyttää tätä menetelmää kommunikoidessaan palvelimen kanssa",
"nameDescription": "Sovelluksen nimi, näytetään sovellusluettelossa",
"platform": "Alusta",
"selectApp": "Valitse Sovellus",
"selectAppDescription": "Valitse sovellus, jota haluat konfiguroida. Kaikki asetukset koskevat valittua sovellusta",
"startupPicture": "Käynnistyskuva",
"startupPictureDescription": "Käynnistyskuva, tukee verkko- ja paikallisia kuvia. Verkkokuville, syötä täydellinen kuvan URL-osoite",
"startupPicturePreview": "Käynnistyskuvan esikatselu",
"startupPictureSkip": "Käynnistyskuvan ohitusaika",
"startupPictureSkipDescription": "Käynnistyskuvan näyttöaika sekunteina, syötä 0, jos ei näytetä",
"subscriptionProtocol": "Tilausprotokolla",
"updateSuccess": "Päivitetty onnistuneesti",
"version": "Versio"
"save": "Tallenna",
"saveFailed": "Tallennus epäonnistui",
"update": "Päivitä",
"updateSuccess": "Päivitys onnistui"
},
"cancel": "Peruuta",
"config": {
"singleSubscriptionMode": "Yhden tilauksen tila",
"singleSubscriptionModeDescription": "Kun tämä on käytössä, kaikki käyttäjätilaukset muunnetaan saldoksi",
"subscriptionDomain": "Tilausalue",
"subscriptionDomainDescription": "Käytetään tilaukseen; jätä tyhjäksi käyttääksesi sivuston verkkotunnusta",
"subscriptionDomainPlaceholder": "Syötä tilausalue, yksi per rivi",
"subscriptionPath": "Tilauspolku",
"subscriptionPathDescription": "Käytetään tilaukseen; varmista, että käynnistät järjestelmän uudelleen muutoksen jälkeen parhaan suorituskyvyn saavuttamiseksi",
"subscriptionPathPlaceholder": "Syötä",
"updateSuccess": "Päivitys onnistui",
"wildcardResolution": "Yleismerkkien ratkaisu",
"wildcardResolutionDescription": "Käytetään tilaukseen"
"description": "Hallitse tilausjärjestelmän asetuksia",
"singleSubscriptionMode": "Yksittäinen tilausmoodi",
"singleSubscriptionModeDescription": "Rajoita käyttäjät yhteen aktiiviseen tilaukseen. Olemassa olevat tilaukset eivät vaikuta",
"subscriptionDomain": "Tilauksen verkkotunnus",
"subscriptionDomainDescription": "Mukautettu verkkotunnus tilauslinkeille",
"subscriptionDomainPlaceholder": "Syötä tilauksen verkkotunnus, yksi per rivi",
"subscriptionPath": "Tilauksen polku",
"subscriptionPathDescription": "Mukautettu polku tilauspisteille (parempi suorituskyky järjestelmän uudelleenkäynnistyksen jälkeen)",
"subscriptionPathPlaceholder": "Syötä tilauksen polku",
"title": "Tilauksen asetukset",
"updateError": "Päivitys epäonnistui",
"updateSuccess": "Asetukset päivitettiin onnistuneesti",
"userAgentLimit": "{userAgent} Rajoitus",
"userAgentLimitDescription": "Ota käyttöön pääsyn rajoitukset perustuen {userAgent}",
"userAgentList": "{userAgent} Valkoinen lista",
"userAgentListDescription": "Sallitut {userAgent} tilauspääsyyn, yksi per rivi. Määritetty sovellus {userAgent} lisätään automaattisesti",
"userAgentListPlaceholder": "Syötä sallitut {userAgent}, yksi per rivi",
"wildcardResolution": "Wildcard-ratkaisu",
"wildcardResolutionDescription": "Ota käyttöön wildcard-verkkotunnuksen ratkaisu tilauksille"
},
"confirm": "Vahvista",
"confirmDelete": "Haluatko varmasti poistaa?",
"copy": "Kopioi",
"copySuccess": "Kopioitu onnistuneesti",
"create": "Luo",
"createSubscribe": "Luo uusi tilaus",
"createSuccess": "Luonti onnistui",
"delete": "poista",
"deleteSuccess": "Poisto onnistui",
"deleteWarning": "Poiston jälkeen tietoja ei voi palauttaa, ole varovainen.",
"deviceLimit": "Laitemäärä/kpl",
"edit": "muokkaa",
"editSubscribe": "Muokkaa tilausta",
"form": {
"Day": "Päivä",
"Hour": "Tunti",
"Minute": "Minuutti",
"Month": "Kuukausi",
"NoLimit": "Ei rajoitusta",
"Year": "Vuosi",
"annualReset": "Vuosittainen Nollaus",
"basic": "Perus",
"cancel": "Peruuta",
"confirm": "Vahvista",
"deductionRatio": "Automaattinen/Manuaalinen Vähennyskonfiguraatio",
"deductionRatioDescription": "Käytetään vähennyksiin. Oletuksena järjestelmä käyttää automaattista laskenta-algoritmia. Kun manuaalinen suhde on annettu, järjestelmä laskee osuudet ajan ja liikenteen suhteen perusteella varmistaen, että kokonaismäärä on 100%.",
"description": "Kuvaus",
"deviceLimit": "Laiterajoitus",
"discount": "Alennus",
"discountDescription": "Aseta alennus yksikköhinnan perusteella",
"discountMonths": "Kuukautta",
"discountPercent": "Alennusprosentti",
"discount_price": "Alennettu hinta",
"duration": "Kesto (kuukautta)",
"groupId": "Tilausryhmä",
"inventory": "Tilausraja",
"monthlyReset": "Kuukausittainen Nollaus",
"name": "Nimi",
"noLimit": "Ei rajoitusta",
"noReset": "Ei Nollausta",
"pricing": "Hinnoittelu",
"purchaseWithDiscount": "Salli Vähennys",
"purchaseWithDiscountDescription": "Ota käyttöön tai poista käytöstä peruutustoiminto. Aktivoinnin jälkeen järjestelmä suorittaa vähennyskäsittelyn määritettyjen sääntöjen ja osuuksien mukaisesti, ja jäljelle jäävä arvo palautetaan saldolle.",
"quota": "Ostorajoitus",
"renewalReset": "Uusimisen Nollaus",
"renewalResetDescription": "Nollaa jakso uusimisen yhteydessä",
"replacement": "Uudelleenhinnan asetus (kerta)",
"resetCycle": "Nollausjakso",
"resetOn1st": "Nollaus 1. päivänä",
"selectResetCycle": "Valitse nollausjakso",
"selectSubscribeGroup": "Valitse tilausryhmä",
"selectUnitTime": "Valitse aikayksikkö",
"server": "Palvelin",
"serverGroup": "Palvelinryhmä",
"servers": "Palvelimet",
"speedLimit": "Nopeusrajoitus ",
"traffic": "Liikenne",
"unitPrice": "Yksikköhinta",
"unitTime": "Aikayksikkö"
},
"group": {
"actions": "Toiminnot",
"cancel": "Peruuta",
"confirm": "Vahvista",
"confirmDelete": "Haluatko varmasti poistaa?",
"create": "Luo",
"createSubscribeGroup": "Luo uusi tilausryhmä",
"createSuccess": "Luonti onnistui",
"delete": "Poista",
"deleteSuccess": "Poisto onnistui",
"deleteWarning": "Poiston jälkeen tietoja ei voi palauttaa, ole varovainen.",
"description": "Kuvaus",
"edit": "Muokkaa",
"editSubscribeGroup": "Muokkaa tilausryhmää",
"form": {
"cancel": "Peruuta",
"confirm": "Vahvista",
"description": "Kuvaus",
"name": "Nimi"
"addTitle": "Lisää asiakas",
"descriptions": {
"description": "Yksityiskohtainen asiakaskuvaus",
"downloadLink": "alustan lataus-URL",
"icon": "Ikonin URL tai base64-koodaus",
"name": "Asiakkaan näyttönimi",
"outputFormat": "Tilauksen konfiguraatiotiedoston muoto",
"scheme": {
"base64Encoding": "Base64-koodaus",
"functions": "Tukee toimintoja:",
"jsonStringify": "JSON-objekti merkkijonoksi",
"nameVariable": "sivuston nimi",
"title": "URL-skeeman malli",
"urlEncoding": "URL-koodaus",
"urlVariable": "tilaus-URL",
"variables": "Tukee muuttujia:"
},
"template": {
"description": "Käytä Go-mallin syntaksia luodaksesi tilauksen konfiguraatiotiedostoja",
"functions": "Mallitoiminnot:",
"if": "ehdolliset lauseet",
"nodes": "proxy-solmujen lista",
"range": "iteroi taulukoita",
"siteName": "sivuston nimi",
"sprig": "Sprig-toimintokirjasto (merkkijonojen käsittely, päivämäärät jne.)",
"subscribeName": "tilauksen nimi",
"title": "Go-mallin syntaksi",
"userInfo": "käyttäjätiedot (liikenne, vanheneminen jne.)",
"variables": "Saatavilla olevat muuttujat:"
},
"userAgentPrefix": "Asiakkaan tunniste erottamaan eri asiakkaita"
},
"name": "Nimi",
"title": "Tilausryhmien lista",
"updateSuccess": "Päivitys onnistui",
"updatedAt": "Päivitetty"
"editTitle": "Muokkaa asiakasta",
"fields": {
"description": "Kuvaus",
"icon": "Ikoni",
"name": "Nimi",
"outputFormat": "Tulostusmuoto",
"scheme": "URL-skeema",
"template": "Tilauksen tiedostomalli"
},
"tabs": {
"basic": "Perustiedot",
"download": "Lataukset",
"template": "Mallit"
},
"validation": {
"nameRequired": "Asiakkaan nimi on pakollinen",
"userAgentRequiredSuffix": "on pakollinen"
}
},
"inventory": "Tilausraja",
"name": "Nimi",
"quota": "Ostorajoitus/kerta",
"replacement": "Nollaa hinta/kerta",
"sell": "myydä",
"show": "Näytä",
"sold": "Tilausmäärä",
"subscribe": "Tilaa",
"subscribeGroup": "Tilaa ryhmä",
"tabs": {
"subscribe": "Tilaa",
"subscribeApp": "Sovelluksen asetukset",
"subscribeConfig": "Tilausasetukset",
"subscribeGroup": "Tilaa ryhmä"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Plain Text",
"yaml": "YAML"
},
"traffic": "liikenne",
"unitPrice": "Yksikköhinta",
"updateSuccess": "Päivitys onnistui"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Asiakashallinta"
},
"table": {
"columns": {
"default": "Oletus",
"description": "Kuvaus",
"name": "Asiakkaan nimi",
"outputFormat": "Tulostusmuoto",
"supportedPlatforms": "Tuetut alustat"
}
},
"templatePreview": {
"base64": {
"decodeError": "Dekoodaus epäonnistui: Sisältö ei ole voimassa olevaa Base64-muotoa",
"decodedContent": "Dekoodattu sisältö",
"originalContent": "Alkuperäinen sisältö (Base64)"
},
"failed": "Esikatselu epäonnistui",
"loading": "Ladataan...",
"preview": "Esikatselu",
"title": "Mallin esikatselu"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "päivä(ä)",
"defaultSubscribe": "Oletusliittymä",
"defaultSubscribeDescription": "Oletusliittymäsuunnitelma uusille käyttäjille",
"description": "Määritä käyttäjien rekisteröintiin liittyvät asetukset",
"enableTrial": "Ota käyttöön kokeilu",
"enableTrialDescription": "Kun tämä on käytössä, uudet käyttäjät saavat kokeilutilauksen rekisteröitymisen yhteydessä",
"hour": "Tunti(tunnit)",
"inputPlaceholder": "Ole hyvä ja syötä",
"ipRegistrationLimit": "IP-rekisteröintiraja",
"ipRegistrationLimitDescription": "Rajoita rekisteröintien määrää yhdestä IP-osoitteesta",
"minute": "Minuutti(minuutit)",
"month": "Kuukausi(kkeet)",
"none": "Ei mitään",
"registrationLimitCount": "Rekisteröintirajamäärä",
"registrationLimitCountDescription": "Rekisteröintien määrä, joka sallitaan IP-osoitteelta rajoitusjakson aikana",
"registrationLimitExpire": "Rajoitusjakso",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Lopeta uusien käyttäjien rekisteröinti",
"stopNewUserRegistrationDescription": "Kun tämä on käytössä, uusien käyttäjien rekisteröinti estetään",
"title": "Rekisteröintiasetukset",
"trialDay": "Kokeilupäivät",
"trialDayDescription": "Kokeilupäivät uusille käyttäjille rekisteröitymisen yhteydessä",
"trialFlow": "Kokeiluliikenne",
"trialFlowDescription": "Kokeiluliikenne uusille käyttäjille rekisteröitymisen yhteydessä"
"trialConfig": "Kokeilukonfiguraatio",
"trialConfigDescription": "Määritä kokeilutilaus, kesto ja aikayksikkö uusille käyttäjille rekisteröitymisen yhteydessä",
"year": "Vuosi(vuodet)"
},
"site": {
"customData": "Mukautettu tieto",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Supplémentaire",
"additionalRecipientEmails": "Emails supplémentaires des destinataires",
"additionalRecipients": "Destinataires supplémentaires",
"additionalRecipientsDescription": "Ces emails recevront la diffusion en plus du filtre utilisateur ci-dessus",
"allUsers": "Tous les utilisateurs",
"broadcastList": "Liste de diffusion",
"broadcastLogs": "Journaux de diffusion",
"cancel": "Annuler",
"cannotBeEmpty": "ne peut pas être vide",
"completed": "Terminé",
"confirm": "Confirmer",
"confirmDelete": "Confirmer la suppression",
"content": "Contenu de l'email",
"create": "Créer",
"createBroadcast": "Créer une diffusion",
"createNewEmailBroadcastCampaign": "Créer une nouvelle campagne de diffusion par email",
"createSuccess": "Créé avec succès",
"createdAt": "Créé le",
"dailyLimit": "La limite quotidienne doit être d'au moins 1",
"dailySendLimit": "Limite d'envoi quotidienne",
"delete": "Supprimer",
"deleteDescription": "Cette opération ne peut pas être annulée. Êtes-vous sûr de vouloir supprimer ?",
"deleteSuccess": "Supprimé avec succès",
"edit": "Modifier",
"emailAddedToScheduledQueue": "Email ajouté à la file d'envoi programmée",
"emailBroadcast": "Diffusion par email",
"emailBroadcastTaskCreatedSuccessfully": "Tâche de diffusion par email créée avec succès",
"emailBroadcastTasks": "Tâches de diffusion par email",
"emailContent": "Contenu de l'email",
"emailInterval": "Intervalle d'envoi des emails (secondes)",
"emailIntervalMinimum": "L'intervalle d'email doit être d'au moins 0,1 seconde",
"emailMarketing": "Marketing par email",
"emailTaskManager": "Gestionnaire de tâches d'email",
"errorMessage": "Message d'erreur",
"estimatedRecipients": "Destinataires estimés",
"expiredSubscriptionUsersOnly": "Utilisateurs avec abonnement expiré uniquement",
"expiredUsers": "Utilisateurs expirés",
"failCount": "Nombre d'échecs",
"failed": "Échoué",
"failedToRefreshTaskStatus": "Échec de la mise à jour du statut de la tâche",
"failedToStopTask": "Échec de l'arrêt de la tâche",
"inProgress": "En cours",
"includeUsersRegisteredAfter": "Inclure les utilisateurs enregistrés à partir de cette date",
"includeUsersRegisteredBefore": "Inclure les utilisateurs enregistrés avant cette date",
"intervalTimeBetweenEmails": "Temps d'intervalle entre chaque email",
"leaveEmptyForImmediateSend": "Laissez vide pour un envoi immédiat",
"logList": "Liste des journaux",
"marketingManagement": "Gestion du marketing",
"maximumNumberPerDay": "Nombre maximum d'emails à envoyer par jour",
"noSubscriptionUsersOnly": "Aucun utilisateur avec abonnement uniquement",
"nonSubscribers": "Non-abonnés",
"notStarted": "Non commencé",
"onePerLine": "un par ligne",
"only": "uniquement",
"pending": "En attente",
"pleaseEnter": "Veuillez entrer",
"pleaseEnterValidEmailAddresses": "Veuillez entrer des adresses email valides, une par ligne",
"processing": "Traitement...",
"progress": "Progrès",
"recipient": "Destinataire",
"recipientEmail": "Email du destinataire",
"recipientType": "Type de destinataire",
"registrationEndDate": "Date de fin d'inscription",
"registrationStartDate": "Date de début d'inscription",
"scheduleSend": "Planifier l'envoi",
"scheduledSend": "Envoi programmé",
"scheduledSendTimeMustBeLater": "L'heure d'envoi programmée doit être ultérieure à l'heure actuelle",
"selectSendScope": "Sélectionner le champ d'envoi",
"selectSendTime": "Sélectionner l'heure d'envoi, laissez vide pour un envoi immédiat",
"sendFailed": "Échec de l'envoi, veuillez réessayer",
"sendNow": "Envoyer maintenant",
"sendScope": "Champ d'envoi",
"sendScopeDescription": "Choisissez le champ d'utilisateurs pour l'envoi d'emails. Sélectionnez \"Emails supplémentaires uniquement\" pour envoyer uniquement aux adresses email remplies ci-dessous",
"sendSettings": "Paramètres d'envoi",
"sendTime": "Heure d'envoi",
"sending": "Envoi en cours",
"sentAt": "Envoyé le",
"specificUsers": "Utilisateurs spécifiques",
"specificUsersOnly": "Emails supplémentaires uniquement (ignorer les utilisateurs de la plateforme)",
"status": "Statut",
"stop": "Arrêter",
"stopped": "Arrêté",
"subject": "Objet de l'email",
"subscribedUsers": "Utilisateurs abonnés",
"subscribedUsersOnly": "Utilisateurs abonnés uniquement",
"successCount": "Nombre de succès",
"taskStatusRefreshed": "Statut de la tâche mis à jour",
"taskStoppedSuccessfully": "Tâche arrêtée avec succès",
"totalSent": "Total envoyé",
"updateSuccess": "Mis à jour avec succès",
"useMarkdownEditor": "Utilisez l'éditeur Markdown pour rédiger le contenu de l'email avec une fonctionnalité d'aperçu",
"users": "utilisateurs",
"view": "Voir",
"viewAndManageEmailBroadcastTasks": "Voir et gérer les tâches de diffusion par email",
"viewContent": "Voir le contenu"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "Configuration ADS",
"Announcement Management": "Gestion des annonces",
"Apple": "Identifiant Apple",
"Application Management": "Gestion des applications",
"Auth Control": "Contrôle d'authentification",
"Coupon Management": "Gestion des coupons",
"Dashboard": "Tableau de bord",
"Device": "Appareil",
"Document Management": "Gestion des documents",
"Email": "E-mail",
"Facebook": "Facebook",
"Finance": "Finance",
"General": "Général",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Gestion du marketing",
"Order Management": "Gestion des commandes",
"Payment Config": "Configuration de paiement",
"Phone Number": "Numéro de téléphone",
"Product Management": "Gestion de produit",
"Protocol Management": "Gestion de protocole",
"Rule Management": "Gestion des règles",
"Server": "Serveur",
"Server Management": "Gestion des services",
"Settings": "Paramètres",
"Subscribe Management": "Gestion des abonnements",
"Subscribe Config": "Configuration d'abonnement",
"System Config": "Configuration du système",
"System Management": "Gestion du système",
"System Tool": "Outil Système",
"Telegram": "Telegram",
"Ticket Management": "Gestion des billets",
"Twitter": "Twitter",
"User": "Utilisateur",
"User Detail": "Détail de l'utilisateur",
"User Management": "Gestion des utilisateurs"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "actions",
"app": {
"appDownloadURL": "URL de téléchargement de l'application",
"appIcon": "Icône de l'application",
"appList": "Liste des applications",
"appName": "Nom de l'application",
"backupDomains": "Liste des domaines de sauvegarde",
"backupDomainsDescription": "Liste des domaines de sauvegarde pour la résolution de domaine, un domaine par ligne",
"batchDelete": "Suppression par lot",
"cancel": "Annuler",
"communicationKey": "Clé de communication",
"communicationKeyDescription": "Clé utilisée pour la communication client",
"config": "Configuration",
"configApp": "Configuration de l'application",
"confirm": "Confirmer",
"confirmDelete": "Confirmer la suppression",
"create": "Créer",
"createApp": "Créer une application",
"createSuccess": "Créé avec succès",
"defaultVersion": "Par défaut",
"delete": "Supprimer",
"deleteWarning": "Cette action est irréversible",
"describeDescription": "Utilisé pour décrire l'application, affiché dans la liste des applications",
"description": "Description",
"downloadLink": "Lien de téléchargement",
"edit": "Modifier",
"editApp": "Modifier l'application",
"encryption": "Méthode de chiffrement",
"encryptionDescription": "Choisissez la méthode de chiffrement pour la communication client. Si elle est sélectionnée, le client utilisera cette méthode pour communiquer avec le serveur",
"nameDescription": "Nom de l'application, affiché dans la liste des applications",
"platform": "Plateforme",
"selectApp": "Sélectionner l'application",
"selectAppDescription": "Sélectionnez l'application à configurer, tous les paramètres s'appliqueront à l'application sélectionnée",
"startupPicture": "Image de démarrage",
"startupPictureDescription": "Image de démarrage, prend en charge les images réseau et locales. Pour les images réseau, veuillez entrer l'URL complète de l'image",
"startupPicturePreview": "Aperçu de l'image de démarrage",
"startupPictureSkip": "Temps de saut de l'image de démarrage",
"startupPictureSkipDescription": "Temps d'affichage de l'image de démarrage en secondes, entrez 0 pour ne pas afficher",
"subscriptionProtocol": "Protocole d'abonnement",
"updateSuccess": "Mis à jour avec succès",
"version": "Version"
},
"cancel": "Annuler",
"config": {
"singleSubscriptionMode": "Mode d'abonnement unique",
"subscriptionDomain": "Domaine d'abonnement",
"subscriptionDomainDescription": "Utilisé pour l'abonnement ; laissez vide pour utiliser le domaine du site",
"subscriptionDomainPlaceholder": "Entrez le domaine d'abonnement, un par ligne",
"subscriptionPath": "Chemin d'abonnement",
"subscriptionPathDescription": "Utilisé pour l'abonnement ; assurez-vous de redémarrer le système après modification pour des performances optimales",
"subscriptionPathPlaceholder": "Entrez",
"updateSuccess": "Mise à jour réussie",
"wildcardResolution": "Résolution générique",
"wildcardResolutionDescription": "Utilisé pour l'abonnement"
},
"confirm": "Confirmer",
"confirmDelete": "Êtes-vous sûr de vouloir supprimer ?",
"copy": "Copier",
"copySuccess": "Copié avec succès",
"create": "Créer",
"createSubscribe": "Créer un abonnement",
"createSuccess": "Création réussie",
"delete": "Supprimer",
"deleteSuccess": "Suppression réussie",
"deleteWarning": "Une fois supprimées, les données ne peuvent pas être récupérées. Veuillez procéder avec prudence.",
"deviceLimit": "Nombre d'appareils",
"edit": "Éditer",
"editSubscribe": "Modifier l'abonnement",
"form": {
"Day": "Jour",
"Hour": "Heure",
"Minute": "Minute",
"Month": "Mois",
"NoLimit": "Pas de limite",
"Year": "Année",
"annualReset": "Réinitialisation Annuelle",
"basic": "Basique",
"cancel": "Annuler",
"confirm": "Confirmer",
"deductionRatio": "Configuration de Déduction Automatique/Manuelle",
"deductionRatioDescription": "Utilisé pour la déduction. Par défaut, le système adopte un algorithme de calcul automatique. Lorsqu'un ratio manuel est fourni, le système calcule les proportions en fonction du temps et du ratio de trafic, en veillant à ce que le total soit égal à 100%.",
"description": "Description",
"deviceLimit": "Limite d'appareils",
"discount": "Remise",
"discountDescription": "Remise basée sur le prix unitaire",
"discountMonths": "mois",
"discountPercent": "Pourcentage de remise",
"discount_price": "Prix remisé",
"duration": "Durée (mois)",
"groupId": "Groupe d'abonnement",
"inventory": "Limite d'abonnement",
"monthlyReset": "Réinitialisation Mensuelle",
"name": "Nom",
"noLimit": "Illimité",
"noReset": "Pas de Réinitialisation",
"pricing": "Tarification",
"purchaseWithDiscount": "Autoriser la Déduction",
"purchaseWithDiscountDescription": "Activer ou désactiver la fonctionnalité de désabonnement. Après activation, le système effectuera un traitement de déduction selon les règles et proportions configurées, et la valeur restante sera retournée au solde.",
"quota": "Quantité d'achat limitée",
"renewalReset": "Réinitialisation au Renouvellement",
"renewalResetDescription": "Réinitialiser le cycle lors du renouvellement",
"replacement": "Prix de réinitialisation (par fois)",
"resetCycle": "Cycle de Réinitialisation",
"resetOn1st": "Réinitialisation le 1er",
"selectResetCycle": "Veuillez sélectionner un cycle de réinitialisation",
"selectSubscribeGroup": "Veuillez sélectionner un groupe d'abonnement",
"selectUnitTime": "Veuillez sélectionner l'unité de temps",
"server": "Serveur",
"serverGroup": "Groupe de serveurs",
"servers": "Serveurs",
"speedLimit": "Limite de vitesse ",
"traffic": "Trafic",
"unitPrice": "Prix unitaire",
"unitTime": "Unité de temps"
},
"group": {
"actions": "Actions",
"cancel": "Annuler",
"confirm": "Confirmer",
"confirmDelete": "Êtes-vous sûr de vouloir supprimer ?",
"create": "Créer",
"createSubscribeGroup": "Créer un groupe d'abonnement",
"createSuccess": "Création réussie",
"delete": "Supprimer",
"deleteSuccess": "Suppression réussie",
"deleteWarning": "Les données ne peuvent pas être récupérées après suppression, veuillez procéder avec prudence.",
"description": "Description",
"edit": "Éditer",
"editSubscribeGroup": "Éditer le groupe d'abonnement",
"form": {
"cancel": "Annuler",
"confirm": "Confirmer",
"description": "Description",
"name": "Nom"
},
"name": "Nom",
"title": "Liste des groupes d'abonnement",
"updateSuccess": "Mise à jour réussie",
"updatedAt": "Date de mise à jour"
},
"inventory": "Limite d'abonnement",
"name": "Nom",
"quota": "Limite d'achat/par fois",
"replacement": "Réinitialiser le prix/par fois",
"sell": "Vente",
"show": "Afficher",
"sold": "Nombre d'abonnements",
"subscribe": "S'abonner",
"subscribeGroup": "S'abonner au groupe",
"tabs": {
"subscribe": "S'abonner",
"subscribeApp": "Configuration de l'application",
"subscribeConfig": "Configuration de l'abonnement",
"subscribeGroup": "Groupe d'abonnement"
},
"traffic": "trafic",
"unitPrice": "Prix unitaire",
"updateSuccess": "Mise à jour réussie"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Type",
"updateSuccess": "Mise à jour réussie",
"updatedAt": "Date de mise à jour",
"userAccount": "Compte utilisateur",
"user": "Utilisateur",
"userDetail": "Détails de l'utilisateur",
"userId": "ID de l'utilisateur"
},
+112 -141
View File
@@ -1,161 +1,132 @@
{
"actions": "actions",
"app": {
"appDownloadURL": "URL de téléchargement de l'application",
"appIcon": "Icône de l'application",
"appList": "Liste des applications",
"appName": "Nom de l'application",
"backupDomains": "Liste des domaines de sauvegarde",
"backupDomainsDescription": "Liste des domaines de sauvegarde pour la résolution de domaine, un domaine par ligne",
"actions": {
"add": "Ajouter",
"batchDelete": "Suppression par lot",
"batchDeleteSuccess": "Suppression de {count} clients réussie",
"batchDeleteWarning": "Êtes-vous sûr de vouloir supprimer les {count} clients sélectionnés ?",
"cancel": "Annuler",
"communicationKey": "Clé de communication",
"communicationKeyDescription": "Clé utilisée pour la communication client",
"config": "Configuration",
"configApp": "Configuration de l'application",
"confirm": "Confirmer",
"confirmDelete": "Confirmer la suppression",
"create": "Créer",
"createApp": "Créer une application",
"createSuccess": "Créé avec succès",
"defaultVersion": "Par défaut",
"delete": "Supprimer",
"deleteWarning": "Cette action est irréversible",
"describeDescription": "Utilisé pour décrire l'application, affiché dans la liste des applications",
"description": "Description",
"downloadLink": "Lien de téléchargement",
"deleteFailed": "Échec de la suppression",
"deleteSuccess": "Supprimé avec succès",
"deleteWarning": "Cette opération ne peut pas être annulée. Êtes-vous sûr de vouloir supprimer ce client ?",
"edit": "Modifier",
"editApp": "Modifier l'application",
"encryption": "Méthode de chiffrement",
"encryptionDescription": "Choisissez la méthode de chiffrement pour la communication client. Si elle est sélectionnée, le client utilisera cette méthode pour communiquer avec le serveur",
"nameDescription": "Nom de l'application, affiché dans la liste des applications",
"platform": "Plateforme",
"selectApp": "Sélectionner l'application",
"selectAppDescription": "Sélectionnez l'application à configurer, tous les paramètres s'appliqueront à l'application sélectionnée",
"startupPicture": "Image de démarrage",
"startupPictureDescription": "Image de démarrage, prend en charge les images réseau et locales. Pour les images réseau, veuillez entrer l'URL complète de l'image",
"startupPicturePreview": "Aperçu de l'image de démarrage",
"startupPictureSkip": "Temps de saut de l'image de démarrage",
"startupPictureSkipDescription": "Temps d'affichage de l'image de démarrage en secondes, entrez 0 pour ne pas afficher",
"subscriptionProtocol": "Protocole d'abonnement",
"updateSuccess": "Mis à jour avec succès",
"version": "Version"
"save": "Enregistrer",
"saveFailed": "Échec de l'enregistrement",
"update": "Mettre à jour",
"updateSuccess": "Mis à jour avec succès"
},
"cancel": "Annuler",
"config": {
"description": "Gérer les paramètres du système d'abonnement",
"singleSubscriptionMode": "Mode d'abonnement unique",
"singleSubscriptionModeDescription": "Lorsqu'il est activé, tous les abonnements des utilisateurs seront convertis en solde",
"singleSubscriptionModeDescription": "Limiter les utilisateurs à un abonnement actif. Les abonnements existants ne sont pas affectés",
"subscriptionDomain": "Domaine d'abonnement",
"subscriptionDomainDescription": "Utilisé pour l'abonnement ; laissez vide pour utiliser le domaine du site",
"subscriptionDomainDescription": "Domaine personnalisé pour les liens d'abonnement",
"subscriptionDomainPlaceholder": "Entrez le domaine d'abonnement, un par ligne",
"subscriptionPath": "Chemin d'abonnement",
"subscriptionPathDescription": "Utilisé pour l'abonnement ; assurez-vous de redémarrer le système après modification pour des performances optimales",
"subscriptionPathPlaceholder": "Entrez",
"updateSuccess": "Mise à jour réussie",
"wildcardResolution": "Résolution générique",
"wildcardResolutionDescription": "Utilisé pour l'abonnement"
"subscriptionPathDescription": "Chemin personnalisé pour les points de terminaison d'abonnement (meilleure performance après le redémarrage du système)",
"subscriptionPathPlaceholder": "Entrez le chemin d'abonnement",
"title": "Configuration de l'abonnement",
"updateError": "Échec de la mise à jour",
"updateSuccess": "Paramètres mis à jour avec succès",
"userAgentLimit": "Restriction {userAgent}",
"userAgentLimitDescription": "Activer les restrictions d'accès basées sur {userAgent}",
"userAgentList": "Liste blanche {userAgent}",
"userAgentListDescription": "Autorisé {userAgent} pour l'accès à l'abonnement, un par ligne. L'application configurée {userAgent} sera automatiquement incluse",
"userAgentListPlaceholder": "Entrez {userAgent} autorisés, un par ligne",
"wildcardResolution": "Résolution de wildcard",
"wildcardResolutionDescription": "Activer la résolution de domaine wildcard pour les abonnements"
},
"confirm": "Confirmer",
"confirmDelete": "Êtes-vous sûr de vouloir supprimer ?",
"copy": "Copier",
"copySuccess": "Copié avec succès",
"create": "Créer",
"createSubscribe": "Créer un abonnement",
"createSuccess": "Création réussie",
"delete": "Supprimer",
"deleteSuccess": "Suppression réussie",
"deleteWarning": "Une fois supprimées, les données ne peuvent pas être récupérées. Veuillez procéder avec prudence.",
"deviceLimit": "Nombre d'appareils",
"edit": "Éditer",
"editSubscribe": "Modifier l'abonnement",
"form": {
"Day": "Jour",
"Hour": "Heure",
"Minute": "Minute",
"Month": "Mois",
"NoLimit": "Pas de limite",
"Year": "Année",
"annualReset": "Réinitialisation Annuelle",
"basic": "Basique",
"cancel": "Annuler",
"confirm": "Confirmer",
"deductionRatio": "Configuration de Déduction Automatique/Manuelle",
"deductionRatioDescription": "Utilisé pour la déduction. Par défaut, le système adopte un algorithme de calcul automatique. Lorsqu'un ratio manuel est fourni, le système calcule les proportions en fonction du temps et du ratio de trafic, en veillant à ce que le total soit égal à 100%.",
"description": "Description",
"deviceLimit": "Limite d'appareils",
"discount": "Remise",
"discountDescription": "Remise basée sur le prix unitaire",
"discountMonths": "mois",
"discountPercent": "Pourcentage de remise",
"discount_price": "Prix remisé",
"duration": "Durée (mois)",
"groupId": "Groupe d'abonnement",
"inventory": "Limite d'abonnement",
"monthlyReset": "Réinitialisation Mensuelle",
"name": "Nom",
"noLimit": "Illimité",
"noReset": "Pas de Réinitialisation",
"pricing": "Tarification",
"purchaseWithDiscount": "Autoriser la Déduction",
"purchaseWithDiscountDescription": "Activer ou désactiver la fonctionnalité de désabonnement. Après activation, le système effectuera un traitement de déduction selon les règles et proportions configurées, et la valeur restante sera retournée au solde.",
"quota": "Quantité d'achat limitée",
"renewalReset": "Réinitialisation au Renouvellement",
"renewalResetDescription": "Réinitialiser le cycle lors du renouvellement",
"replacement": "Prix de réinitialisation (par fois)",
"resetCycle": "Cycle de Réinitialisation",
"resetOn1st": "Réinitialisation le 1er",
"selectResetCycle": "Veuillez sélectionner un cycle de réinitialisation",
"selectSubscribeGroup": "Veuillez sélectionner un groupe d'abonnement",
"selectUnitTime": "Veuillez sélectionner l'unité de temps",
"server": "Serveur",
"serverGroup": "Groupe de serveurs",
"servers": "Serveurs",
"speedLimit": "Limite de vitesse ",
"traffic": "Trafic",
"unitPrice": "Prix unitaire",
"unitTime": "Unité de temps"
},
"group": {
"actions": "Actions",
"cancel": "Annuler",
"confirm": "Confirmer",
"confirmDelete": "Êtes-vous sûr de vouloir supprimer ?",
"create": "Créer",
"createSubscribeGroup": "Créer un groupe d'abonnement",
"createSuccess": "Création réussie",
"delete": "Supprimer",
"deleteSuccess": "Suppression réussie",
"deleteWarning": "Les données ne peuvent pas être récupérées après suppression, veuillez procéder avec prudence.",
"description": "Description",
"edit": "Éditer",
"editSubscribeGroup": "Éditer le groupe d'abonnement",
"form": {
"cancel": "Annuler",
"confirm": "Confirmer",
"description": "Description",
"name": "Nom"
"addTitle": "Ajouter un client",
"descriptions": {
"description": "Description détaillée du client",
"downloadLink": "URL de téléchargement de la plateforme",
"icon": "URL de l'icône ou encodage base64",
"name": "Nom d'affichage du client",
"outputFormat": "Format du fichier de configuration d'abonnement",
"scheme": {
"base64Encoding": "Encodage Base64",
"functions": "Prend en charge les fonctions :",
"jsonStringify": "Objet JSON en chaîne",
"nameVariable": "nom du site",
"title": "Modèle de schéma d'URL",
"urlEncoding": "Encodage d'URL",
"urlVariable": "URL d'abonnement",
"variables": "Prend en charge les variables :"
},
"template": {
"description": "Utilisez la syntaxe de modèle Go pour générer des fichiers de configuration d'abonnement",
"functions": "Fonctions de modèle :",
"if": "instructions conditionnelles",
"nodes": "liste des nœuds proxy",
"range": "itérer des tableaux",
"siteName": "nom du site",
"sprig": "Bibliothèque de fonctions Sprig (traitement de chaînes, dates, etc.)",
"subscribeName": "nom de l'abonnement",
"title": "Syntaxe de modèle Go",
"userInfo": "informations utilisateur (trafic, expiration, etc.)",
"variables": "Variables disponibles :"
},
"userAgentPrefix": "Identifiant du client pour distinguer différents clients"
},
"name": "Nom",
"title": "Liste des groupes d'abonnement",
"updateSuccess": "Mise à jour réussie",
"updatedAt": "Date de mise à jour"
"editTitle": "Modifier un client",
"fields": {
"description": "Description",
"icon": "Icône",
"name": "Nom",
"outputFormat": "Format de sortie",
"scheme": "Schéma d'URL",
"template": "Modèle de fichier d'abonnement"
},
"tabs": {
"basic": "Informations de base",
"download": "Téléchargements",
"template": "Modèles"
},
"validation": {
"nameRequired": "Le nom du client est requis",
"userAgentRequiredSuffix": "est requis"
}
},
"inventory": "Limite d'abonnement",
"name": "Nom",
"quota": "Limite d'achat/par fois",
"replacement": "Réinitialiser le prix/par fois",
"sell": "Vente",
"show": "Afficher",
"sold": "Nombre d'abonnements",
"subscribe": "S'abonner",
"subscribeGroup": "S'abonner au groupe",
"tabs": {
"subscribe": "S'abonner",
"subscribeApp": "Configuration de l'application",
"subscribeConfig": "Configuration de l'abonnement",
"subscribeGroup": "Groupe d'abonnement"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Texte brut",
"yaml": "YAML"
},
"traffic": "trafic",
"unitPrice": "Prix unitaire",
"updateSuccess": "Mise à jour réussie"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Gestion des clients"
},
"table": {
"columns": {
"default": "Par défaut",
"description": "Description",
"name": "Nom du client",
"outputFormat": "Format de sortie",
"supportedPlatforms": "Plateformes prises en charge"
}
},
"templatePreview": {
"base64": {
"decodeError": "Échec du décodage : le contenu n'est pas au format Base64 valide",
"decodedContent": "Contenu décodé",
"originalContent": "Contenu original (Base64)"
},
"failed": "Échec de l'aperçu",
"loading": "Chargement...",
"preview": "Aperçu",
"title": "Aperçu du modèle"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "jour(s)",
"defaultSubscribe": "Abonnement par défaut",
"defaultSubscribeDescription": "Plan d'abonnement par défaut pour les nouveaux utilisateurs",
"description": "Configurer les paramètres liés à l'inscription des utilisateurs",
"enableTrial": "Activer l'essai",
"enableTrialDescription": "Lorsqu'il est activé, les nouveaux utilisateurs recevront un abonnement d'essai lors de leur inscription",
"hour": "Heure(s)",
"inputPlaceholder": "Veuillez entrer",
"ipRegistrationLimit": "Limite d'inscription par IP",
"ipRegistrationLimitDescription": "Limiter le nombre d'inscriptions à partir d'une seule adresse IP",
"minute": "Minute(s)",
"month": "Mois",
"none": "Aucun",
"registrationLimitCount": "Nombre limite d'inscriptions",
"registrationLimitCountDescription": "Nombre d'inscriptions autorisées par IP pendant la période limite",
"registrationLimitExpire": "Période limite",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Arrêter l'inscription des nouveaux utilisateurs",
"stopNewUserRegistrationDescription": "Lorsque cette option est activée, l'inscription des nouveaux utilisateurs sera désactivée",
"title": "Paramètres d'inscription",
"trialDay": "Jours d'essai",
"trialDayDescription": "Jours d'essai accordés aux nouveaux utilisateurs lors de l'inscription",
"trialFlow": "Trafic d'essai",
"trialFlowDescription": "Trafic d'essai accordé aux nouveaux utilisateurs lors de l'inscription"
"trialConfig": "Configuration d'essai",
"trialConfigDescription": "Configurer l'abonnement d'essai, la durée et l'unité de temps pour les nouveaux utilisateurs lors de l'inscription",
"year": "An(s)"
},
"site": {
"customData": "Données personnalisées",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "अतिरिक्त",
"additionalRecipientEmails": "अतिरिक्त प्राप्तकर्ता ईमेल",
"additionalRecipients": "अतिरिक्त प्राप्तकर्ता",
"additionalRecipientsDescription": "ये ईमेल उपरोक्त उपयोगकर्ता फ़िल्टर के अलावा प्रसारण प्राप्त करेंगे",
"allUsers": "सभी उपयोगकर्ता",
"broadcastList": "प्रसारण सूची",
"broadcastLogs": "प्रसारण लॉग",
"cancel": "रद्द करें",
"cannotBeEmpty": "खाली नहीं हो सकता",
"completed": "पूर्ण",
"confirm": "पुष्टि करें",
"confirmDelete": "हटाने की पुष्टि करें",
"content": "ईमेल सामग्री",
"create": "बनाएँ",
"createBroadcast": "प्रसारण बनाएँ",
"createNewEmailBroadcastCampaign": "नई ईमेल प्रसारण अभियान बनाएँ",
"createSuccess": "सफलता से बनाया गया",
"createdAt": "बनाया गया",
"dailyLimit": "दैनिक सीमा कम से कम 1 होनी चाहिए",
"dailySendLimit": "दैनिक भेजने की सीमा",
"delete": "हटाएँ",
"deleteDescription": "यह क्रिया पूर्ववत नहीं की जा सकती। क्या आप वास्तव में हटाना चाहते हैं?",
"deleteSuccess": "सफलता से हटाया गया",
"edit": "संपादित करें",
"emailAddedToScheduledQueue": "ईमेल अनुसूचित भेजने की कतार में जोड़ा गया",
"emailBroadcast": "ईमेल प्रसारण",
"emailBroadcastTaskCreatedSuccessfully": "ईमेल प्रसारण कार्य सफलतापूर्वक बनाया गया",
"emailBroadcastTasks": "ईमेल प्रसारण कार्य",
"emailContent": "ईमेल सामग्री",
"emailInterval": "ईमेल अंतराल (सेकंड)",
"emailIntervalMinimum": "ईमेल अंतराल कम से कम 0.1 सेकंड होना चाहिए",
"emailMarketing": "ईमेल विपणन",
"emailTaskManager": "ईमेल कार्य प्रबंधक",
"errorMessage": "त्रुटि संदेश",
"estimatedRecipients": "अनुमानित प्राप्तकर्ता",
"expiredSubscriptionUsersOnly": "केवल समाप्त सदस्यता वाले उपयोगकर्ता",
"expiredUsers": "समाप्त उपयोगकर्ता",
"failCount": "विफलता की संख्या",
"failed": "विफल",
"failedToRefreshTaskStatus": "कार्य स्थिति को ताज़ा करने में विफल",
"failedToStopTask": "कार्य को रोकने में विफल",
"inProgress": "प्रगति पर",
"includeUsersRegisteredAfter": "इस तिथि के बाद पंजीकृत उपयोगकर्ताओं को शामिल करें",
"includeUsersRegisteredBefore": "इस तिथि से पहले पंजीकृत उपयोगकर्ताओं को शामिल करें",
"intervalTimeBetweenEmails": "प्रत्येक ईमेल के बीच का अंतराल समय",
"leaveEmptyForImmediateSend": "तत्काल भेजने के लिए खाली छोड़ें",
"logList": "लॉग सूची",
"marketingManagement": "विपणन प्रबंधन",
"maximumNumberPerDay": "प्रति दिन भेजने के लिए अधिकतम ईमेल की संख्या",
"noSubscriptionUsersOnly": "केवल कोई सदस्यता वाले उपयोगकर्ता",
"nonSubscribers": "गैर-सदस्य",
"notStarted": "शुरू नहीं हुआ",
"onePerLine": "एक प्रति पंक्ति",
"only": "केवल",
"pending": "लंबित",
"pleaseEnter": "कृपया दर्ज करें",
"pleaseEnterValidEmailAddresses": "कृपया मान्य ईमेल पते दर्ज करें, एक प्रति पंक्ति",
"processing": "प्रसंस्करण...",
"progress": "प्रगति",
"recipient": "प्राप्तकर्ता",
"recipientEmail": "प्राप्तकर्ता ईमेल",
"recipientType": "प्राप्तकर्ता प्रकार",
"registrationEndDate": "पंजीकरण समाप्ति तिथि",
"registrationStartDate": "पंजीकरण प्रारंभ तिथि",
"scheduleSend": "भेजने का कार्यक्रम",
"scheduledSend": "अनुसूचित भेजें",
"scheduledSendTimeMustBeLater": "अनुसूचित भेजने का समय वर्तमान समय से बाद में होना चाहिए",
"selectSendScope": "भेजने के दायरे का चयन करें",
"selectSendTime": "भेजने का समय चुनें, तत्काल भेजने के लिए खाली छोड़ें",
"sendFailed": "भेजने में विफल, कृपया पुनः प्रयास करें",
"sendNow": "अब भेजें",
"sendScope": "भेजने का दायरा",
"sendScopeDescription": "ईमेल भेजने के लिए उपयोगकर्ता दायरा चुनें। केवल नीचे भरे गए ईमेल पते पर भेजने के लिए \"अतिरिक्त ईमेल केवल\" चुनें",
"sendSettings": "भेजने की सेटिंग्स",
"sendTime": "भेजने का समय",
"sending": "भेजना",
"sentAt": "भेजा गया",
"specificUsers": "विशिष्ट उपयोगकर्ता",
"specificUsersOnly": "केवल अतिरिक्त ईमेल (प्लेटफ़ॉर्म उपयोगकर्ताओं को छोड़कर)",
"status": "स्थिति",
"stop": "रोकें",
"stopped": "रुका हुआ",
"subject": "ईमेल विषय",
"subscribedUsers": "सदस्यता प्राप्त उपयोगकर्ता",
"subscribedUsersOnly": "केवल सदस्यता प्राप्त उपयोगकर्ता",
"successCount": "सफलता की संख्या",
"taskStatusRefreshed": "कार्य स्थिति को ताज़ा किया गया",
"taskStoppedSuccessfully": "कार्य सफलतापूर्वक रोका गया",
"totalSent": "कुल भेजा गया",
"updateSuccess": "सफलता से अपडेट किया गया",
"useMarkdownEditor": "ईमेल सामग्री लिखने के लिए मार्कडाउन संपादक का उपयोग करें जिसमें पूर्वावलोकन कार्यक्षमता है",
"users": "उपयोगकर्ता",
"view": "देखें",
"viewAndManageEmailBroadcastTasks": "ईमेल प्रसारण कार्यों को देखें और प्रबंधित करें",
"viewContent": "सामग्री देखें"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "एडीएस कॉन्फ़िग",
"Announcement Management": "घोषणा प्रबंधन",
"Apple": "एप्पल आईडी",
"Application Management": "ऐप्लिकेशन प्रबंधन",
"Auth Control": "प्रमाणिकरण नियंत्रण",
"Coupon Management": "कूपन प्रबंधन",
"Dashboard": "डैशबोर्ड",
"Device": "डिवाइस",
"Document Management": "दस्तावेज़ प्रबंधन",
"Email": "ईमेल",
"Facebook": "फेसबुक",
"Finance": "वित्त",
"General": "सामान्य",
"GitHub": "GitHub",
"Google": "गूगल",
"Marketing Management": "मार्केटिंग प्रबंधन",
"Order Management": "ऑर्डर प्रबंधन",
"Payment Config": "भुगतान कॉन्फ़िगरेशन",
"Phone Number": "फ़ोन नंबर",
"Product Management": "उत्पाद प्रबंधन",
"Protocol Management": "प्रोटोकॉल प्रबंधन",
"Rule Management": "नियम प्रबंधन",
"Server": "सर्वर",
"Server Management": "सर्वर प्रबंधन",
"Settings": "सेटिंग्स",
"Subscribe Management": "सदस्यता प्रबंधन",
"Subscribe Config": "सदस्यता कॉन्फ़िगरेशन",
"System Config": "सिस्टम कॉन्फ़िगरेशन",
"System Management": "सिस्टम प्रबंधन",
"System Tool": "सिस्टम उपकरण",
"Telegram": "टेलीग्राम",
"Ticket Management": "टिकट प्रबंधन",
"Twitter": "ट्विटर",
"User": "उपयोगकर्ता",
"User Detail": "उपयोगकर्ता विवरण",
"User Management": "उपयोगकर्ता प्रबंधन"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "क्रियाएँ",
"app": {
"appDownloadURL": "ऐप डाउनलोड URL",
"appIcon": "ऐप आइकन",
"appList": "ऐप सूची",
"appName": "ऐप का नाम",
"backupDomains": "बैकअप डोमेन सूची",
"backupDomainsDescription": "डोमेन समाधान के लिए बैकअप डोमेन सूची, प्रत्येक पंक्ति में एक डोमेन",
"batchDelete": "बैच हटाएं",
"cancel": "रद्द करें",
"communicationKey": "संचार कुंजी",
"communicationKeyDescription": "क्लाइंट संचार के लिए उपयोग की जाने वाली कुंजी",
"config": "कॉन्फ़िग",
"configApp": "ऐप कॉन्फ़िगरेशन",
"confirm": "पुष्टि करें",
"confirmDelete": "हटाने की पुष्टि करें",
"create": "बनाएं",
"createApp": "ऐप बनाएं",
"createSuccess": "सफलतापूर्वक बनाया गया",
"defaultVersion": "डिफ़ॉल्ट",
"delete": "हटाएं",
"deleteWarning": "यह क्रिया पूर्ववत नहीं की जा सकती",
"describeDescription": "एप्लिकेशन का वर्णन करने के लिए उपयोग किया जाता है, ऐप सूची में प्रदर्शित",
"description": "विवरण",
"downloadLink": "डाउनलोड लिंक",
"edit": "संपादित करें",
"editApp": "ऐप संपादित करें",
"encryption": "एन्क्रिप्शन विधि",
"encryptionDescription": "क्लाइंट संचार के लिए एन्क्रिप्शन विधि चुनें। यदि चुना गया, तो क्लाइंट इस विधि का उपयोग सर्वर के साथ संचार करने के लिए करेगा",
"nameDescription": "एप्लिकेशन का नाम, ऐप सूची में प्रदर्शित",
"platform": "प्लेटफ़ॉर्म",
"selectApp": "ऐप चुनें",
"selectAppDescription": "कॉन्फ़िगर करने के लिए ऐप चुनें, सभी सेटिंग्स चयनित ऐप पर लागू होंगी",
"startupPicture": "स्टार्टअप चित्र",
"startupPictureDescription": "स्टार्टअप चित्र, नेटवर्क और स्थानीय छवियों का समर्थन करता है। नेटवर्क छवियों के लिए, कृपया पूरी छवि URL दर्ज करें",
"startupPicturePreview": "स्टार्टअप चित्र पूर्वावलोकन",
"startupPictureSkip": "स्टार्टअप चित्र छोड़ने का समय",
"startupPictureSkipDescription": "स्टार्टअप चित्र प्रदर्शन समय सेकंड में, प्रदर्शित न करने के लिए 0 दर्ज करें",
"subscriptionProtocol": "सदस्यता प्रोटोकॉल",
"updateSuccess": "सफलतापूर्वक अपडेट किया गया",
"version": "संस्करण"
},
"cancel": "रद्द करें",
"config": {
"singleSubscriptionMode": "एकल सदस्यता मोड",
"subscriptionDomain": "सदस्यता डोमेन",
"subscriptionDomainDescription": "सदस्यता के लिए उपयोग किया जाता है; साइट डोमेन का उपयोग करने के लिए खाली छोड़ दें",
"subscriptionDomainPlaceholder": "सदस्यता डोमेन दर्ज करें, एक प्रति पंक्ति",
"subscriptionPath": "सदस्यता पथ",
"subscriptionPathDescription": "सदस्यता के लिए उपयोग किया जाता है; इष्टतम प्रदर्शन के लिए संशोधन के बाद सिस्टम को पुनः आरंभ करना सुनिश्चित करें",
"subscriptionPathPlaceholder": "दर्ज करें",
"updateSuccess": "सफलता से अपडेट किया गया",
"wildcardResolution": "वाइल्डकार्ड समाधान",
"wildcardResolutionDescription": "सदस्यता के लिए उपयोग किया जाता है"
},
"confirm": "पुष्टि करें",
"confirmDelete": "क्या आप वाकई हटाना चाहते हैं?",
"copy": "कॉपी",
"copySuccess": "सफलतापूर्वक कॉपी किया गया",
"create": "सृजन",
"createSubscribe": "नई सदस्यता बनाएं",
"createSuccess": "सृजन सफल",
"delete": "हटाएं",
"deleteSuccess": "हटाने में सफलता",
"deleteWarning": "हटाने के बाद डेटा पुनः प्राप्त नहीं किया जा सकता है, कृपया सावधानीपूर्वक कार्य करें।",
"deviceLimit": "उपकरण संख्या/यूनिट",
"edit": "संपादित करें",
"editSubscribe": "संपादन सदस्यता",
"form": {
"Day": "दिन",
"Hour": "घंटा",
"Minute": "मिनट",
"Month": "महीना",
"NoLimit": "कोई सीमा नहीं",
"Year": "वर्ष",
"annualReset": "वार्षिक रीसेट",
"basic": "मूल",
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"deductionRatio": "स्वचालित/मैनुअल कटौती कॉन्फ़िगरेशन",
"deductionRatioDescription": "कटौती के लिए उपयोग किया जाता है। डिफ़ॉल्ट रूप से, सिस्टम एक स्वचालित गणना एल्गोरिदम अपनाता है। जब एक मैनुअल अनुपात प्रदान किया जाता है, तो सिस्टम समय और ट्रैफ़िक अनुपात के आधार पर अनुपात की गणना करता है, यह सुनिश्चित करते हुए कि कुल 100% के बराबर हो।",
"description": "विवरण",
"deviceLimit": "उपकरण सीमा",
"discount": "छूट",
"discountDescription": "इकाई मूल्य के आधार पर छूट सेट करें",
"discountMonths": "महीने",
"discountPercent": "छूट प्रतिशत",
"discount_price": "छूट मूल्य",
"duration": "अवधि (महीने)",
"groupId": "सदस्यता समूह",
"inventory": "सदस्यता सीमा",
"monthlyReset": "मासिक रीसेट",
"name": "नाम",
"noLimit": "कोई सीमा नहीं",
"noReset": "कोई रीसेट नहीं",
"pricing": "मूल्य निर्धारण",
"purchaseWithDiscount": "कटौती की अनुमति दें",
"purchaseWithDiscountDescription": "अनसब्सक्राइब कार्यक्षमता को सक्षम या अक्षम करें। सक्रियण के बाद, सिस्टम कॉन्फ़िगर किए गए नियमों और अनुपातों के अनुसार कटौती प्रसंस्करण करेगा, और शेष मूल्य को बैलेंस में वापस कर दिया जाएगा।",
"quota": "खरीद सीमा",
"renewalReset": "नवीनीकरण रीसेट",
"renewalResetDescription": "नवीनीकरण पर रीसेट चक्र",
"replacement": "पुनःस्थापना मूल्य (प्रति बार)",
"resetCycle": "रीसेट चक्र",
"resetOn1st": "1 तारीख को रीसेट",
"selectResetCycle": "कृपया एक रीसेट चक्र चुनें",
"selectSubscribeGroup": "कृपया सदस्यता समूह चुनें",
"selectUnitTime": "कृपया इकाई समय चुनें",
"server": "सर्वर",
"serverGroup": "सर्वर समूह",
"servers": "सर्वर",
"speedLimit": "गति सीमा ",
"traffic": "ट्रैफिक",
"unitPrice": "इकाई मूल्य",
"unitTime": "इकाई समय"
},
"group": {
"actions": "क्रियाएँ",
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"confirmDelete": "क्या आप वाकई हटाना चाहते हैं?",
"create": "बनाएँ",
"createSubscribeGroup": "नई सदस्यता समूह बनाएं",
"createSuccess": "सफलतापूर्वक बनाया गया",
"delete": "हटाएँ",
"deleteSuccess": "सफलतापूर्वक हटाया गया",
"deleteWarning": "हटाने के बाद डेटा पुनः प्राप्त नहीं किया जा सकता, कृपया सावधानीपूर्वक कार्य करें।",
"description": "विवरण",
"edit": "संपादित करें",
"editSubscribeGroup": "सदस्यता समूह संपादित करें",
"form": {
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"description": "विवरण",
"name": "नाम"
},
"name": "नाम",
"title": "सदस्यता समूह सूची",
"updateSuccess": "सफलतापूर्वक अपडेट किया गया",
"updatedAt": "अपडेट का समय"
},
"inventory": "सदस्यता सीमा",
"name": "नाम",
"quota": "प्रति खरीद सीमा",
"replacement": "मूल्य/प्रति बार रीसेट करें",
"sell": "बिक्री",
"show": "दिखाएं",
"sold": "सदस्यता गणना",
"subscribe": "सदस्यता लें",
"subscribeGroup": "सदस्यता समूह",
"tabs": {
"subscribe": "सदस्यता लें",
"subscribeApp": "ऐप कॉन्फ़िगरेशन",
"subscribeConfig": "सदस्यता कॉन्फ़िगरेशन",
"subscribeGroup": "समूह सदस्यता"
},
"traffic": "ट्रैफिक",
"unitPrice": "इकाई मूल्य",
"updateSuccess": "अपडेट सफल"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "प्रकार",
"updateSuccess": "सफलतापूर्वक अपडेट किया गया",
"updatedAt": "अपडेट समय",
"userAccount": "उपयोगकर्ता खाता",
"user": "उपयोगकर्ता",
"userDetail": "उपयोगकर्ता विवरण",
"userId": "उपयोगकर्ता आईडी"
},
+112 -141
View File
@@ -1,161 +1,132 @@
{
"actions": "क्रियाएँ",
"app": {
"appDownloadURL": "ऐप डाउनलोड URL",
"appIcon": "ऐप आइकन",
"appList": "ऐप सूची",
"appName": "ऐप का नाम",
"backupDomains": "बैकअप डोमेन सूची",
"backupDomainsDescription": "डोमेन समाधान के लिए बैकअप डोमेन सूची, प्रत्येक पंक्ति में एक डोमेन",
"actions": {
"add": "जोड़ें",
"batchDelete": "बैच हटाएं",
"batchDeleteSuccess": "सफलता से {count} क्लाइंट हटाए गए",
"batchDeleteWarning": "क्या आप निश्चित हैं कि आप चयनित {count} क्लाइंट हटाना चाहते हैं?",
"cancel": "रद्द करें",
"communicationKey": "संचार कुंजी",
"communicationKeyDescription": "क्लाइंट संचार के लिए उपयोग की जाने वाली कुंजी",
"config": "कॉन्फ़िग",
"configApp": "ऐप कॉन्फ़िगरेशन",
"confirm": "पुष्टि करें",
"confirmDelete": "हटाने की पुष्टि करें",
"create": "बनाएं",
"createApp": "ऐप बनाएं",
"createSuccess": "सफलतापूर्वक बनाया गया",
"defaultVersion": "डिफ़ॉल्ट",
"createSuccess": "सफलता से बनाया गया",
"delete": "हटाएं",
"deleteWarning": "यह क्रिया पूर्ववत नहीं की जा सकती",
"describeDescription": "एप्लिकेशन का वर्णन करने के लिए उपयोग किया जाता है, ऐप सूची में प्रदर्शित",
"description": "विवरण",
"downloadLink": "डाउनलोड लिंक",
"deleteFailed": "हटाना विफल",
"deleteSuccess": "सफलता से हटाया गया",
"deleteWarning": "यह क्रिया पूर्ववत नहीं की जा सकती। क्या आप निश्चित हैं कि आप इस क्लाइंट को हटाना चाहते हैं?",
"edit": "संपादित करें",
"editApp": "ऐप संपादित करें",
"encryption": "एन्क्रिप्शन विधि",
"encryptionDescription": "क्लाइंट संचार के लिए एन्क्रिप्शन विधि चुनें। यदि चुना गया, तो क्लाइंट इस विधि का उपयोग सर्वर के साथ संचार करने के लिए करेगा",
"nameDescription": "एप्लिकेशन का नाम, ऐप सूची में प्रदर्शित",
"platform": "प्लेटफ़ॉर्म",
"selectApp": "ऐप चुनें",
"selectAppDescription": "कॉन्फ़िगर करने के लिए ऐप चुनें, सभी सेटिंग्स चयनित ऐप पर लागू होंगी",
"startupPicture": "स्टार्टअप चित्र",
"startupPictureDescription": "स्टार्टअप चित्र, नेटवर्क और स्थानीय छवियों का समर्थन करता है। नेटवर्क छवियों के लिए, कृपया पूरी छवि URL दर्ज करें",
"startupPicturePreview": "स्टार्टअप चित्र पूर्वावलोकन",
"startupPictureSkip": "स्टार्टअप चित्र छोड़ने का समय",
"startupPictureSkipDescription": "स्टार्टअप चित्र प्रदर्शन समय सेकंड में, प्रदर्शित न करने के लिए 0 दर्ज करें",
"subscriptionProtocol": "सदस्यता प्रोटोकॉल",
"updateSuccess": "सफलतापूर्वक अपडेट किया गया",
"version": "संस्करण"
"save": "सहेजें",
"saveFailed": "सहेजना विफल",
"update": "अपडेट करें",
"updateSuccess": "सफलता से अपडेट किया गया"
},
"cancel": "रद्द करें",
"config": {
"description": "सदस्यता प्रणाली सेटिंग्स प्रबंधित करें",
"singleSubscriptionMode": "एकल सदस्यता मोड",
"singleSubscriptionModeDescription": "सक्रिय होने पर, सभी उपयोगकर्ता सदस्यताएँ शेष में परिवर्तित हो जाएँगी",
"singleSubscriptionModeDescription": "उपयोगकर्ताओं को एक सक्रिय सदस्यता तक सीमित करें। मौजूदा सदस्यताएँ अप्रभावित रहेंगी",
"subscriptionDomain": "सदस्यता डोमेन",
"subscriptionDomainDescription": "सदस्यता के लिए उपयोग किया जाता है; साइट डोमेन का उपयोग करने के लिए खाली छोड़ दें",
"subscriptionDomainDescription": "सदस्यता लिंक के लिए कस्टम डोमेन",
"subscriptionDomainPlaceholder": "सदस्यता डोमेन दर्ज करें, एक प्रति पंक्ति",
"subscriptionPath": "सदस्यता पथ",
"subscriptionPathDescription": "सदस्यता के लिए उपयोग किया जाता है; इष्टतम प्रदर्शन के लिए संशोधन के बाद सिस्टम को पुनः आरंभ करना सुनिश्चित करें",
"subscriptionPathPlaceholder": "दर्ज करें",
"updateSuccess": "सफलता से अपडेट किया गया",
"subscriptionPathDescription": "सदस्यता एंडपॉइंट्स के लिए कस्टम पथ (सिस्टम पुनरारंभ के बाद बेहतर प्रदर्शन)",
"subscriptionPathPlaceholder": "सदस्यता पथ दर्ज करें",
"title": "सदस्यता कॉन्फ़िगरेशन",
"updateError": "अपडेट विफल",
"updateSuccess": "सेटिंग्स सफलतापूर्वक अपडेट की गईं",
"userAgentLimit": "{userAgent} प्रतिबंध",
"userAgentLimitDescription": "{userAgent} के आधार पर पहुंच प्रतिबंध सक्षम करें",
"userAgentList": "{userAgent} श्वेतसूची",
"userAgentListDescription": "सदस्यता पहुंच के लिए अनुमत {userAgent}, एक प्रति पंक्ति। कॉन्फ़िगर की गई एप्लिकेशन {userAgent} स्वचालित रूप से शामिल की जाएगी",
"userAgentListPlaceholder": "अनुमत {userAgent} दर्ज करें, एक प्रति पंक्ति",
"wildcardResolution": "वाइल्डकार्ड समाधान",
"wildcardResolutionDescription": "सदस्यता के लिए उपयोग किया जाता है"
"wildcardResolutionDescription": "सदस्यताओं के लिए वाइल्डकार्ड डोमेन समाधान सक्षम करें"
},
"confirm": "पुष्टि करें",
"confirmDelete": "क्या आप वाकई हटाना चाहते हैं?",
"copy": "कॉपी",
"copySuccess": "सफलतापूर्वक कॉपी किया गया",
"create": "सृजन",
"createSubscribe": "नई सदस्यता बनाएं",
"createSuccess": "सृजन सफल",
"delete": "हटाएं",
"deleteSuccess": "हटाने में सफलता",
"deleteWarning": "हटाने के बाद डेटा पुनः प्राप्त नहीं किया जा सकता है, कृपया सावधानीपूर्वक कार्य करें।",
"deviceLimit": "उपकरण संख्या/यूनिट",
"edit": "संपादित करें",
"editSubscribe": "संपादन सदस्यता",
"form": {
"Day": "दिन",
"Hour": "घंटा",
"Minute": "मिनट",
"Month": "महीना",
"NoLimit": "कोई सीमा नहीं",
"Year": "वर्ष",
"annualReset": "वार्षिक रीसेट",
"basic": "मूल",
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"deductionRatio": "स्वचालित/मैनुअल कटौती कॉन्फ़िगरेशन",
"deductionRatioDescription": "कटौती के लिए उपयोग किया जाता है। डिफ़ॉल्ट रूप से, सिस्टम एक स्वचालित गणना एल्गोरिदम अपनाता है। जब एक मैनुअल अनुपात प्रदान किया जाता है, तो सिस्टम समय और ट्रैफ़िक अनुपात के आधार पर अनुपात की गणना करता है, यह सुनिश्चित करते हुए कि कुल 100% के बराबर हो।",
"description": "विवरण",
"deviceLimit": "उपकरण सीमा",
"discount": "छूट",
"discountDescription": "इकाई मूल्य के आधार पर छूट सेट करें",
"discountMonths": "महीने",
"discountPercent": "छूट प्रतिशत",
"discount_price": "छूट मूल्य",
"duration": "अवधि (महीने)",
"groupId": "सदस्यता समूह",
"inventory": "सदस्यता सीमा",
"monthlyReset": "मासिक रीसेट",
"name": "नाम",
"noLimit": "कोई सीमा नहीं",
"noReset": "कोई रीसेट नहीं",
"pricing": "मूल्य निर्धारण",
"purchaseWithDiscount": "कटौती की अनुमति दें",
"purchaseWithDiscountDescription": "अनसब्सक्राइब कार्यक्षमता को सक्षम या अक्षम करें। सक्रियण के बाद, सिस्टम कॉन्फ़िगर किए गए नियमों और अनुपातों के अनुसार कटौती प्रसंस्करण करेगा, और शेष मूल्य को बैलेंस में वापस कर दिया जाएगा।",
"quota": "खरीद सीमा",
"renewalReset": "नवीनीकरण रीसेट",
"renewalResetDescription": "नवीनीकरण पर रीसेट चक्र",
"replacement": "पुनःस्थापना मूल्य (प्रति बार)",
"resetCycle": "रीसेट चक्र",
"resetOn1st": "1 तारीख को रीसेट",
"selectResetCycle": "कृपया एक रीसेट चक्र चुनें",
"selectSubscribeGroup": "कृपया सदस्यता समूह चुनें",
"selectUnitTime": "कृपया इकाई समय चुनें",
"server": "सर्वर",
"serverGroup": "सर्वर समूह",
"servers": "सर्वर",
"speedLimit": "गति सीमा ",
"traffic": "ट्रैफिक",
"unitPrice": "इकाई मूल्य",
"unitTime": "इकाई समय"
},
"group": {
"actions": "क्रियाएँ",
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"confirmDelete": "क्या आप वाकई हटाना चाहते हैं?",
"create": "बनाएँ",
"createSubscribeGroup": "नई सदस्यता समूह बनाएं",
"createSuccess": "सफलतापूर्वक बनाया गया",
"delete": "हटाएँ",
"deleteSuccess": "सफलतापूर्वक हटाया गया",
"deleteWarning": "हटाने के बाद डेटा पुनः प्राप्त नहीं किया जा सकता, कृपया सावधानीपूर्वक कार्य करें।",
"description": "विवरण",
"edit": "संपादित करें",
"editSubscribeGroup": "सदस्यता समूह संपादित करें",
"form": {
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"description": "विवरण",
"name": "नाम"
"addTitle": "क्लाइंट जोड़ें",
"descriptions": {
"description": "क्लाइंट का विस्तृत विवरण",
"downloadLink": "प्लेटफ़ॉर्म डाउनलोड यूआरएल",
"icon": "आइकन यूआरएल या बेस64 एन्कोडिंग",
"name": "क्लाइंट प्रदर्शन नाम",
"outputFormat": "सदस्यता कॉन्फ़िगरेशन फ़ाइल प्रारूप",
"scheme": {
"base64Encoding": "बेस64 एन्कोडिंग",
"functions": "कार्य का समर्थन करता है:",
"jsonStringify": "जेसन ऑब्जेक्ट को स्ट्रिंग",
"nameVariable": "साइट का नाम",
"title": "यूआरएल स्कीम टेम्पलेट",
"urlEncoding": "यूआरएल एन्कोडिंग",
"urlVariable": "सदस्यता यूआरएल",
"variables": "चर का समर्थन करता है:"
},
"template": {
"description": "सदस्यता कॉन्फ़िगरेशन फ़ाइलें उत्पन्न करने के लिए गो टेम्पलेट सिंटैक्स का उपयोग करें",
"functions": "टेम्पलेट कार्य:",
"if": "शर्तीय कथन",
"nodes": "प्रॉक्सी नोड्स की सूची",
"range": "ऐरे को दोहराएं",
"siteName": "साइट का नाम",
"sprig": "स्प्रिग फ़ंक्शन पुस्तकालय (स्ट्रिंग प्रोसेसिंग, तिथियाँ, आदि)",
"subscribeName": "सदस्यता का नाम",
"title": "गो टेम्पलेट सिंटैक्स",
"userInfo": "उपयोगकर्ता जानकारी (ट्रैफ़िक, समाप्ति, आदि)",
"variables": "उपलब्ध चर:"
},
"userAgentPrefix": "विभिन्न क्लाइंट्स को अलग करने के लिए क्लाइंट पहचानकर्ता"
},
"name": "नाम",
"title": "सदस्यता समूह सूची",
"updateSuccess": "सफलतापूर्वक अपडेट किया गया",
"updatedAt": "अपडेट का समय"
"editTitle": "क्लाइंट संपादित करें",
"fields": {
"description": "विवरण",
"icon": "आइकन",
"name": "नाम",
"outputFormat": "आउटपुट प्रारूप",
"scheme": "यूआरएल स्कीम",
"template": "सदस्यता फ़ाइल टेम्पलेट"
},
"tabs": {
"basic": "बुनियादी जानकारी",
"download": "डाउनलोड",
"template": "टेम्पलेट"
},
"validation": {
"nameRequired": "क्लाइंट नाम आवश्यक है",
"userAgentRequiredSuffix": "आवश्यक है"
}
},
"inventory": "सदस्यता सीमा",
"name": "नाम",
"quota": "प्रति खरीद सीमा",
"replacement": "मूल्य/प्रति बार रीसेट करें",
"sell": "बिक्री",
"show": "दिखाएं",
"sold": "सदस्यता गणना",
"subscribe": "सदस्यता लें",
"subscribeGroup": "सदस्यता समूह",
"tabs": {
"subscribe": "सदस्यता लें",
"subscribeApp": "ऐप कॉन्फ़िगरेशन",
"subscribeConfig": "सदस्यता कॉन्फ़िगरेशन",
"subscribeGroup": "समूह सदस्यता"
"outputFormats": {
"base64": "बेस64",
"conf": "CONF",
"json": "JSON",
"plain": "सादा पाठ",
"yaml": "YAML"
},
"traffic": "ट्रैफिक",
"unitPrice": "इकाई मूल्य",
"updateSuccess": "अपडेट सफल"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "क्लाइंट प्रबंधन"
},
"table": {
"columns": {
"default": "डिफ़ॉल्ट",
"description": "विवरण",
"name": "क्लाइंट नाम",
"outputFormat": "आउटपुट प्रारूप",
"supportedPlatforms": "समर्थित प्लेटफ़ॉर्म"
}
},
"templatePreview": {
"base64": {
"decodeError": "डिकोड विफल: सामग्री मान्य Base64 प्रारूप नहीं है",
"decodedContent": "डिकोड की गई सामग्री",
"originalContent": "मूल सामग्री (Base64)"
},
"failed": "पूर्वावलोकन विफल",
"loading": "लोड हो रहा है...",
"preview": "पूर्वावलोकन",
"title": "टेम्पलेट पूर्वावलोकन"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "दिन(ों)",
"defaultSubscribe": "डिफ़ॉल्ट सदस्यता",
"defaultSubscribeDescription": "नए उपयोगकर्ताओं के लिए डिफ़ॉल्ट सदस्यता योजना",
"description": "उपयोगकर्ता पंजीकरण से संबंधित सेटिंग्स को कॉन्फ़िगर करें",
"enableTrial": "परीक्षण सक्षम करें",
"enableTrialDescription": "जब सक्षम किया जाता है, नए उपयोगकर्ताओं को पंजीकरण के समय एक परीक्षण सदस्यता प्राप्त होगी",
"hour": "घंटा(ों)",
"inputPlaceholder": "कृपया दर्ज करें",
"ipRegistrationLimit": "आईपी पंजीकरण सीमा",
"ipRegistrationLimitDescription": "एकल आईपी पते से पंजीकरण की संख्या को सीमित करें",
"minute": "मिनट(ों)",
"month": "महीना(ों)",
"none": "कोई नहीं",
"registrationLimitCount": "पंजीकरण सीमा संख्या",
"registrationLimitCountDescription": "सीमित अवधि के भीतर प्रति आईपी अनुमत पंजीकरण की संख्या",
"registrationLimitExpire": "सीमा अवधि",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "नए उपयोगकर्ता पंजीकरण रोकें",
"stopNewUserRegistrationDescription": "जब सक्षम किया जाता है, नए उपयोगकर्ता पंजीकरण अक्षम हो जाएगा",
"title": "पंजीकरण सेटिंग्स",
"trialDay": "परीक्षण दिन",
"trialDayDescription": "पंजीकरण पर नए उपयोगकर्ताओं को दिए गए परीक्षण दिन",
"trialFlow": "परीक्षण ट्रैफ़िक",
"trialFlowDescription": "पंजीकरण पर नए उपयोगकर्ताओं को दिया गया परीक्षण ट्रैफ़िक"
"trialConfig": "परीक्षण कॉन्फ़िगरेशन",
"trialConfigDescription": "नए उपयोगकर्ताओं के लिए पंजीकरण के समय परीक्षण सदस्यता, अवधि और समय इकाई कॉन्फ़िगर करें",
"year": "साल"
},
"site": {
"customData": "कस्टम डेटा",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "További",
"additionalRecipientEmails": "További címzett e-mailek",
"additionalRecipients": "További címzettek",
"additionalRecipientsDescription": "Ezek az e-mailek a fenti felhasználói szűrőn kívül is megkapják a közvetítést",
"allUsers": "Minden felhasználó",
"broadcastList": "Közvetítési lista",
"broadcastLogs": "Közvetítési naplók",
"cancel": "Mégse",
"cannotBeEmpty": "nem lehet üres",
"completed": "Befejezve",
"confirm": "Megerősít",
"confirmDelete": "Törlés megerősítése",
"content": "E-mail tartalom",
"create": "Létrehoz",
"createBroadcast": "Közvetítés létrehozása",
"createNewEmailBroadcastCampaign": "Új e-mail közvetítési kampány létrehozása",
"createSuccess": "Sikeresen létrehozva",
"createdAt": "Létrehozva",
"dailyLimit": "A napi limitnek legalább 1-nek kell lennie",
"dailySendLimit": "Napi küldési limit",
"delete": "Törlés",
"deleteDescription": "Ez a művelet nem vonható vissza. Biztosan törölni szeretné?",
"deleteSuccess": "Sikeresen törölve",
"edit": "Szerkeszt",
"emailAddedToScheduledQueue": "E-mail hozzáadva a tervezett küldési sorhoz",
"emailBroadcast": "E-mail közvetítés",
"emailBroadcastTaskCreatedSuccessfully": "E-mail közvetítési feladat sikeresen létrehozva",
"emailBroadcastTasks": "E-mail közvetítési feladatok",
"emailContent": "E-mail tartalom",
"emailInterval": "E-mail intervallum (másodperc)",
"emailIntervalMinimum": "Az e-mail intervallumnak legalább 0,1 másodpercesnek kell lennie",
"emailMarketing": "E-mail marketing",
"emailTaskManager": "E-mail feladatkezelő",
"errorMessage": "Hibaüzenet",
"estimatedRecipients": "Becsült címzettek",
"expiredSubscriptionUsersOnly": "Csak lejárt előfizetésű felhasználók",
"expiredUsers": "Lejárt felhasználók",
"failCount": "Hibák száma",
"failed": "Sikertelen",
"failedToRefreshTaskStatus": "A feladat állapotának frissítése sikertelen",
"failedToStopTask": "A feladat leállítása sikertelen",
"inProgress": "Folyamatban",
"includeUsersRegisteredAfter": "Felhasználók, akik ezen a napon vagy azt követően regisztráltak",
"includeUsersRegisteredBefore": "Felhasználók, akik ezen a napon vagy azt megelőzően regisztráltak",
"intervalTimeBetweenEmails": "Időintervallum az egyes e-mailek között",
"leaveEmptyForImmediateSend": "Hagyja üresen az azonnali küldéshez",
"logList": "Napló lista",
"marketingManagement": "Marketing menedzsment",
"maximumNumberPerDay": "Maximum e-mailek száma naponta",
"noSubscriptionUsersOnly": "Csak előfizetéssel nem rendelkező felhasználók",
"nonSubscribers": "Nem előfizetők",
"notStarted": "Nem indult el",
"onePerLine": "egy sorban",
"only": "csak",
"pending": "Függőben",
"pleaseEnter": "Kérjük, adja meg",
"pleaseEnterValidEmailAddresses": "Kérjük, adjon meg érvényes e-mail címeket, egy sorban",
"processing": "Feldolgozás...",
"progress": "Haladás",
"recipient": "Címzett",
"recipientEmail": "Címzett e-mail",
"recipientType": "Címzett típusa",
"registrationEndDate": "Regisztrációs végdátum",
"registrationStartDate": "Regisztrációs kezdődátum",
"scheduleSend": "Küldés ütemezése",
"scheduledSend": "Ütemezett küldés",
"scheduledSendTimeMustBeLater": "Az ütemezett küldési időnek később kell lennie, mint a jelenlegi idő",
"selectSendScope": "Küldési terjedelem kiválasztása",
"selectSendTime": "Küldési idő kiválasztása, hagyja üresen az azonnali küldéshez",
"sendFailed": "A küldés sikertelen, kérjük, próbálja újra",
"sendNow": "Küldés most",
"sendScope": "Küldési terjedelem",
"sendScopeDescription": "Válassza ki a felhasználói terjedelmet az e-mail küldéséhez. Válassza a \"Csak további e-mailek\" lehetőséget, ha csak az alább megadott e-mail címekre szeretne küldeni",
"sendSettings": "Küldési beállítások",
"sendTime": "Küldési idő",
"sending": "Küldés alatt",
"sentAt": "Küldve",
"specificUsers": "Különleges felhasználók",
"specificUsersOnly": "Csak további e-mailek (platform felhasználók kihagyása)",
"status": "Állapot",
"stop": "Megállít",
"stopped": "Megállítva",
"subject": "E-mail téma",
"subscribedUsers": "Előfizetett felhasználók",
"subscribedUsersOnly": "Csak előfizetett felhasználók",
"successCount": "Sikeres küldések száma",
"taskStatusRefreshed": "Feladat állapota frissítve",
"taskStoppedSuccessfully": "Feladat sikeresen leállítva",
"totalSent": "Összes küldve",
"updateSuccess": "Sikeresen frissítve",
"useMarkdownEditor": "Használja a Markdown szerkesztőt az e-mail tartalom írásához előnézeti funkcióval",
"users": "felhasználók",
"view": "Megtekintés",
"viewAndManageEmailBroadcastTasks": "E-mail közvetítési feladatok megtekintése és kezelése",
"viewContent": "Tartalom megtekintése"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "ADS konfiguráció",
"Announcement Management": "Hirdetménykezelés",
"Apple": "Apple ID",
"Application Management": "Alkalmazáskezelés",
"Auth Control": "Hitelesítési vezérlés",
"Coupon Management": "Kuponkezelés",
"Dashboard": "Irányítópult",
"Device": "Eszköz",
"Document Management": "Dokumentumkezelés",
"Email": "E-mail",
"Facebook": "Facebook",
"Finance": "Pénzügy",
"General": "Általános",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "Marketing Menedzsment",
"Order Management": "Rendeléskezelés",
"Payment Config": "Fizetési beállítások",
"Phone Number": "Telefonszám",
"Product Management": "Termékmenedzsment",
"Protocol Management": "Protokollkezelés",
"Rule Management": "Szabálykezelés",
"Server": "Szolgáltatás",
"Server Management": "Szerverkezelés",
"Settings": "Beállítások",
"Subscribe Management": "Előfizetés kezelése",
"Subscribe Config": "Előfizetés Beállítás",
"System Config": "Rendszerkonfiguráció",
"System Management": "Rendszerkezelés",
"System Tool": "Rendszereszköz",
"Telegram": "Telegram",
"Ticket Management": "Jegykezelés",
"Twitter": "Twitter",
"User": "Felhasználó",
"User Detail": "Felhasználói részletek",
"User Management": "Felhasználókezelés"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "műveletek",
"app": {
"appDownloadURL": "Alkalmazás letöltési URL",
"appIcon": "Alkalmazás ikon",
"appList": "Alkalmazáslista",
"appName": "Alkalmazás neve",
"backupDomains": "Biztonsági tartománylista",
"backupDomainsDescription": "Biztonsági tartománylista a tartomány feloldásához, soronként egy tartomány",
"batchDelete": "Csoportos törlés",
"cancel": "Mégse",
"communicationKey": "Kommunikációs kulcs",
"communicationKeyDescription": "Kulcs az ügyfélkommunikációhoz",
"config": "Beállítás",
"configApp": "Alkalmazás beállítása",
"confirm": "Megerősítés",
"confirmDelete": "Törlés megerősítése",
"create": "Létrehozás",
"createApp": "Alkalmazás létrehozása",
"createSuccess": "Sikeresen létrehozva",
"defaultVersion": "Alapértelmezett",
"delete": "Törlés",
"deleteWarning": "Ez a művelet nem vonható vissza",
"describeDescription": "Az alkalmazás leírására szolgál, megjelenik az alkalmazáslistában",
"description": "Leírás",
"downloadLink": "Letöltési hivatkozás",
"edit": "Szerkesztés",
"editApp": "Alkalmazás szerkesztése",
"encryption": "Titkosítási módszer",
"encryptionDescription": "Válassza ki az ügyfélkommunikáció titkosítási módszerét. Ha kiválasztja, az ügyfél ezt a módszert fogja használni a szerverrel való kommunikációhoz",
"nameDescription": "Alkalmazás neve, megjelenik az alkalmazáslistában",
"platform": "Platform",
"selectApp": "Alkalmazás kiválasztása",
"selectAppDescription": "Válassza ki a konfigurálandó alkalmazást, az összes beállítás az adott alkalmazásra vonatkozik",
"startupPicture": "Indító kép",
"startupPictureDescription": "Indító kép, támogatja a hálózati és helyi képeket. Hálózati képek esetén kérjük, adja meg a teljes kép URL-jét",
"startupPicturePreview": "Indító kép előnézete",
"startupPictureSkip": "Indító kép kihagyási ideje",
"startupPictureSkipDescription": "Indító kép megjelenítési ideje másodpercben, 0 megadása esetén nem jelenik meg",
"subscriptionProtocol": "Előfizetési protokoll",
"updateSuccess": "Sikeresen frissítve",
"version": "Verzió"
},
"cancel": "Mégse",
"config": {
"singleSubscriptionMode": "Egyszeri Előfizetési Mód",
"subscriptionDomain": "Előfizetési Tartomány",
"subscriptionDomainDescription": "Előfizetéshez használatos; hagyja üresen a webhely tartományának használatához",
"subscriptionDomainPlaceholder": "Adja meg az előfizetési tartományt, soronként egyet",
"subscriptionPath": "Előfizetési Útvonal",
"subscriptionPathDescription": "Előfizetéshez használatos; a módosítás után feltétlenül indítsa újra a rendszert az optimális teljesítmény érdekében",
"subscriptionPathPlaceholder": "Adja meg",
"updateSuccess": "Sikeresen frissítve",
"wildcardResolution": "Joker Feloldás",
"wildcardResolutionDescription": "Előfizetéshez használatos"
},
"confirm": "Megerősítés",
"confirmDelete": "Biztosan törölni szeretné?",
"copy": "Másolás",
"copySuccess": "Sikeresen másolva",
"create": "Létrehozás",
"createSubscribe": "Új előfizetés létrehozása",
"createSuccess": "Sikeres létrehozás",
"delete": "törlés",
"deleteSuccess": "Sikeres törlés",
"deleteWarning": "A törlés után az adatok nem állíthatók vissza, kérjük, járjon el körültekintően.",
"deviceLimit": "Eszközök száma/db",
"edit": "szerkesztés",
"editSubscribe": "Előfizetés szerkesztése",
"form": {
"Day": "Nap",
"Hour": "Óra",
"Minute": "Perc",
"Month": "Hónap",
"NoLimit": "Nincs korlátozás",
"Year": "Év",
"annualReset": "Éves Visszaállítás",
"basic": "Alap",
"cancel": "Mégse",
"confirm": "Megerősít",
"deductionRatio": "Automatikus/Kézi Levonási Beállítás",
"deductionRatioDescription": "Levonáshoz használatos. Alapértelmezés szerint a rendszer automatikus számítási algoritmust alkalmaz. Amikor kézi arányt adnak meg, a rendszer az idő és forgalom arány alapján számítja ki az arányokat, biztosítva, hogy az összeg 100% legyen.",
"description": "Leírás",
"deviceLimit": "Eszközkorlát",
"discount": "Kedvezmény",
"discountDescription": "Kedvezmény az egységár alapján",
"discountMonths": "Hónap",
"discountPercent": "Kedvezmény százalék",
"discount_price": "Kedvezményes ár",
"duration": "Időtartam (hónap)",
"groupId": "Előfizetési csoport",
"inventory": "Előfizetési korlát",
"monthlyReset": "Havi Visszaállítás",
"name": "Név",
"noLimit": "Korlátlan",
"noReset": "Nincs Visszaállítás",
"pricing": "Árazás",
"purchaseWithDiscount": "Levonás Engedélyezése",
"purchaseWithDiscountDescription": "Leiratkozási funkció engedélyezése vagy letiltása. Aktiválás után a rendszer a beállított szabályok és arányok szerint végzi el a levonási feldolgozást, és a fennmaradó értéket visszatéríti az egyenlegre.",
"quota": "Vásárlási korlát",
"renewalReset": "Megújítási Visszaállítás",
"renewalResetDescription": "Visszaállítási ciklus megújításkor",
"replacement": "Csere ára (alkalmanként)",
"resetCycle": "Visszaállítási Ciklus",
"resetOn1st": "Visszaállítás 1-jén",
"selectResetCycle": "Kérjük, válasszon visszaállítási ciklust",
"selectSubscribeGroup": "Kérjük, válassza ki az előfizetési csoportot",
"selectUnitTime": "Kérjük, válassza ki az időegységet",
"server": "Szolgáltatás",
"serverGroup": "Szolgáltatáscsoport",
"servers": "Szerverek",
"speedLimit": "Sebességkorlát ",
"traffic": "Forgalom",
"unitPrice": "Egységár",
"unitTime": "Időegység"
},
"group": {
"actions": "Műveletek",
"cancel": "Mégse",
"confirm": "Megerősít",
"confirmDelete": "Biztosan törölni szeretné?",
"create": "Létrehozás",
"createSubscribeGroup": "Új előfizetési csoport létrehozása",
"createSuccess": "Sikeres létrehozás",
"delete": "Törlés",
"deleteSuccess": "Sikeres törlés",
"deleteWarning": "A törlés után az adatok nem állíthatók vissza, kérjük, legyen óvatos.",
"description": "Leírás",
"edit": "Szerkesztés",
"editSubscribeGroup": "Előfizetési csoport szerkesztése",
"form": {
"cancel": "Mégse",
"confirm": "Megerősít",
"description": "Leírás",
"name": "Név"
},
"name": "Név",
"title": "Előfizetési csoportok listája",
"updateSuccess": "Sikeres frissítés",
"updatedAt": "Frissítés ideje"
},
"inventory": "Előfizetési korlát",
"name": "Név",
"quota": "Vásárlási korlát/alkalom",
"replacement": "Ár visszaállítása/alkalom",
"sell": "eladás",
"show": "Megjelenítés",
"sold": "Előfizetések száma",
"subscribe": "Feliratkozás",
"subscribeGroup": "Feliratkozási csoport",
"tabs": {
"subscribe": "Feliratkozás",
"subscribeApp": "Alkalmazás konfiguráció",
"subscribeConfig": "Előfizetés konfiguráció",
"subscribeGroup": "Feliratkozási csoport"
},
"traffic": "forgalom",
"unitPrice": "Egységár",
"updateSuccess": "Sikeres frissítés"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "Típus",
"updateSuccess": "Sikeres frissítés",
"updatedAt": "Frissítés ideje",
"userAccount": "Felhasználói Fiók",
"user": "Felhasználó",
"userDetail": "Felhasználói Részletek",
"userId": "Felhasználói Azonosító"
},
+115 -144
View File
@@ -1,161 +1,132 @@
{
"actions": "műveletek",
"app": {
"appDownloadURL": "Alkalmazás letöltési URL",
"appIcon": "Alkalmazás ikon",
"appList": "Alkalmazáslista",
"appName": "Alkalmazás neve",
"backupDomains": "Biztonsági tartománylista",
"backupDomainsDescription": "Biztonsági tartománylista a tartomány feloldásához, soronként egy tartomány",
"batchDelete": "Csoportos törlés",
"actions": {
"add": "Hozzáadás",
"batchDelete": "Tömeges törlés",
"batchDeleteSuccess": "Sikeresen törölt {count} ügyfelet",
"batchDeleteWarning": "Biztosan törölni szeretné a kiválasztott {count} ügyfelet?",
"cancel": "Mégse",
"communicationKey": "Kommunikációs kulcs",
"communicationKeyDescription": "Kulcs az ügyfélkommunikációhoz",
"config": "Beállítás",
"configApp": "Alkalmazás beállítása",
"confirm": "Megerősítés",
"confirmDelete": "Törlés megerősítése",
"create": "Létrehozás",
"createApp": "Alkalmazás létrehozása",
"createSuccess": "Sikeresen létrehozva",
"defaultVersion": "Alapértelmezett",
"delete": "Törlés",
"deleteWarning": "Ez a művelet nem vonható vissza",
"describeDescription": "Az alkalmazás leírására szolgál, megjelenik az alkalmazáslistában",
"description": "Leírás",
"downloadLink": "Letöltési hivatkozás",
"deleteFailed": "Törlés sikertelen",
"deleteSuccess": "Sikeresen törölve",
"deleteWarning": "Ez a művelet nem vonható vissza. Biztosan törölni szeretné ezt az ügyfelet?",
"edit": "Szerkesztés",
"editApp": "Alkalmazás szerkesztése",
"encryption": "Titkosítási módszer",
"encryptionDescription": "Válassza ki az ügyfélkommunikáció titkosítási módszerét. Ha kiválasztja, az ügyfél ezt a módszert fogja használni a szerverrel való kommunikációhoz",
"nameDescription": "Alkalmazás neve, megjelenik az alkalmazáslistában",
"platform": "Platform",
"selectApp": "Alkalmazás kiválasztása",
"selectAppDescription": "Válassza ki a konfigurálandó alkalmazást, az összes beállítás az adott alkalmazásra vonatkozik",
"startupPicture": "Indító kép",
"startupPictureDescription": "Indító kép, támogatja a hálózati és helyi képeket. Hálózati képek esetén kérjük, adja meg a teljes kép URL-jét",
"startupPicturePreview": "Indító kép előnézete",
"startupPictureSkip": "Indító kép kihagyási ideje",
"startupPictureSkipDescription": "Indító kép megjelenítési ideje másodpercben, 0 megadása esetén nem jelenik meg",
"subscriptionProtocol": "Előfizetési protokoll",
"updateSuccess": "Sikeresen frissítve",
"version": "Verzió"
"save": "Mentés",
"saveFailed": "Mentés sikertelen",
"update": "Frissítés",
"updateSuccess": "Sikeresen frissítve"
},
"cancel": "Mégse",
"config": {
"description": "Előfizetési rendszer beállításainak kezelése",
"singleSubscriptionMode": "Egyszeri Előfizetési Mód",
"singleSubscriptionModeDescription": "Ha engedélyezve van, az összes felhasználói előfizetés egyenlegre lesz átváltva",
"subscriptionDomain": "Előfizetési Tartomány",
"subscriptionDomainDescription": "Előfizetéshez használatos; hagyja üresen a webhely tartományának használatához",
"subscriptionDomainPlaceholder": "Adja meg az előfizetési tartományt, soronként egyet",
"singleSubscriptionModeDescription": "Korlátozza a felhasználókat egy aktív előfizetésre. A meglévő előfizetések nem érintettek",
"subscriptionDomain": "Előfizetési Domain",
"subscriptionDomainDescription": "Egyedi domain az előfizetési linkekhez",
"subscriptionDomainPlaceholder": "Adja meg az előfizetési domaint, soronként egyet",
"subscriptionPath": "Előfizetési Útvonal",
"subscriptionPathDescription": "Előfizetéshez használatos; a módosítás után feltétlenül indítsa újra a rendszert az optimális teljesítmény érdekében",
"subscriptionPathPlaceholder": "Adja meg",
"updateSuccess": "Sikeresen frissítve",
"wildcardResolution": "Joker Feloldás",
"wildcardResolutionDescription": "Előfizetéshez használatos"
"subscriptionPathDescription": "Egyedi útvonal az előfizetési végpontokhoz (jobb teljesítmény a rendszer újraindítása után)",
"subscriptionPathPlaceholder": "Adja meg az előfizetési útvonalat",
"title": "Előfizetés Beállítások",
"updateError": "Frissítés sikertelen",
"updateSuccess": "Beállítások sikeresen frissítve",
"userAgentLimit": "{userAgent} Korlátozás",
"userAgentLimitDescription": "Engedélyezze a hozzáférési korlátozásokat a {userAgent} alapján",
"userAgentList": "{userAgent} Fehérlista",
"userAgentListDescription": "Engedélyezett {userAgent} az előfizetési hozzáféréshez, soronként egyet. A konfigurált alkalmazás {userAgent} automatikusan belekerül",
"userAgentListPlaceholder": "Adja meg az engedélyezett {userAgent} értékeket, soronként egyet",
"wildcardResolution": "Joker karakterek feloldása",
"wildcardResolutionDescription": "Engedélyezze a joker karakterek domain feloldását az előfizetésekhez"
},
"confirm": "Megerősítés",
"confirmDelete": "Biztosan törölni szeretné?",
"copy": "Másolás",
"copySuccess": "Sikeresen másolva",
"create": "Létrehozás",
"createSubscribe": "Új előfizetés létrehozása",
"createSuccess": "Sikeres létrehozás",
"delete": "törlés",
"deleteSuccess": "Sikeres törlés",
"deleteWarning": "A törlés után az adatok nem állíthatók vissza, kérjük, járjon el körültekintően.",
"deviceLimit": "Eszközök száma/db",
"edit": "szerkesztés",
"editSubscribe": "Előfizetés szerkesztése",
"form": {
"Day": "Nap",
"Hour": "Óra",
"Minute": "Perc",
"Month": "Hónap",
"NoLimit": "Nincs korlátozás",
"Year": "Év",
"annualReset": "Éves Visszaállítás",
"basic": "Alap",
"cancel": "Mégse",
"confirm": "Megerősít",
"deductionRatio": "Automatikus/Kézi Levonási Beállítás",
"deductionRatioDescription": "Levonáshoz használatos. Alapértelmezés szerint a rendszer automatikus számítási algoritmust alkalmaz. Amikor kézi arányt adnak meg, a rendszer az idő és forgalom arány alapján számítja ki az arányokat, biztosítva, hogy az összeg 100% legyen.",
"description": "Leírás",
"deviceLimit": "Eszközkort",
"discount": "Kedvezmény",
"discountDescription": "Kedvezmény az egységár alapján",
"discountMonths": "Hónap",
"discountPercent": "Kedvezmény százalék",
"discount_price": "Kedvezményes ár",
"duration": "Időtartam (hónap)",
"groupId": "Előfizetési csoport",
"inventory": "Előfizetési korlát",
"monthlyReset": "Havi Visszaállítás",
"name": "Név",
"noLimit": "Korlátlan",
"noReset": "Nincs Visszaállítás",
"pricing": "Árazás",
"purchaseWithDiscount": "Levonás Engedélyezése",
"purchaseWithDiscountDescription": "Leiratkozási funkció engedélyezése vagy letiltása. Aktiválás után a rendszer a beállított szabályok és arányok szerint végzi el a levonási feldolgozást, és a fennmaradó értéket visszatéríti az egyenlegre.",
"quota": "Vásárlási korlát",
"renewalReset": "Megújítási Visszaállítás",
"renewalResetDescription": "Visszaállítási ciklus megújításkor",
"replacement": "Csere ára (alkalmanként)",
"resetCycle": "Visszaállítási Ciklus",
"resetOn1st": "Visszaállítás 1-jén",
"selectResetCycle": "Kérjük, válasszon visszaállítási ciklust",
"selectSubscribeGroup": "Kérjük, válassza ki az előfizetési csoportot",
"selectUnitTime": "Kérjük, válassza ki az időegységet",
"server": "Szolgáltatás",
"serverGroup": "Szolgáltatáscsoport",
"servers": "Szerverek",
"speedLimit": "Sebességkorlát ",
"traffic": "Forgalom",
"unitPrice": "Egységár",
"unitTime": "Időegység"
},
"group": {
"actions": "Műveletek",
"cancel": "Mégse",
"confirm": "Megerősít",
"confirmDelete": "Biztosan törölni szeretné?",
"create": "Létrehozás",
"createSubscribeGroup": "Új előfizetési csoport létrehozása",
"createSuccess": "Sikeres létrehozás",
"delete": "Törlés",
"deleteSuccess": "Sikeres törlés",
"deleteWarning": "A törlés után az adatok nem állíthatók vissza, kérjük, legyen óvatos.",
"description": "Leírás",
"edit": "Szerkesztés",
"editSubscribeGroup": "Előfizetési csoport szerkesztése",
"form": {
"cancel": "Mégse",
"confirm": "Megerősít",
"description": "Leírás",
"name": "Név"
"addTitle": "Ügyfél Hozzáadása",
"descriptions": {
"description": "Részletes ügyfél leírás",
"downloadLink": "platform letöltési URL",
"icon": "Ikon URL vagy base64 kódolás",
"name": "Ügyfél megjelenítési neve",
"outputFormat": "Előfizetési konfigurációs fájl formátum",
"scheme": {
"base64Encoding": "Base64 kódolás",
"functions": "Támogatott funkciók:",
"jsonStringify": "JSON objektum stringgé alakítása",
"nameVariable": "webhely neve",
"title": "URL séma sablon",
"urlEncoding": "URL kódos",
"urlVariable": "előfizetési URL",
"variables": "Támogatott változók:"
},
"template": {
"description": "Használja a Go sablon szintaxist az előfizetési konfigurációs fájlok generálásához",
"functions": "Sablon funkciók:",
"if": "feltételes állítások",
"nodes": "proxy csomópontok listája",
"range": "tömbök iterálása",
"siteName": "webhely neve",
"sprig": "Sprig funkció könyvtár (string feldolgozás, dátumok, stb.)",
"subscribeName": "előfizetés neve",
"title": "Go Sablon Szintaxis",
"userInfo": "felhasználói információ (forgalom, lejárat, stb.)",
"variables": "Elérhető változók:"
},
"userAgentPrefix": "Ügyfél azonosító a különböző ügyfelek megkülönböztetésére"
},
"name": "Név",
"title": "Előfizetési csoportok listája",
"updateSuccess": "Sikeres frissítés",
"updatedAt": "Frissítés ideje"
"editTitle": "Ügyfél Szerkesztése",
"fields": {
"description": "Leírás",
"icon": "Ikon",
"name": "Név",
"outputFormat": "Kimeneti Formátum",
"scheme": "URL séma",
"template": "Előfizetési Fájl Sablon"
},
"tabs": {
"basic": "Alap Információk",
"download": "Letöltések",
"template": "Sablonok"
},
"validation": {
"nameRequired": "Ügyfél név megadása kötelező",
"userAgentRequiredSuffix": "megadása kötelező"
}
},
"inventory": "Előfizetési korlát",
"name": "Név",
"quota": "Vásárlási korlát/alkalom",
"replacement": "Ár visszaállítása/alkalom",
"sell": "eladás",
"show": "Megjelenítés",
"sold": "Előfizetések száma",
"subscribe": "Feliratkozás",
"subscribeGroup": "Feliratkozási csoport",
"tabs": {
"subscribe": "Feliratkozás",
"subscribeApp": "Alkalmazás konfiguráció",
"subscribeConfig": "Előfizetés konfiguráció",
"subscribeGroup": "Feliratkozási csoport"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "Egyszerű Szöveg",
"yaml": "YAML"
},
"traffic": "forgalom",
"unitPrice": "Egységár",
"updateSuccess": "Sikeres frissítés"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "Ügyfélkezelés"
},
"table": {
"columns": {
"default": "Alapértelmezett",
"description": "Leírás",
"name": "Ügyfél Neve",
"outputFormat": "Kimeneti Formátum",
"supportedPlatforms": "Támogatott Platformok"
}
},
"templatePreview": {
"base64": {
"decodeError": "Dekódolás sikertelen: A tartalom nem érvényes Base64 formátum",
"decodedContent": "Dekódolt Tartalom",
"originalContent": "Eredeti Tartalom (Base64)"
},
"failed": "Az előnézet nem sikerült",
"loading": "Betöltés...",
"preview": "Előnézet",
"title": "Sablon Előnézet"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "nap(napok)",
"defaultSubscribe": "Alapértelmezett előfizetés",
"defaultSubscribeDescription": "Alapértelmezett előfizetési terv új felhasználók számára",
"description": "Felhasználói regisztrációval kapcsolatos beállítások konfigurálása",
"enableTrial": "Próbaverzió engedélyezése",
"enableTrialDescription": "Ha engedélyezve van, az új felhasználók próbaelőfizetést kapnak a regisztráció során",
"hour": "Óra(ák)",
"inputPlaceholder": "Kérjük, adja meg",
"ipRegistrationLimit": "IP regisztrációs korlát",
"ipRegistrationLimitDescription": "Korlátozza a regisztrációk számát egyetlen IP címről",
"minute": "Perc(ek)",
"month": "Hónap(ok)",
"none": "Nincs",
"registrationLimitCount": "Regisztrációs korlát száma",
"registrationLimitCountDescription": "A megengedett regisztrációk száma IP-nként a korlátozási időszakon belül",
"registrationLimitExpire": "Korlátozási időszak",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "Új felhasználói regisztráció leállítása",
"stopNewUserRegistrationDescription": "Ha engedélyezve van, az új felhasználói regisztráció le lesz tiltva",
"title": "Regisztrációs beállítások",
"trialDay": "Próbák napjai",
"trialDayDescription": "Próbás napok, amelyeket új felhasználóknak adunk regisztrációkor",
"trialFlow": "Próbaforgalom",
"trialFlowDescription": "Próbaforgalom, amelyet új felhasználóknak adunk regisztrációkor"
"trialConfig": "Próbaverzió beállítás",
"trialConfigDescription": "Próbás előfizetés konfigurálása, időtartam és időegység új felhasználók számára a regisztráció során",
"year": "Év(ek)"
},
"site": {
"customData": "Egyedi adatok",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "追加",
"additionalRecipientEmails": "追加の受信者メール",
"additionalRecipients": "追加の受信者",
"additionalRecipientsDescription": "これらのメールは、上記のユーザーフィルターに加えて放送を受信します",
"allUsers": "すべてのユーザー",
"broadcastList": "放送リスト",
"broadcastLogs": "放送ログ",
"cancel": "キャンセル",
"cannotBeEmpty": "空にすることはできません",
"completed": "完了",
"confirm": "確認",
"confirmDelete": "削除を確認",
"content": "メール内容",
"create": "作成",
"createBroadcast": "放送を作成",
"createNewEmailBroadcastCampaign": "新しいメール放送キャンペーンを作成",
"createSuccess": "作成に成功しました",
"createdAt": "作成日時",
"dailyLimit": "1以上のデイリーログが必要です",
"dailySendLimit": "デイリー送信制限",
"delete": "削除",
"deleteDescription": "この操作は元に戻せません。本当に削除しますか?",
"deleteSuccess": "削除に成功しました",
"edit": "編集",
"emailAddedToScheduledQueue": "メールがスケジュール送信キューに追加されました",
"emailBroadcast": "メール放送",
"emailBroadcastTaskCreatedSuccessfully": "メール放送タスクが正常に作成されました",
"emailBroadcastTasks": "メール放送タスク",
"emailContent": "メール内容",
"emailInterval": "メール間隔(秒)",
"emailIntervalMinimum": "メール間隔は0.1秒以上でなければなりません",
"emailMarketing": "メールマーケティング",
"emailTaskManager": "メールタスクマネージャー",
"errorMessage": "エラーメッセージ",
"estimatedRecipients": "推定受信者",
"expiredSubscriptionUsersOnly": "期限切れのサブスクリプションユーザーのみ",
"expiredUsers": "期限切れのユーザー",
"failCount": "失敗数",
"failed": "失敗",
"failedToRefreshTaskStatus": "タスクステータスの更新に失敗しました",
"failedToStopTask": "タスクの停止に失敗しました",
"inProgress": "進行中",
"includeUsersRegisteredAfter": "この日以降に登録されたユーザーを含める",
"includeUsersRegisteredBefore": "この日以前に登録されたユーザーを含める",
"intervalTimeBetweenEmails": "各メール間の間隔時間",
"leaveEmptyForImmediateSend": "即時送信のために空白のままにする",
"logList": "ログリスト",
"marketingManagement": "マーケティング管理",
"maximumNumberPerDay": "1日に送信できるメールの最大数",
"noSubscriptionUsersOnly": "サブスクリプションのないユーザーのみ",
"nonSubscribers": "非購読者",
"notStarted": "未開始",
"onePerLine": "1行に1つ",
"only": "のみ",
"pending": "保留中",
"pleaseEnter": "入力してください",
"pleaseEnterValidEmailAddresses": "有効なメールアドレスを入力してください(1行に1つ)",
"processing": "処理中...",
"progress": "進捗",
"recipient": "受信者",
"recipientEmail": "受信者メール",
"recipientType": "受信者タイプ",
"registrationEndDate": "登録終了日",
"registrationStartDate": "登録開始日",
"scheduleSend": "送信スケジュール",
"scheduledSend": "スケジュール送信",
"scheduledSendTimeMustBeLater": "スケジュール送信時間は現在の時間よりも遅くなければなりません",
"selectSendScope": "送信範囲を選択",
"selectSendTime": "送信時間を選択、即時送信のために空白のままにする",
"sendFailed": "送信に失敗しました。再試行してください",
"sendNow": "今すぐ送信",
"sendScope": "送信範囲",
"sendScopeDescription": "メール送信のユーザー範囲を選択します。「追加のメールのみ」を選択すると、下に入力されたメールアドレスのみに送信されます",
"sendSettings": "送信設定",
"sendTime": "送信時間",
"sending": "送信中",
"sentAt": "送信日時",
"specificUsers": "特定のユーザー",
"specificUsersOnly": "追加のメールのみ(プラットフォームユーザーをスキップ)",
"status": "ステータス",
"stop": "停止",
"stopped": "停止しました",
"subject": "メール件名",
"subscribedUsers": "購読ユーザー",
"subscribedUsersOnly": "購読ユーザーのみ",
"successCount": "成功数",
"taskStatusRefreshed": "タスクステータスが更新されました",
"taskStoppedSuccessfully": "タスクが正常に停止しました",
"totalSent": "合計送信数",
"updateSuccess": "更新に成功しました",
"useMarkdownEditor": "プレビュー機能を使ってメール内容を書くためにMarkdownエディタを使用",
"users": "ユーザー",
"view": "表示",
"viewAndManageEmailBroadcastTasks": "メール放送タスクを表示および管理",
"viewContent": "内容を表示"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "ADS設定",
"Announcement Management": "お知らせ管理",
"Apple": "Apple ID",
"Application Management": "アプリケーション管理",
"Auth Control": "認証管理",
"Coupon Management": "クーポン管理",
"Dashboard": "ダッシュボード",
"Device": "デバイス",
"Document Management": "ドキュメント管理",
"Email": "メール",
"Facebook": "Facebook",
"Finance": "財務",
"General": "一般",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "マーケティングマネジメント",
"Order Management": "注文管理",
"Payment Config": "支払い設定",
"Phone Number": "電話番号",
"Product Management": "プロダクトマネジメント",
"Protocol Management": "プロトコル管理",
"Rule Management": "ルール管理",
"Server": "サーバー",
"Server Management": "サーバー管理",
"Settings": "設定",
"Subscribe Management": "サブスクリプション管理",
"Subscribe Config": "サブスクリプション設定",
"System Config": "システム構成",
"System Management": "システム管理",
"System Tool": "システムツール",
"Telegram": "テレグラム",
"Ticket Management": "チケット管理",
"Twitter": "Twitter",
"User": "ユーザー",
"User Detail": "ユーザー詳細",
"User Management": "ユーザー管理"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "アクション",
"app": {
"appDownloadURL": "アプリダウンロードURL",
"appIcon": "アプリアイコン",
"appList": "アプリリスト",
"appName": "アプリ名",
"backupDomains": "バックアップドメインリスト",
"backupDomainsDescription": "ドメイン解決のためのバックアップドメインリスト、1行に1つのドメイン",
"batchDelete": "一括削除",
"cancel": "キャンセル",
"communicationKey": "通信キー",
"communicationKeyDescription": "クライアント通信に使用されるキー",
"config": "設定",
"configApp": "アプリ設定",
"confirm": "確認",
"confirmDelete": "削除を確認",
"create": "作成",
"createApp": "アプリ作成",
"createSuccess": "作成に成功しました",
"defaultVersion": "デフォルト",
"delete": "削除",
"deleteWarning": "この操作は元に戻せません",
"describeDescription": "アプリケーションを説明するために使用され、アプリリストに表示されます",
"description": "説明",
"downloadLink": "ダウンロードリンク",
"edit": "編集",
"editApp": "アプリ編集",
"encryption": "暗号化方式",
"encryptionDescription": "クライアント通信の暗号化方式を選択してください。選択された場合、クライアントはこの方式を使用してサーバーと通信します",
"nameDescription": "アプリケーション名、アプリリストに表示されます",
"platform": "プラットフォーム",
"selectApp": "アプリを選択",
"selectAppDescription": "設定するアプリを選択してください。すべての設定は選択したアプリに適用されます",
"startupPicture": "スタートアップ画像",
"startupPictureDescription": "スタートアップ画像、ネットワークおよびローカル画像をサポートします。ネットワーク画像の場合は、完全な画像URLを入力してください",
"startupPicturePreview": "スタートアップ画像プレビュー",
"startupPictureSkip": "スタートアップ画像スキップ時間",
"startupPictureSkipDescription": "スタートアップ画像の表示時間(秒)、表示しない場合は0を入力",
"subscriptionProtocol": "サブスクリプションプロトコル",
"updateSuccess": "更新に成功しました",
"version": "バージョン"
},
"cancel": "キャンセル",
"config": {
"singleSubscriptionMode": "シングルサブスクリプションモード",
"subscriptionDomain": "サブスクリプションドメイン",
"subscriptionDomainDescription": "サブスクリプションに使用します。サイトドメインを使用する場合は空白のままにしてください",
"subscriptionDomainPlaceholder": "サブスクリプションドメインを入力してください。1行に1つずつ",
"subscriptionPath": "サブスクリプションパス",
"subscriptionPathDescription": "サブスクリプションに使用します。最適なパフォーマンスのために、変更後は必ずシステムを再起動してください",
"subscriptionPathPlaceholder": "入力してください",
"updateSuccess": "更新が成功しました",
"wildcardResolution": "ワイルドカード解決",
"wildcardResolutionDescription": "サブスクリプションに使用します"
},
"confirm": "確認",
"confirmDelete": "削除してもよろしいですか?",
"copy": "コピー",
"copySuccess": "コピーしました",
"create": "作成",
"createSubscribe": "新規購読",
"createSuccess": "作成に成功しました",
"delete": "削除",
"deleteSuccess": "削除に成功しました",
"deleteWarning": "削除後、データは復元できませんので、慎重に操作してください。",
"deviceLimit": "デバイス数/台",
"edit": "編集",
"editSubscribe": "サブスクリプションを編集",
"form": {
"Day": "日",
"Hour": "時",
"Minute": "分",
"Month": "月",
"NoLimit": "制限なし",
"Year": "年",
"annualReset": "毎年リセット",
"basic": "基本",
"cancel": "キャンセル",
"confirm": "確認",
"deductionRatio": "自動/手動控除設定",
"deductionRatioDescription": "控除に使用されます。デフォルトでは、システムは自動計算アルゴリズムを採用します。手動比率が提供されると、システムは時間とトラフィックの比率に基づいて割合を計算し、合計が100%になるようにします。",
"description": "説明",
"deviceLimit": "デバイス制限",
"discount": "割引",
"discountDescription": "単価に基づく割引設定",
"discountMonths": "月",
"discountPercent": "割引率",
"discount_price": "割引価格",
"duration": "期間(月)",
"groupId": "サブスクリプショングループ",
"inventory": "サブスクリプション制限",
"monthlyReset": "毎月リセット",
"name": "名称",
"noLimit": "無制限",
"noReset": "リセットなし",
"pricing": "価格設定",
"purchaseWithDiscount": "控除を許可",
"purchaseWithDiscountDescription": "購読解除機能を有効または無効にします。有効化後、システムは設定されたルールと割合に従って控除処理を行い、残りの金額を残高に返金します。",
"quota": "購入制限数",
"renewalReset": "更新時リセット",
"renewalResetDescription": "更新時にリセットサイクル",
"replacement": "リセット価格(毎回)",
"resetCycle": "リセットサイクル",
"resetOn1st": "1日にリセット",
"selectResetCycle": "リセットサイクルを選択してください",
"selectSubscribeGroup": "サブスクリプショングループを選択してください",
"selectUnitTime": "単位時間を選択してください",
"server": "サーバー",
"serverGroup": "サーバーグループ",
"servers": "サーバー",
"speedLimit": "速度制限",
"traffic": "トラフィック",
"unitPrice": "単価",
"unitTime": "単位時間"
},
"group": {
"actions": "操作",
"cancel": "キャンセル",
"confirm": "確認",
"confirmDelete": "削除してもよろしいですか?",
"create": "作成",
"createSubscribeGroup": "新しい購読グループを作成",
"createSuccess": "作成成功",
"delete": "削除",
"deleteSuccess": "削除成功",
"deleteWarning": "削除後はデータを復元できませんので、慎重に操作してください。",
"description": "説明",
"edit": "編集",
"editSubscribeGroup": "購読グループを編集",
"form": {
"cancel": "キャンセル",
"confirm": "確認",
"description": "説明",
"name": "名前"
},
"name": "名前",
"title": "購読グループ一覧",
"updateSuccess": "更新成功",
"updatedAt": "更新日時"
},
"inventory": "サブスクリプションの制限",
"name": "名前",
"quota": "購入制限/回",
"replacement": "リセット価格/回",
"sell": "販売",
"show": "表示",
"sold": "サブスクリプション数",
"subscribe": "購読",
"subscribeGroup": "グループを購読する",
"tabs": {
"subscribe": "購読",
"subscribeApp": "アプリ設定",
"subscribeConfig": "サブスクリプション設定",
"subscribeGroup": "購読グループ"
},
"traffic": "トラフィック",
"unitPrice": "単価",
"updateSuccess": "更新が成功しました"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "タイプ",
"updateSuccess": "更新成功",
"updatedAt": "更新時間",
"userAccount": "ユーザーアカウント",
"user": "ユーザー",
"userDetail": "ユーザーの詳細",
"userId": "ユーザーID"
},
+114 -143
View File
@@ -1,161 +1,132 @@
{
"actions": "アクション",
"app": {
"appDownloadURL": "アプリダウンロードURL",
"appIcon": "アプリアイコン",
"appList": "アプリリスト",
"appName": "アプリ名",
"backupDomains": "バックアップドメインリスト",
"backupDomainsDescription": "ドメイン解決のためのバックアップドメインリスト、1行に1つのドメイン",
"actions": {
"add": "追加",
"batchDelete": "一括削除",
"batchDeleteSuccess": "{count} 件のクライアントを正常に削除しました",
"batchDeleteWarning": "選択した {count} 件のクライアントを削除してもよろしいですか?",
"cancel": "キャンセル",
"communicationKey": "通信キー",
"communicationKeyDescription": "クライアント通信に使用されるキー",
"config": "設定",
"configApp": "アプリ設定",
"confirm": "確認",
"confirmDelete": "削除を確認",
"create": "作成",
"createApp": "アプリ作成",
"createSuccess": "作成に成功しました",
"defaultVersion": "デフォルト",
"createSuccess": "正常に作成されました",
"delete": "削除",
"deleteWarning": "この操作は元に戻せません",
"describeDescription": "アプリケーションを説明するために使用され、アプリリストに表示されま",
"description": "説明",
"downloadLink": "ダウンロードリンク",
"deleteFailed": "削除に失敗しました",
"deleteSuccess": "正常に削除されました",
"deleteWarning": "この操作は元に戻せません。本当にこのクライアントを削除してもよろしいですか?",
"edit": "編集",
"editApp": "アプリ編集",
"encryption": "暗号化方式",
"encryptionDescription": "クライアント通信の暗号化方式を選択してください。選択された場合、クライアントはこの方式を使用してサーバーと通信します",
"nameDescription": "アプリケーション名、アプリリストに表示されます",
"platform": "プラットフォーム",
"selectApp": "アプリを選択",
"selectAppDescription": "設定するアプリを選択してください。すべての設定は選択したアプリに適用されます",
"startupPicture": "スタートアップ画像",
"startupPictureDescription": "スタートアップ画像、ネットワークおよびローカル画像をサポートします。ネットワーク画像の場合は、完全な画像URLを入力してください",
"startupPicturePreview": "スタートアップ画像プレビュー",
"startupPictureSkip": "スタートアップ画像スキップ時間",
"startupPictureSkipDescription": "スタートアップ画像の表示時間(秒)、表示しない場合は0を入力",
"subscriptionProtocol": "サブスクリプションプロトコル",
"updateSuccess": "更新に成功しました",
"version": "バージョン"
"save": "保存",
"saveFailed": "保存に失敗しました",
"update": "更新",
"updateSuccess": "正常に更新されました"
},
"cancel": "キャンセル",
"config": {
"singleSubscriptionMode": "シングルサブスクリプションモード",
"singleSubscriptionModeDescription": "有効にすると、すべてのユーザーサブスクリプションがバランスに変換されます",
"description": "サブスクリプションシステムの設定を管理します",
"singleSubscriptionMode": "単一サブスクリプションモード",
"singleSubscriptionModeDescription": "ユーザーを1つのアクティブなサブスクリプションに制限します。既存のサブスクリプションには影響しません",
"subscriptionDomain": "サブスクリプションドメイン",
"subscriptionDomainDescription": "サブスクリプションに使用します。サイトドメインを使用する場合は空白のままにしてください",
"subscriptionDomainPlaceholder": "サブスクリプションドメインを入力してください1行に1つずつ",
"subscriptionDomainDescription": "サブスクリプションリンク用のカスタムドメイン",
"subscriptionDomainPlaceholder": "サブスクリプションドメインを入力してください1行につき1つ)",
"subscriptionPath": "サブスクリプションパス",
"subscriptionPathDescription": "サブスクリプションに使用します。最適なパフォーマンスのために、変更後は必ずシステム再起動してください",
"subscriptionPathPlaceholder": "入力してください",
"updateSuccess": "更新が成功しました",
"subscriptionPathDescription": "サブスクリプションエンドポイント用のカスタムパス(システム再起動後のパフォーマンス向上)",
"subscriptionPathPlaceholder": "サブスクリプションパスを入力してください",
"title": "サブスクリプション設定",
"updateError": "更新に失敗しました",
"updateSuccess": "設定が正常に更新されました",
"userAgentLimit": "{userAgent} 制限",
"userAgentLimitDescription": "{userAgent} に基づくアクセス制限を有効にします",
"userAgentList": "{userAgent} ホワイトリスト",
"userAgentListDescription": "サブスクリプションアクセスを許可された {userAgent}(1行につき1つ)。構成されたアプリケーション {userAgent} は自動的に含まれます",
"userAgentListPlaceholder": "許可された {userAgent} を入力してください(1行につき1つ)",
"wildcardResolution": "ワイルドカード解決",
"wildcardResolutionDescription": "サブスクリプションに使用します"
"wildcardResolutionDescription": "サブスクリプション用のワイルドカードドメイン解決を有効にします"
},
"confirm": "確認",
"confirmDelete": "削除してもよろしいですか?",
"copy": "コピー",
"copySuccess": "コピーしました",
"create": "作成",
"createSubscribe": "新規購読",
"createSuccess": "作成に成功しました",
"delete": "削除",
"deleteSuccess": "削除に成功しました",
"deleteWarning": "削除後、データは復元できませんので、慎重に操作してください。",
"deviceLimit": "デバイス数/台",
"edit": "編集",
"editSubscribe": "サブスクリプションを編集",
"form": {
"Day": "日",
"Hour": "時",
"Minute": "分",
"Month": "月",
"NoLimit": "制限なし",
"Year": "年",
"annualReset": "毎年リセット",
"basic": "基本",
"cancel": "キャンセル",
"confirm": "確認",
"deductionRatio": "自動/手動控除設定",
"deductionRatioDescription": "控除に使用されます。デフォルトでは、システムは自動計算アルゴリズムを採用します。手動比率が提供されると、システムは時間とトラフィックの比率に基づいて割合を計算し、合計が100%になるようにします。",
"description": "説明",
"deviceLimit": "デバイス制限",
"discount": "割引",
"discountDescription": "単価に基づく割引設定",
"discountMonths": "月",
"discountPercent": "割引率",
"discount_price": "割引価格",
"duration": "期間(月)",
"groupId": "サブスクリプショングループ",
"inventory": "サブスクリプション制限",
"monthlyReset": "毎月リセット",
"name": "名",
"noLimit": "無制限",
"noReset": "リセットなし",
"pricing": "価格設定",
"purchaseWithDiscount": "控除を許可",
"purchaseWithDiscountDescription": "購読解除機能を有効または無効にします。有効化後、システムは設定されたルールと割合に従って控除処理を行い、残りの金額を残高に返金します。",
"quota": "購入制限数",
"renewalReset": "更新時リセット",
"renewalResetDescription": "更新時にリセットサイクル",
"replacement": "リセット価格(毎回)",
"resetCycle": "リセットサイクル",
"resetOn1st": "1日にリセット",
"selectResetCycle": "リセットサイクルを選択してください",
"selectSubscribeGroup": "サブスクリプショングループを選択してください",
"selectUnitTime": "単位時間を選択してください",
"server": "サーバー",
"serverGroup": "サーバーグループ",
"servers": "サーバー",
"speedLimit": "速度制限",
"traffic": "トラフィック",
"unitPrice": "単価",
"unitTime": "単位時間"
},
"group": {
"actions": "操作",
"cancel": "キャンセル",
"confirm": "確認",
"confirmDelete": "削除してもよろしいですか?",
"create": "作成",
"createSubscribeGroup": "新しい購読グループを作成",
"createSuccess": "作成成功",
"delete": "削除",
"deleteSuccess": "削除成功",
"deleteWarning": "削除後はデータを復元できませんので、慎重に操作してください。",
"description": "説明",
"edit": "編集",
"editSubscribeGroup": "購読グループを編集",
"form": {
"cancel": "キャンセル",
"confirm": "確認",
"description": "説明",
"name": "名前"
"addTitle": "クライアントを追加",
"descriptions": {
"description": "詳細なクライアント説明",
"downloadLink": "プラットフォームダウンロードURL",
"icon": "アイコンのURLまたはbase64エンコーディング",
"name": "クライアントの表示名",
"outputFormat": "サブスクリプション設定ファイル形式",
"scheme": {
"base64Encoding": "Base64エンコーディング",
"functions": "サポートされている関数:",
"jsonStringify": "JSONオブジェクトを文字列に",
"nameVariable": "サイト名",
"title": "URLスキームテンプレート",
"urlEncoding": "URLエンコーディング",
"urlVariable": "サブスクリプションURL",
"variables": "サポートされている変数:"
},
"template": {
"description": "Goテンプレート構文を使用してサブスクリプション設定ファイルを生成します",
"functions": "テンプレート関数:",
"if": "条件文",
"nodes": "プロキシノードリスト",
"range": "配列を反復処理",
"siteName": "サイト名",
"sprig": "Sprig関数ライブラリ(文字列処理、日付など)",
"subscribeName": "サブスクリプション名",
"title": "Goテンプレート構文",
"userInfo": "ユーザー情報(トラフィック、有効期限など)",
"variables": "利用可能な変数:"
},
"userAgentPrefix": "異なるクライアントを区別するためのクライアント識別子"
},
"name": "名前",
"title": "購読グループ一覧",
"updateSuccess": "更新成功",
"updatedAt": "更新日時"
"editTitle": "クライアントを編集",
"fields": {
"description": "説明",
"icon": "アイコン",
"name": "名前",
"outputFormat": "出力形式",
"scheme": "URLスキーム",
"template": "サブスクリプションファイルテンプレート"
},
"tabs": {
"basic": "基本情報",
"download": "ダウンロード",
"template": "テンプレート"
},
"validation": {
"nameRequired": "クライアント名は必須です",
"userAgentRequiredSuffix": "は必須です"
}
},
"inventory": "サブスクリプションの制限",
"name": "名前",
"quota": "購入制限/回",
"replacement": "リセット価格/回",
"sell": "販売",
"show": "表示",
"sold": "サブスクリプション数",
"subscribe": "購読",
"subscribeGroup": "グループを購読する",
"tabs": {
"subscribe": "購読",
"subscribeApp": "アプリ設定",
"subscribeConfig": "サブスクリプション設定",
"subscribeGroup": "購読グループ"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "プレーンテキスト",
"yaml": "YAML"
},
"traffic": "トラフィック",
"unitPrice": "単価",
"updateSuccess": "更新が成功しました"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "クライアント管理"
},
"table": {
"columns": {
"default": "デフォルト",
"description": "説明",
"name": "クライアント名",
"outputFormat": "出力形式",
"supportedPlatforms": "サポートされているプラットフォーム"
}
},
"templatePreview": {
"base64": {
"decodeError": "デコードに失敗しました:コンテンツが有効なBase64形式ではありません",
"decodedContent": "デコードされたコンテンツ",
"originalContent": "オリジナルコンテンツ(Base64"
},
"failed": "プレビューに失敗しました",
"loading": "読み込み中...",
"preview": "プレビュー",
"title": "テンプレートプレビュー"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "日",
"defaultSubscribe": "デフォルトサブスクリプション",
"defaultSubscribeDescription": "新規ユーザーのデフォルトサブスクリプションプラン",
"description": "ユーザー登録に関連する設定を構成します",
"enableTrial": "トライアルを有効にする",
"enableTrialDescription": "有効にすると、新しいユーザーは登録時にトライアルサブスクリプションを受け取ります",
"hour": "時間",
"inputPlaceholder": "入力してください",
"ipRegistrationLimit": "IP登録制限",
"ipRegistrationLimitDescription": "単一のIPアドレスからの登録数を制限します",
"minute": "分",
"month": "月",
"none": "なし",
"registrationLimitCount": "登録制限数",
"registrationLimitCountDescription": "制限期間内に許可される登録数",
"registrationLimitExpire": "制限期間",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "新規ユーザー登録を停止",
"stopNewUserRegistrationDescription": "有効にすると、新規ユーザー登録が無効になります",
"title": "登録設定",
"trialDay": "トライアル日数",
"trialDayDescription": "新規ユーザー登録時に受け取るトライアル日数",
"trialFlow": "トライアルトラフィック",
"trialFlowDescription": "新規ユーザーが登録時に受け取るトライアルトラフィック"
"trialConfig": "トライアル設定",
"trialConfigDescription": "新規ユーザー登録時にトライアルサブスクリプション、期間、および時間単位を設定します",
"year": "年"
},
"site": {
"customData": "カスタムデータ",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "추가",
"additionalRecipientEmails": "추가 수신자 이메일",
"additionalRecipients": "추가 수신자",
"additionalRecipientsDescription": "이 이메일은 위의 사용자 필터 외에 방송을 수신합니다.",
"allUsers": "모든 사용자",
"broadcastList": "방송 목록",
"broadcastLogs": "방송 로그",
"cancel": "취소",
"cannotBeEmpty": "비어 있을 수 없습니다",
"completed": "완료",
"confirm": "확인",
"confirmDelete": "삭제 확인",
"content": "이메일 내용",
"create": "생성",
"createBroadcast": "방송 생성",
"createNewEmailBroadcastCampaign": "새 이메일 방송 캠페인 생성",
"createSuccess": "성공적으로 생성됨",
"createdAt": "생성일",
"dailyLimit": "일일 한도는 최소 1 이상이어야 합니다",
"dailySendLimit": "일일 발송 한도",
"delete": "삭제",
"deleteDescription": "이 작업은 취소할 수 없습니다. 정말로 삭제하시겠습니까?",
"deleteSuccess": "성공적으로 삭제됨",
"edit": "편집",
"emailAddedToScheduledQueue": "이메일이 예약 발송 대기열에 추가됨",
"emailBroadcast": "이메일 방송",
"emailBroadcastTaskCreatedSuccessfully": "이메일 방송 작업이 성공적으로 생성됨",
"emailBroadcastTasks": "이메일 방송 작업",
"emailContent": "이메일 내용",
"emailInterval": "이메일 간격 (초)",
"emailIntervalMinimum": "이메일 간격은 최소 0.1초 이상이어야 합니다",
"emailMarketing": "이메일 마케팅",
"emailTaskManager": "이메일 작업 관리자",
"errorMessage": "오류 메시지",
"estimatedRecipients": "예상 수신자",
"expiredSubscriptionUsersOnly": "만료된 구독 사용자만",
"expiredUsers": "만료된 사용자",
"failCount": "실패 수",
"failed": "실패",
"failedToRefreshTaskStatus": "작업 상태를 새로 고치는 데 실패했습니다",
"failedToStopTask": "작업 중지에 실패했습니다",
"inProgress": "진행 중",
"includeUsersRegisteredAfter": "이 날짜 이후에 등록된 사용자 포함",
"includeUsersRegisteredBefore": "이 날짜 이전에 등록된 사용자 포함",
"intervalTimeBetweenEmails": "각 이메일 간의 간격 시간",
"leaveEmptyForImmediateSend": "즉시 발송을 위해 비워 두세요",
"logList": "로그 목록",
"marketingManagement": "마케팅 관리",
"maximumNumberPerDay": "하루에 보낼 수 있는 최대 이메일 수",
"noSubscriptionUsersOnly": "구독 없는 사용자만",
"nonSubscribers": "비구독자",
"notStarted": "시작되지 않음",
"onePerLine": "한 줄에 하나",
"only": "오직",
"pending": "대기 중",
"pleaseEnter": "입력해 주세요",
"pleaseEnterValidEmailAddresses": "유효한 이메일 주소를 입력해 주세요, 한 줄에 하나씩",
"processing": "처리 중...",
"progress": "진행 상황",
"recipient": "수신자",
"recipientEmail": "수신자 이메일",
"recipientType": "수신자 유형",
"registrationEndDate": "등록 종료 날짜",
"registrationStartDate": "등록 시작 날짜",
"scheduleSend": "예약 발송",
"scheduledSend": "예약 발송",
"scheduledSendTimeMustBeLater": "예약 발송 시간은 현재 시간 이후여야 합니다",
"selectSendScope": "발송 범위 선택",
"selectSendTime": "발송 시간 선택, 즉시 발송을 위해 비워 두세요",
"sendFailed": "발송 실패, 다시 시도해 주세요",
"sendNow": "지금 발송",
"sendScope": "발송 범위",
"sendScopeDescription": "이메일 발송을 위한 사용자 범위를 선택하세요. 아래에 입력된 이메일 주소로만 발송하려면 '추가 이메일만'을 선택하세요.",
"sendSettings": "발송 설정",
"sendTime": "발송 시간",
"sending": "발송 중",
"sentAt": "발송일",
"specificUsers": "특정 사용자",
"specificUsersOnly": "추가 이메일만 (플랫폼 사용자 제외)",
"status": "상태",
"stop": "중지",
"stopped": "중지됨",
"subject": "이메일 제목",
"subscribedUsers": "구독한 사용자",
"subscribedUsersOnly": "구독한 사용자만",
"successCount": "성공 수",
"taskStatusRefreshed": "작업 상태가 새로 고쳐졌습니다",
"taskStoppedSuccessfully": "작업이 성공적으로 중지되었습니다",
"totalSent": "총 발송 수",
"updateSuccess": "성공적으로 업데이트됨",
"useMarkdownEditor": "미리보기 기능이 있는 Markdown 편집기를 사용하여 이메일 내용을 작성하세요",
"users": "사용자",
"view": "보기",
"viewAndManageEmailBroadcastTasks": "이메일 방송 작업 보기 및 관리",
"viewContent": "내용 보기"
}
+5 -11
View File
@@ -1,32 +1,26 @@
{
"ADS Config": "ADS 구성",
"Announcement Management": "공지 관리",
"Apple": "Apple ID",
"Application Management": "애플리케이션 관리",
"Auth Control": "인증 제어",
"Coupon Management": "쿠폰 관리",
"Dashboard": "대시보드",
"Device": "장치",
"Document Management": "문서 관리",
"Email": "이메일",
"Facebook": "Facebook",
"Finance": "재무",
"General": "일반",
"GitHub": "GitHub",
"Google": "Google",
"Marketing Management": "마케팅 관리",
"Order Management": "주문 관리",
"Payment Config": "결제 구성",
"Phone Number": "전화번호",
"Product Management": "제품 관리",
"Protocol Management": "프로토콜 관리",
"Rule Management": "규칙 관리",
"Server": "서버",
"Server Management": "서버 관리",
"Settings": "설정",
"Subscribe Management": "구독 관리",
"Subscribe Config": "구독 설정",
"System Config": "시스템 구성",
"System Management": "시스템 관리",
"System Tool": "시스템 도구",
"Telegram": "텔레그램",
"Ticket Management": "티켓 관리",
"Twitter": "트위터",
"User": "사용자",
"User Detail": "사용자 세부 정보",
"User Management": "사용자 관리"
+160
View File
@@ -0,0 +1,160 @@
{
"actions": "작업",
"app": {
"appDownloadURL": "앱 다운로드 URL",
"appIcon": "앱 아이콘",
"appList": "앱 목록",
"appName": "앱 이름",
"backupDomains": "백업 도메인 목록",
"backupDomainsDescription": "도메인 해석을 위한 백업 도메인 목록, 한 줄에 하나의 도메인",
"batchDelete": "일괄 삭제",
"cancel": "취소",
"communicationKey": "통신 키",
"communicationKeyDescription": "클라이언트 통신에 사용되는 키",
"config": "설정",
"configApp": "앱 설정",
"confirm": "확인",
"confirmDelete": "삭제 확인",
"create": "생성",
"createApp": "앱 생성",
"createSuccess": "성공적으로 생성되었습니다",
"defaultVersion": "기본",
"delete": "삭제",
"deleteWarning": "이 작업은 되돌릴 수 없습니다",
"describeDescription": "애플리케이션을 설명하는 데 사용되며, 앱 목록에 표시됩니다",
"description": "설명",
"downloadLink": "다운로드 링크",
"edit": "편집",
"editApp": "앱 편집",
"encryption": "암호화 방법",
"encryptionDescription": "클라이언트 통신을 위한 암호화 방법을 선택하세요. 선택하면 클라이언트는 이 방법을 사용하여 서버와 통신합니다.",
"nameDescription": "애플리케이션 이름, 앱 목록에 표시됩니다",
"platform": "플랫폼",
"selectApp": "앱 선택",
"selectAppDescription": "구성할 앱을 선택하세요. 모든 설정은 선택한 앱에 적용됩니다.",
"startupPicture": "시작 화면",
"startupPictureDescription": "시작 화면, 네트워크 및 로컬 이미지를 지원합니다. 네트워크 이미지를 사용할 경우, 전체 이미지 URL을 입력하세요",
"startupPicturePreview": "시작 화면 미리보기",
"startupPictureSkip": "시작 화면 건너뛰기 시간",
"startupPictureSkipDescription": "시작 화면 표시 시간(초), 0을 입력하면 표시되지 않습니다",
"subscriptionProtocol": "구독 프로토콜",
"updateSuccess": "성공적으로 업데이트되었습니다",
"version": "버전"
},
"cancel": "취소",
"config": {
"singleSubscriptionMode": "단일 구독 모드",
"subscriptionDomain": "구독 도메인",
"subscriptionDomainDescription": "구독에 사용됩니다; 사이트 도메인을 사용하려면 비워 두세요",
"subscriptionDomainPlaceholder": "구독 도메인을 입력하세요, 한 줄에 하나씩",
"subscriptionPath": "구독 경로",
"subscriptionPathDescription": "구독에 사용됩니다; 최적의 성능을 위해 수정 후 시스템을 재시작하세요",
"subscriptionPathPlaceholder": "입력하세요",
"updateSuccess": "성공적으로 업데이트되었습니다",
"wildcardResolution": "와일드카드 해상도",
"wildcardResolutionDescription": "구독에 사용됩니다"
},
"confirm": "확인",
"confirmDelete": "삭제하시겠습니까?",
"copy": "복사",
"copySuccess": "성공적으로 복사되었습니다",
"create": "생성",
"createSubscribe": "새 구독 생성",
"createSuccess": "생성 성공",
"delete": "삭제",
"deleteSuccess": "삭제 성공",
"deleteWarning": "삭제 후 데이터는 복구할 수 없으니 신중하게 진행하세요.",
"deviceLimit": "장치 수/대",
"edit": "편집",
"editSubscribe": "구독 편집",
"form": {
"Day": "일",
"Hour": "시",
"Minute": "분",
"Month": "월",
"NoLimit": "제한 없음",
"Year": "년",
"annualReset": "연간 초기화",
"basic": "기본",
"cancel": "취소",
"confirm": "확인",
"deductionRatio": "자동/수동 공제 설정",
"deductionRatioDescription": "공제에 사용됩니다. 기본적으로 시스템은 자동 계산 알고리즘을 채택합니다. 수동 비율이 제공되면 시스템은 시간 및 트래픽 비율에 따라 비율을 계산하여 총합이 100%가 되도록 합니다.",
"description": "설명",
"deviceLimit": "기기 제한",
"discount": "할인",
"discountDescription": "단가 기준으로 할인 설정",
"discountMonths": "개월",
"discountPercent": "할인율",
"discount_price": "할인가",
"duration": "기간 (개월)",
"groupId": "구독 그룹",
"inventory": "구독 한도",
"monthlyReset": "월별 초기화",
"name": "이름",
"noLimit": "무제한",
"noReset": "초기화 없음",
"pricing": "가격",
"purchaseWithDiscount": "공제 허용",
"purchaseWithDiscountDescription": "구독 취소 기능을 활성화하거나 비활성화합니다. 활성화 후, 시스템은 설정된 규칙과 비율에 따라 공제 처리를 수행하며, 남은 가치는 잔액으로 반환됩니다.",
"quota": "구매 한도",
"renewalReset": "갱신 초기화",
"renewalResetDescription": "갱신 시 초기화 주기",
"replacement": "재설정 가격 (매회)",
"resetCycle": "초기화 주기",
"resetOn1st": "매월 1일 초기화",
"selectResetCycle": "초기화 주기를 선택하세요",
"selectSubscribeGroup": "구독 그룹을 선택하세요",
"selectUnitTime": "단위 시간을 선택하세요",
"server": "서버",
"serverGroup": "서버 그룹",
"servers": "서버",
"speedLimit": "속도 제한 ",
"traffic": "트래픽",
"unitPrice": "단가",
"unitTime": "단위 시간"
},
"group": {
"actions": "작업",
"cancel": "취소",
"confirm": "확인",
"confirmDelete": "삭제하시겠습니까?",
"create": "생성",
"createSubscribeGroup": "새 구독 그룹 생성",
"createSuccess": "생성 성공",
"delete": "삭제",
"deleteSuccess": "삭제 성공",
"deleteWarning": "삭제 후 데이터는 복구할 수 없습니다. 신중하게 진행하세요.",
"description": "설명",
"edit": "편집",
"editSubscribeGroup": "구독 그룹 편집",
"form": {
"cancel": "취소",
"confirm": "확인",
"description": "설명",
"name": "이름"
},
"name": "이름",
"title": "구독 그룹 목록",
"updateSuccess": "업데이트 성공",
"updatedAt": "업데이트 시간"
},
"inventory": "구독 한도",
"name": "이름",
"quota": "구매 제한/회",
"replacement": "가격 재설정/회",
"sell": "판매",
"show": "표시",
"sold": "구독 수",
"subscribe": "구독",
"subscribeGroup": "구독 그룹",
"tabs": {
"subscribe": "구독",
"subscribeApp": "앱 구성",
"subscribeConfig": "구독 구성",
"subscribeGroup": "구독 그룹"
},
"traffic": "트래픽",
"unitPrice": "단가",
"updateSuccess": "업데이트 성공"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"type": "유형",
"updateSuccess": "업데이트 성공",
"updatedAt": "업데이트 시간",
"userAccount": "사용자 계정",
"user": "사용자",
"userDetail": "사용자 상세 정보",
"userId": "사용자 ID"
},
+111 -140
View File
@@ -1,161 +1,132 @@
{
"actions": "작업",
"app": {
"appDownloadURL": "앱 다운로드 URL",
"appIcon": "앱 아이콘",
"appList": "앱 목록",
"appName": "앱 이름",
"backupDomains": "백업 도메인 목록",
"backupDomainsDescription": "도메인 해석을 위한 백업 도메인 목록, 한 줄에 하나의 도메인",
"actions": {
"add": "추가",
"batchDelete": "일괄 삭제",
"batchDeleteSuccess": "{count}명의 클라이언트를 성공적으로 삭제했습니다",
"batchDeleteWarning": "선택한 {count}명의 클라이언트를 삭제하시겠습니까?",
"cancel": "취소",
"communicationKey": "통신 키",
"communicationKeyDescription": "클라이언트 통신에 사용되는 키",
"config": "설정",
"configApp": "앱 설정",
"confirm": "확인",
"confirmDelete": "삭제 확인",
"create": "생성",
"createApp": "앱 생성",
"createSuccess": "성공적으로 생성되었습니다",
"defaultVersion": "기본",
"delete": "삭제",
"deleteWarning": "이 작업은 되돌릴 수 없습니다",
"describeDescription": "애플리케이션을 설명하는 데 사용되며, 앱 목록에 표시됩니다",
"description": "설명",
"downloadLink": "다운로드 링크",
"deleteFailed": "삭제 실패",
"deleteSuccess": "성공적으로 삭제되었습니다",
"deleteWarning": "이 작업은 취소할 수 없습니다. 이 클라이언트를 삭제하시겠습니까?",
"edit": "편집",
"editApp": "앱 편집",
"encryption": "암호화 방법",
"encryptionDescription": "클라이언트 통신을 위한 암호화 방법을 선택하세요. 선택하면 클라이언트는 이 방법을 사용하여 서버와 통신합니다.",
"nameDescription": "애플리케이션 이름, 앱 목록에 표시됩니다",
"platform": "플랫폼",
"selectApp": "앱 선택",
"selectAppDescription": "구성할 앱을 선택하세요. 모든 설정은 선택한 앱에 적용됩니다.",
"startupPicture": "시작 화면",
"startupPictureDescription": "시작 화면, 네트워크 및 로컬 이미지를 지원합니다. 네트워크 이미지를 사용할 경우, 전체 이미지 URL을 입력하세요",
"startupPicturePreview": "시작 화면 미리보기",
"startupPictureSkip": "시작 화면 건너뛰기 시간",
"startupPictureSkipDescription": "시작 화면 표시 시간(초), 0을 입력하면 표시되지 않습니다",
"subscriptionProtocol": "구독 프로토콜",
"updateSuccess": "성공적으로 업데이트되었습니다",
"version": "버전"
"save": "저장",
"saveFailed": "저장 실패",
"update": "업데이트",
"updateSuccess": "성공적으로 업데이트되었습니다"
},
"cancel": "취소",
"config": {
"description": "구독 시스템 설정 관리",
"singleSubscriptionMode": "단일 구독 모드",
"singleSubscriptionModeDescription": "활성화되면 모든 사용자 구독이 잔액으로 전환됩니다",
"singleSubscriptionModeDescription": "사용자를 하나의 활성 구독으로 제한합니다. 기존 구독에는 영향을 미치지 않습니다",
"subscriptionDomain": "구독 도메인",
"subscriptionDomainDescription": "구독에 사용됩니다; 사이트 도메인을 사용하려면 비워 두세요",
"subscriptionDomainDescription": "구독 링크를 위한 사용자 정의 도메인",
"subscriptionDomainPlaceholder": "구독 도메인을 입력하세요, 한 줄에 하나씩",
"subscriptionPath": "구독 경로",
"subscriptionPathDescription": "구독에 사용됩니다; 최적의 성능을 위해 수정 후 시스템 재시작하세요",
"subscriptionPathPlaceholder": "입력하세요",
"updateSuccess": "성공적으로 업데이트되었습니다",
"subscriptionPathDescription": "구독 엔드포인트를 위한 사용자 정의 경로 (시스템 재시작 후 성능 향상)",
"subscriptionPathPlaceholder": "구독 경로를 입력하세요",
"title": "구독 설정",
"updateError": "업데이트 실패",
"updateSuccess": "설정이 성공적으로 업데이트되었습니다",
"userAgentLimit": "{userAgent} 제한",
"userAgentLimitDescription": "{userAgent}에 기반한 접근 제한을 활성화합니다",
"userAgentList": "{userAgent} 허용 목록",
"userAgentListDescription": "구독 접근을 위한 허용된 {userAgent}, 한 줄에 하나씩. 구성된 애플리케이션 {userAgent}는 자동으로 포함됩니다",
"userAgentListPlaceholder": "허용된 {userAgent}를 입력하세요, 한 줄에 하나씩",
"wildcardResolution": "와일드카드 해상도",
"wildcardResolutionDescription": "구독에 사용됩니다"
"wildcardResolutionDescription": "구독을 위한 와일드카드 도메인 해상도를 활성화합니다"
},
"confirm": "확인",
"confirmDelete": "삭제하시겠습니까?",
"copy": "복사",
"copySuccess": "성공적으로 복사되었습니다",
"create": "생성",
"createSubscribe": "새 구독 생성",
"createSuccess": "생성 성공",
"delete": "삭제",
"deleteSuccess": "삭제 성공",
"deleteWarning": "삭제 후 데이터는 복구할 수 없으니 신중하게 진행하세요.",
"deviceLimit": "장치 수/대",
"edit": "편집",
"editSubscribe": "구독 편집",
"form": {
"Day": "일",
"Hour": "시",
"Minute": "분",
"Month": "월",
"NoLimit": "제한 없음",
"Year": "년",
"annualReset": "연간 초기화",
"basic": "기본",
"cancel": "취소",
"confirm": "확인",
"deductionRatio": "자동/수동 공제 설정",
"deductionRatioDescription": "공제에 사용됩니다. 기본적으로 시스템은 자동 계산 알고리즘을 채택합니다. 수동 비율이 제공되면 시스템은 시간 및 트래픽 비율에 따라 비율을 계산하여 총합이 100%가 되도록 합니다.",
"description": "설명",
"deviceLimit": "기기 제한",
"discount": "할인",
"discountDescription": "단가 기준으로 할인 설정",
"discountMonths": "개월",
"discountPercent": "할인율",
"discount_price": "할인가",
"duration": "기간 (개월)",
"groupId": "구독 그룹",
"inventory": "구독 한도",
"monthlyReset": "월별 초기화",
"name": "이름",
"noLimit": "무제한",
"noReset": "초기화 없음",
"pricing": "가격",
"purchaseWithDiscount": "공제 허용",
"purchaseWithDiscountDescription": "구독 취소 기능을 활성화하거나 비활성화합니다. 활성화 후, 시스템은 설정된 규칙과 비율에 따라 공제 처리를 수행하며, 남은 가치는 잔액으로 반환됩니다.",
"quota": "구매 한도",
"renewalReset": "갱신 초기화",
"renewalResetDescription": "갱신 시 초기화 주기",
"replacement": "재설정 가격 (매회)",
"resetCycle": "초기화 주기",
"resetOn1st": "매월 1일 초기화",
"selectResetCycle": "초기화 주기를 선택하세요",
"selectSubscribeGroup": "구독 그룹을 선택하세요",
"selectUnitTime": "단위 시간을 선택하세요",
"server": "서버",
"serverGroup": "서버 그룹",
"servers": "서버",
"speedLimit": "속도 제한 ",
"traffic": "트래픽",
"unitPrice": "단가",
"unitTime": "단위 시간"
},
"group": {
"actions": "작업",
"cancel": "취소",
"confirm": "확인",
"confirmDelete": "삭제하시겠습니까?",
"create": "생성",
"createSubscribeGroup": "새 구독 그룹 생성",
"createSuccess": "생성 성공",
"delete": "삭제",
"deleteSuccess": "삭제 성공",
"deleteWarning": "삭제 후 데이터는 복구할 수 없습니다. 신중하게 진행하세요.",
"description": "설명",
"edit": "편집",
"editSubscribeGroup": "구독 그룹 편집",
"form": {
"cancel": "취소",
"confirm": "확인",
"description": "설명",
"name": "이름"
"addTitle": "클라이언트 추가",
"descriptions": {
"description": "상세 클라이언트 설명",
"downloadLink": "플랫폼 다운로드 URL",
"icon": "아이콘 URL 또는 base64 인코딩",
"name": "클라이언트 표시 이름",
"outputFormat": "구독 구성 파일 형식",
"scheme": {
"base64Encoding": "Base64 인코딩",
"functions": "기능을 지원합니다:",
"jsonStringify": "JSON 객체를 문자열로 변환",
"nameVariable": "사이트 이름",
"title": "URL 스킴 템플릿",
"urlEncoding": "URL 인코딩",
"urlVariable": "구독 URL",
"variables": "변수를 지원합니다:"
},
"template": {
"description": "구독 구성 파일 생성을 위한 Go 템플릿 구문 사용",
"functions": "템플릿 함수:",
"if": "조건문",
"nodes": "프록시 노드 목록",
"range": "배열 반복",
"siteName": "사이트 이름",
"sprig": "Sprig 함수 라이브러리 (문자열 처리, 날짜 등)",
"subscribeName": "구독 이름",
"title": "Go 템플릿 구문",
"userInfo": "사용자 정보 (트래픽, 만료 등)",
"variables": "사용 가능한 변수:"
},
"userAgentPrefix": "다양한 클라이언트를 구별하기 위한 클라이언트 식별자"
},
"name": "이름",
"title": "구독 그룹 목록",
"updateSuccess": "업데이트 성공",
"updatedAt": "업데이트 시간"
"editTitle": "클라이언트 편집",
"fields": {
"description": "설명",
"icon": "아이콘",
"name": "이름",
"outputFormat": "출력 형식",
"scheme": "URL 스킴",
"template": "구독 파일 템플릿"
},
"tabs": {
"basic": "기본 정보",
"download": "다운로드",
"template": "템플릿"
},
"validation": {
"nameRequired": "클라이언트 이름은 필수입니다",
"userAgentRequiredSuffix": "필수입니다"
}
},
"inventory": "구독 한도",
"name": "이름",
"quota": "구매 제한/회",
"replacement": "가격 재설정/회",
"sell": "판매",
"show": "표시",
"sold": "구독 수",
"subscribe": "구독",
"subscribeGroup": "구독 그룹",
"tabs": {
"subscribe": "구독",
"subscribeApp": "앱 구성",
"subscribeConfig": "구독 구성",
"subscribeGroup": "구독 그룹"
"outputFormats": {
"base64": "Base64",
"conf": "CONF",
"json": "JSON",
"plain": "일반 텍스트",
"yaml": "YAML"
},
"traffic": "트래픽",
"unitPrice": "단가",
"updateSuccess": "업데이트 성공"
"platforms": {
"android": "Android",
"harmony": "HarmonyOS",
"ios": "iOS",
"linux": "Linux",
"mac": "macOS",
"windows": "Windows"
},
"protocol": {
"title": "클라이언트 관리"
},
"table": {
"columns": {
"default": "기본",
"description": "설명",
"name": "클라이언트 이름",
"outputFormat": "출력 형식",
"supportedPlatforms": "지원되는 플랫폼"
}
},
"templatePreview": {
"base64": {
"decodeError": "디코드 실패: 콘텐츠가 유효한 Base64 형식이 아닙니다",
"decodedContent": "디코딩된 콘텐츠",
"originalContent": "원본 콘텐츠 (Base64)"
},
"failed": "미리보기가 실패했습니다",
"loading": "로딩 중...",
"preview": "미리보기",
"title": "템플릿 미리보기"
}
}
+9 -6
View File
@@ -39,12 +39,16 @@
},
"register": {
"day": "일",
"defaultSubscribe": "기본 구독",
"defaultSubscribeDescription": "신규 사용자를 위한 기본 구독 계획",
"description": "사용자 등록 관련 설정 구성",
"enableTrial": "체험판 활성화",
"enableTrialDescription": "활성화하면 신규 사용자가 등록 시 체험 구독을 받게 됩니다.",
"hour": "시간",
"inputPlaceholder": "입력해 주세요",
"ipRegistrationLimit": "IP 등록 제한",
"ipRegistrationLimitDescription": "단일 IP 주소에서의 등록 수 제한",
"minute": "분",
"month": "개월",
"none": "없음",
"registrationLimitCount": "등록 제한 수",
"registrationLimitCountDescription": "제한 기간 내 허용되는 등록 수",
"registrationLimitExpire": "제한 기간",
@@ -55,10 +59,9 @@
"stopNewUserRegistration": "신규 사용자 등록 중지",
"stopNewUserRegistrationDescription": "활성화 시, 신규 사용자 등록이 비활성화됩니다.",
"title": "등록 설정",
"trialDay": "체험 일수",
"trialDayDescription": "신규 사용자 등록 시 제공되는 체험 일수",
"trialFlow": "체험 트래픽",
"trialFlowDescription": "신규 사용자 등록 시 제공되는 체험 트래픽"
"trialConfig": "체험 구성",
"trialConfigDescription": "등록 시 신규 사용자를 위한 체험 구독, 기간 및 시간 단위를 설정합니다.",
"year": "년"
},
"site": {
"customData": "사용자 정의 데이터",
+97
View File
@@ -0,0 +1,97 @@
{
"additional": "Tillegg",
"additionalRecipientEmails": "Ytterligere mottaker-e-poster",
"additionalRecipients": "Ytterligere mottakere",
"additionalRecipientsDescription": "Disse e-postene vil motta sendingen i tillegg til brukerfilteret ovenfor",
"allUsers": "Alle brukere",
"broadcastList": "Sende liste",
"broadcastLogs": "Sende logger",
"cancel": "Avbryt",
"cannotBeEmpty": "kan ikke være tom",
"completed": "Fullført",
"confirm": "Bekreft",
"confirmDelete": "Bekreft sletting",
"content": "E-postinnhold",
"create": "Opprett",
"createBroadcast": "Opprett sending",
"createNewEmailBroadcastCampaign": "Opprett ny e-postsending kampanje",
"createSuccess": "Opprettet med suksess",
"createdAt": "Opprettet den",
"dailyLimit": "Daglig grense må være minst 1",
"dailySendLimit": "Daglig sendingsgrense",
"delete": "Slett",
"deleteDescription": "Denne operasjonen kan ikke angres. Er du sikker på at du vil slette?",
"deleteSuccess": "Slettet med suksess",
"edit": "Rediger",
"emailAddedToScheduledQueue": "E-post lagt til i planlagt sendekø",
"emailBroadcast": "E-postsending",
"emailBroadcastTaskCreatedSuccessfully": "E-postsending oppgave opprettet med suksess",
"emailBroadcastTasks": "E-postsending oppgaver",
"emailContent": "E-postinnhold",
"emailInterval": "E-postintervall (sekunder)",
"emailIntervalMinimum": "E-postintervall må være minst 0,1 sekunder",
"emailMarketing": "E-postmarkedsføring",
"emailTaskManager": "E-postoppgavebehandler",
"errorMessage": "Feilmelding",
"estimatedRecipients": "Estimert antall mottakere",
"expiredSubscriptionUsersOnly": "Kun brukere med utløpt abonnement",
"expiredUsers": "Utløpte brukere",
"failCount": "Feilantall",
"failed": "Feilet",
"failedToRefreshTaskStatus": "Feilet å oppdatere oppgave-status",
"failedToStopTask": "Feilet å stoppe oppgave",
"inProgress": "Pågår",
"includeUsersRegisteredAfter": "Inkluder brukere registrert på eller etter denne datoen",
"includeUsersRegisteredBefore": "Inkluder brukere registrert på eller før denne datoen",
"intervalTimeBetweenEmails": "Intervall tid mellom hver e-post",
"leaveEmptyForImmediateSend": "La stå tomt for umiddelbar sending",
"logList": "Loggliste",
"marketingManagement": "Markedsføringsledelse",
"maximumNumberPerDay": "Maksimalt antall e-poster som kan sendes per dag",
"noSubscriptionUsersOnly": "Kun brukere uten abonnement",
"nonSubscribers": "Ikke-abonnenter",
"notStarted": "Ikke startet",
"onePerLine": "en per linje",
"only": "kun",
"pending": "Venter",
"pleaseEnter": "Vennligst skriv inn",
"pleaseEnterValidEmailAddresses": "Vennligst skriv inn gyldige e-postadresser, en per linje",
"processing": "Behandler...",
"progress": "Fremdrift",
"recipient": "Mottaker",
"recipientEmail": "Mottakerens e-post",
"recipientType": "Mottakertype",
"registrationEndDate": "Registreringssluttdato",
"registrationStartDate": "Registreringsstartdato",
"scheduleSend": "Planlegg sending",
"scheduledSend": "Planlagt sending",
"scheduledSendTimeMustBeLater": "Planlagt sendetid må være senere enn nåværende tid",
"selectSendScope": "Velg sendingsomfang",
"selectSendTime": "Velg sendetid, la stå tomt for umiddelbar sending",
"sendFailed": "Sending feilet, vennligst prøv igjen",
"sendNow": "Send nå",
"sendScope": "Sendingsomfang",
"sendScopeDescription": "Velg brukeromfang for e-postsending. Velg \"Kun ytterligere e-poster\" for å sende kun til e-postadressene fylt ut nedenfor",
"sendSettings": "Sendingsinnstillinger",
"sendTime": "Sendetid",
"sending": "Sender",
"sentAt": "Sendt den",
"specificUsers": "Spesifikke brukere",
"specificUsersOnly": "Kun ytterligere e-poster (hopp over plattformbrukere)",
"status": "Status",
"stop": "Stopp",
"stopped": "Stoppet",
"subject": "E-postemne",
"subscribedUsers": "Abonnerte brukere",
"subscribedUsersOnly": "Kun abonnenter",
"successCount": "Suksessantall",
"taskStatusRefreshed": "Oppgave-status oppdatert",
"taskStoppedSuccessfully": "Oppgave stoppet med suksess",
"totalSent": "Totalt sendt",
"updateSuccess": "Oppdatert med suksess",
"useMarkdownEditor": "Bruk Markdown-editor for å skrive e-postinnhold med forhåndsvisningsfunksjonalitet",
"users": "brukere",
"view": "Vis",
"viewAndManageEmailBroadcastTasks": "Vis og administrer e-postsending oppgaver",
"viewContent": "Vis innhold"
}

Some files were not shown because too many files have changed in this diff Show More