Compare commits

..

40 Commits

Author SHA1 Message Date
semantic-release-bot f275f01f25 🔖 chore(release): v1.0.0-beta.5 [skip ci]
# [1.0.0-beta.5](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2025-01-09)

###  Features

* **locales**: Replace 'nodeGroupId' with 'groupId' in multiple language files for consistency ([a4e9d5d](https://github.com/perfect-panel/ppanel-web/commit/a4e9d5d))
* **locales**: Update 'deductBalance' to 'giftAmount' across multiple languages and fix newline in announcement.json ([70497af](https://github.com/perfect-panel/ppanel-web/commit/70497af))
* **stats**: Replace dynamic stat fetching with environment constants for user, server, and location counts ([46ae166](https://github.com/perfect-panel/ppanel-web/commit/46ae166))
* **subscribe**: Update suffix from 'MB' to 'Mbps' and enhance speed limit display logic ([3547bb1](https://github.com/perfect-panel/ppanel-web/commit/3547bb1))
* **user**: Add 'gift_amount' field and update related references in user services and components ([b13c77e](https://github.com/perfect-panel/ppanel-web/commit/b13c77e))

### 🎫 Chores

* **deps**: Update package dependencies across multiple projects for improved stability and performance ([b01a5bc](https://github.com/perfect-panel/ppanel-web/commit/b01a5bc))
* **ui**: Update package dependencies for improved stability and performance ([25da429](https://github.com/perfect-panel/ppanel-web/commit/25da429))

### 🐛 Bug Fixes

* **api**: Replace 'deduction' with 'gift_amount' and add 'commission' field in type definitions ([77edf1d](https://github.com/perfect-panel/ppanel-web/commit/77edf1d))
* **api**: Update API type definitions to replace 'deduction' with 'gift_amount' and make 'commission' field optional ([c2af060](https://github.com/perfect-panel/ppanel-web/commit/c2af060))
* **auth**: Refactor user authentication forms to remove global store dependency and improve type handling ([12026b0](https://github.com/perfect-panel/ppanel-web/commit/12026b0))
* **coupon**: Rename 'server' field to 'subscribe' in coupon form and update coupon update request type ([f8b6d82](https://github.com/perfect-panel/ppanel-web/commit/f8b6d82))
* **types**: Add 'gift_amount' field to API type definitions ([8f8a12a](https://github.com/perfect-panel/ppanel-web/commit/8f8a12a))
* **user**: Add the 'gift_amount' field to the user service's type definition ([6301409](https://github.com/perfect-panel/ppanel-web/commit/6301409))
2025-01-09 14:42:36 +00:00
web@ppanel c2af06052c 🐛 fix(api): Update API type definitions to replace 'deduction' with 'gift_amount' and make 'commission' field optional 2025-01-09 21:40:02 +07:00
web@ppanel 8f8a12a510 🐛 fix(types): Add 'gift_amount' field to API type definitions 2025-01-09 21:31:25 +07:00
web@ppanel 77edf1d6ec 🐛 fix(api): Replace 'deduction' with 'gift_amount' and add 'commission' field in type definitions 2025-01-09 21:25:21 +07:00
web@ppanel f8b6d82780 🐛 fix(coupon): Rename 'server' field to 'subscribe' in coupon form and update coupon update request type 2025-01-09 20:25:34 +07:00
web@ppanel b01a5bc83b 🔧 chore(deps): Update package dependencies across multiple projects for improved stability and performance 2025-01-09 17:28:34 +07:00
web@ppanel 25da429da6 🔧 chore(ui): Update package dependencies for improved stability and performance 2025-01-09 13:30:11 +07:00
web@ppanel 12026b02cd 🐛 fix(auth): Refactor user authentication forms to remove global store dependency and improve type handling 2025-01-09 13:19:18 +07:00
web@ppanel 6301409531 🐛 fix(user): Add the 'gift_amount' field to the user service's type definition 2025-01-08 23:42:34 +07:00
web@ppanel b13c77e9b7 feat(user): Add 'gift_amount' field and update related references in user services and components 2025-01-08 23:25:13 +07:00
web@ppanel a4e9d5da59 feat(locales): Replace 'nodeGroupId' with 'groupId' in multiple language files for consistency 2025-01-08 23:13:32 +07:00
web@ppanel 70497af0aa feat(locales): Update 'deductBalance' to 'giftAmount' across multiple languages and fix newline in announcement.json 2025-01-08 12:55:10 +07:00
web@ppanel 46ae1665be feat(stats): Replace dynamic stat fetching with environment constants for user, server, and location counts 2025-01-08 12:54:43 +07:00
web@ppanel 3547bb1596 feat(subscribe): Update suffix from 'MB' to 'Mbps' and enhance speed limit display logic 2025-01-08 11:14:16 +07:00
semantic-release-bot 10d322f1ba 🔖 chore(release): v1.0.0-beta.4 [skip ci]
# [1.0.0-beta.4](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2025-01-07)

### ♻ Code Refactoring

* **auth**: Refactor user authorization handling and improve error logging ([68bc18f](https://github.com/perfect-panel/ppanel-web/commit/68bc18f))

###  Features

* **affiliate**: Add Affiliate component with commission display and invite link functionality ([4aea4e8](https://github.com/perfect-panel/ppanel-web/commit/4aea4e8))
* **affiliate**: Update affiliate component to display total commission and improve data fetching ([cc834ca](https://github.com/perfect-panel/ppanel-web/commit/cc834ca))
* **api**: Add new subscription properties and locale support for deduction ratios and reset cycles ([fec80f5](https://github.com/perfect-panel/ppanel-web/commit/fec80f5))
* **api**: Add Time Period Configuration ([837157c](https://github.com/perfect-panel/ppanel-web/commit/837157c))
* **favicon**: Update SVG favicon design for admin and user interfaces ([1d91738](https://github.com/perfect-panel/ppanel-web/commit/1d91738))
* **node**: Add serverKey ([25ce37e](https://github.com/perfect-panel/ppanel-web/commit/25ce37e))
* **relay**: Add relay mode configuration and update related schemas ([3cc9477](https://github.com/perfect-panel/ppanel-web/commit/3cc9477))
* **schema**: Add security field to hysteria2 and tuic schemas ([cd59d44](https://github.com/perfect-panel/ppanel-web/commit/cd59d44))
* **subscribe**: Add reset_time to API typings and update unsubscribe logic ([eeea165](https://github.com/perfect-panel/ppanel-web/commit/eeea165))
* **subscribe**: Add subscribe_discount type ([f99c604](https://github.com/perfect-panel/ppanel-web/commit/f99c604))
* **subscribe**: Add subscription credits ([5bc7905](https://github.com/perfect-panel/ppanel-web/commit/5bc7905))
* **subscribe**: Add unsubscribe functionality with confirmation messages and localized strings ([b2a2f42](https://github.com/perfect-panel/ppanel-web/commit/b2a2f42))
* **subscribe**: Improve error handling in subscription forms and update component props ([d28a10b](https://github.com/perfect-panel/ppanel-web/commit/d28a10b))
* **subscribe**: Improve layout and styling in subscription components ([5766376](https://github.com/perfect-panel/ppanel-web/commit/5766376))
* **subscription**: Add localized messages for existing subscriptions and deletion restrictions ([e8a72d5](https://github.com/perfect-panel/ppanel-web/commit/e8a72d5))

### 🎫 Chores

* Update changelog, enhance prepare script, and add openapi command ([a93db4e](https://github.com/perfect-panel/ppanel-web/commit/a93db4e))

### 🐛 Bug Fixes

* **dashboard**: Correct progress value calculations and update groupId accessor ([36c7667](https://github.com/perfect-panel/ppanel-web/commit/36c7667))
* **layout**: Remove unnecessary cookie initialization in Logout function ([3065c3a](https://github.com/perfect-panel/ppanel-web/commit/3065c3a))
* **locales**: Update Hong Kong ([6d0d069](https://github.com/perfect-panel/ppanel-web/commit/6d0d069))
* **subscribe**: Update value validation to check for number type in subscribe form ([6de29d5](https://github.com/perfect-panel/ppanel-web/commit/6de29d5))

### 💄 Styles

* **locales**: Remove unused subscription labels from multiple locale files ([fb0c510](https://github.com/perfect-panel/ppanel-web/commit/fb0c510))
* **locales**: Update server.json to reorganize relay mode options and improve labels ([701cdee](https://github.com/perfect-panel/ppanel-web/commit/701cdee))
* **node**: Improve layout and spacing in NodeStatusCell component ([136287d](https://github.com/perfect-panel/ppanel-web/commit/136287d))
* **time-slot**: Add chart display ([c44ad47](https://github.com/perfect-panel/ppanel-web/commit/c44ad47))
2025-01-07 17:46:57 +00:00
web@ppanel 1d917383eb feat(favicon): Update SVG favicon design for admin and user interfaces 2025-01-08 00:44:26 +07:00
web@ppanel 36c76674b6 🐛 fix(dashboard): Correct progress value calculations and update groupId accessor 2025-01-08 00:43:32 +07:00
web@ppanel 5766376590 feat(subscribe): Improve layout and styling in subscription components 2025-01-08 00:42:58 +07:00
lyndon986 6d0d069ce7 🐛 fix(locales): Update Hong Kong 2025-01-04 23:11:21 +07:00
web@ppanel 6de29d51c4 🐛 fix(subscribe): Update value validation to check for number type in subscribe form 2025-01-04 22:45:10 +07:00
web@ppanel e8a72d5579 feat(subscription): Add localized messages for existing subscriptions and deletion restrictions 2025-01-04 22:30:27 +07:00
web@ppanel eeea165f7e feat(subscribe): Add reset_time to API typings and update unsubscribe logic 2025-01-04 20:57:37 +07:00
web@ppanel 25ce37ea05 feat(node): Add serverKey 2025-01-04 20:26:53 +07:00
web@ppanel b2a2f42e53 feat(subscribe): Add unsubscribe functionality with confirmation messages and localized strings 2025-01-04 20:05:00 +07:00
web@ppanel cc834caa30 feat(affiliate): Update affiliate component to display total commission and improve data fetching 2025-01-04 16:51:03 +07:00
web@ppanel 4aea4e811f feat(affiliate): Add Affiliate component with commission display and invite link functionality 2025-01-03 13:54:33 +07:00
web@ppanel fb0c510b93 💄 style(locales): Remove unused subscription labels from multiple locale files 2025-01-02 22:04:07 +07:00
web@ppanel d28a10b6df feat(subscribe): Improve error handling in subscription forms and update component props 2025-01-02 21:58:36 +07:00
web@ppanel f99c6048ad feat(subscribe): Add subscribe_discount type 2025-01-01 16:13:04 +07:00
web@ppanel 136287d85a 💄 style(node): Improve layout and spacing in NodeStatusCell component 2025-01-01 12:44:57 +07:00
web@ppanel 5bc7905a52 feat(subscribe): Add subscription credits 2024-12-31 20:16:14 +07:00
web@ppanel 701cdee6de 💄 style(locales): Update server.json to reorganize relay mode options and improve labels 2024-12-31 20:15:45 +07:00
web@ppanel 3065c3a0df 🐛 fix(layout): Remove unnecessary cookie initialization in Logout function 2024-12-30 22:53:06 +07:00
web@ppanel 68bc18f584 ♻️ refactor(auth): Refactor user authorization handling and improve error logging 2024-12-30 22:41:12 +07:00
web@ppanel cd59d44435 feat(schema): Add security field to hysteria2 and tuic schemas 2024-12-30 20:59:35 +07:00
web@ppanel 3cc94773ef feat(relay): Add relay mode configuration and update related schemas 2024-12-30 17:28:24 +07:00
web@ppanel c44ad47f3c 💄 style(time-slot): Add chart display 2024-12-30 13:02:03 +07:00
web@ppanel 837157cc42 feat(api): Add Time Period Configuration 2024-12-29 22:10:43 +07:00
web@ppanel fec80f592d feat(api): Add new subscription properties and locale support for deduction ratios and reset cycles 2024-12-29 16:18:21 +07:00
web@ppanel a93db4eb9f 🔧 chore: Update changelog, enhance prepare script, and add openapi command 2024-12-28 23:24:40 +07:00
339 changed files with 4630 additions and 2319 deletions
+68 -2
View File
@@ -1,12 +1,78 @@
<a name="readme-top"></a>
# Changelog
# [1.0.0-beta.3](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2024-12-26)
# [1.0.0-beta.5](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2025-01-09)
### ✨ Features
* **locales**: Replace 'nodeGroupId' with 'groupId' in multiple language files for consistency ([a4e9d5d](https://github.com/perfect-panel/ppanel-web/commit/a4e9d5d))
* **locales**: Update 'deductBalance' to 'giftAmount' across multiple languages and fix newline in announcement.json ([70497af](https://github.com/perfect-panel/ppanel-web/commit/70497af))
* **stats**: Replace dynamic stat fetching with environment constants for user, server, and location counts ([46ae166](https://github.com/perfect-panel/ppanel-web/commit/46ae166))
* **subscribe**: Update suffix from 'MB' to 'Mbps' and enhance speed limit display logic ([3547bb1](https://github.com/perfect-panel/ppanel-web/commit/3547bb1))
* **user**: Add 'gift_amount' field and update related references in user services and components ([b13c77e](https://github.com/perfect-panel/ppanel-web/commit/b13c77e))
### 🎫 Chores
* **deps**: Update package dependencies across multiple projects for improved stability and performance ([b01a5bc](https://github.com/perfect-panel/ppanel-web/commit/b01a5bc))
* **ui**: Update package dependencies for improved stability and performance ([25da429](https://github.com/perfect-panel/ppanel-web/commit/25da429))
### 🐛 Bug Fixes
* **api**: Replace 'deduction' with 'gift_amount' and add 'commission' field in type definitions ([77edf1d](https://github.com/perfect-panel/ppanel-web/commit/77edf1d))
* **api**: Update API type definitions to replace 'deduction' with 'gift_amount' and make 'commission' field optional ([c2af060](https://github.com/perfect-panel/ppanel-web/commit/c2af060))
* **auth**: Refactor user authentication forms to remove global store dependency and improve type handling ([12026b0](https://github.com/perfect-panel/ppanel-web/commit/12026b0))
* **coupon**: Rename 'server' field to 'subscribe' in coupon form and update coupon update request type ([f8b6d82](https://github.com/perfect-panel/ppanel-web/commit/f8b6d82))
* **types**: Add 'gift_amount' field to API type definitions ([8f8a12a](https://github.com/perfect-panel/ppanel-web/commit/8f8a12a))
* **user**: Add the 'gift_amount' field to the user service's type definition ([6301409](https://github.com/perfect-panel/ppanel-web/commit/6301409))
<a name="readme-top"></a>
# Changelog
# [1.0.0-beta.4](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2025-01-07)
### ♻ Code Refactoring
* **config**: Simplify environment variable handling and improve build script ([cf54d0f](https://github.com/perfect-panel/ppanel-web/commit/cf54d0f))
- **auth**: Refactor user authorization handling and improve error logging ([68bc18f](https://github.com/perfect-panel/ppanel-web/commit/68bc18f))
### ✨ Features
- **affiliate**: Add Affiliate component with commission display and invite link functionality ([4aea4e8](https://github.com/perfect-panel/ppanel-web/commit/4aea4e8))
- **affiliate**: Update affiliate component to display total commission and improve data fetching ([cc834ca](https://github.com/perfect-panel/ppanel-web/commit/cc834ca))
- **api**: Add new subscription properties and locale support for deduction ratios and reset cycles ([fec80f5](https://github.com/perfect-panel/ppanel-web/commit/fec80f5))
- **api**: Add Time Period Configuration ([837157c](https://github.com/perfect-panel/ppanel-web/commit/837157c))
- **favicon**: Update SVG favicon design for admin and user interfaces ([1d91738](https://github.com/perfect-panel/ppanel-web/commit/1d91738))
- **node**: Add serverKey ([25ce37e](https://github.com/perfect-panel/ppanel-web/commit/25ce37e))
- **relay**: Add relay mode configuration and update related schemas ([3cc9477](https://github.com/perfect-panel/ppanel-web/commit/3cc9477))
- **schema**: Add security field to hysteria2 and tuic schemas ([cd59d44](https://github.com/perfect-panel/ppanel-web/commit/cd59d44))
- **subscribe**: Add reset_time to API typings and update unsubscribe logic ([eeea165](https://github.com/perfect-panel/ppanel-web/commit/eeea165))
- **subscribe**: Add subscribe_discount type ([f99c604](https://github.com/perfect-panel/ppanel-web/commit/f99c604))
- **subscribe**: Add subscription credits ([5bc7905](https://github.com/perfect-panel/ppanel-web/commit/5bc7905))
- **subscribe**: Add unsubscribe functionality with confirmation messages and localized strings ([b2a2f42](https://github.com/perfect-panel/ppanel-web/commit/b2a2f42))
- **subscribe**: Improve error handling in subscription forms and update component props ([d28a10b](https://github.com/perfect-panel/ppanel-web/commit/d28a10b))
- **subscribe**: Improve layout and styling in subscription components ([5766376](https://github.com/perfect-panel/ppanel-web/commit/5766376))
- **subscription**: Add localized messages for existing subscriptions and deletion restrictions ([e8a72d5](https://github.com/perfect-panel/ppanel-web/commit/e8a72d5))
### 🎫 Chores
- Update changelog, enhance prepare script, and add openapi command ([a93db4e](https://github.com/perfect-panel/ppanel-web/commit/a93db4e))
### 🐛 Bug Fixes
- **dashboard**: Correct progress value calculations and update groupId accessor ([36c7667](https://github.com/perfect-panel/ppanel-web/commit/36c7667))
- **layout**: Remove unnecessary cookie initialization in Logout function ([3065c3a](https://github.com/perfect-panel/ppanel-web/commit/3065c3a))
- **locales**: Update Hong Kong ([6d0d069](https://github.com/perfect-panel/ppanel-web/commit/6d0d069))
- **subscribe**: Update value validation to check for number type in subscribe form ([6de29d5](https://github.com/perfect-panel/ppanel-web/commit/6de29d5))
### 💄 Styles
- **locales**: Remove unused subscription labels from multiple locale files ([fb0c510](https://github.com/perfect-panel/ppanel-web/commit/fb0c510))
- **locales**: Update server.json to reorganize relay mode options and improve labels ([701cdee](https://github.com/perfect-panel/ppanel-web/commit/701cdee))
- **node**: Improve layout and spacing in NodeStatusCell component ([136287d](https://github.com/perfect-panel/ppanel-web/commit/136287d))
- **time-slot**: Add chart display ([c44ad47](https://github.com/perfect-panel/ppanel-web/commit/c44ad47))
<a name="readme-top"></a>
-3
View File
@@ -4,7 +4,6 @@ import {
NEXT_PUBLIC_DEFAULT_USER_EMAIL,
NEXT_PUBLIC_DEFAULT_USER_PASSWORD,
} from '@/config/constants';
import useGlobalStore from '@/config/use-global';
import { checkUser, resetPassword, userLogin, userRegister } from '@/services/common/auth';
import { getRedirectUrl, setAuthorization } from '@/utils/common';
import { useTranslations } from 'next-intl';
@@ -18,8 +17,6 @@ import UserResetForm from './user-reset-form';
export default function UserAuthForm() {
const t = useTranslations('auth');
const { common } = useGlobalStore();
const { register } = common;
const router = useRouter();
const [type, setType] = useState<'login' | 'register' | 'reset'>();
const [loading, startTransition] = useTransition();
+9 -18
View File
@@ -8,30 +8,21 @@ import { useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
interface UserCheckFormProps {
loading?: boolean;
onSubmit: (data: any) => void;
initialValues: any;
}
export default function UserCheckForm({
loading,
onSubmit,
initialValues,
}: {
loading?: boolean;
onSubmit: (data: any) => void;
initialValues: any;
}) {
}: Readonly<UserCheckFormProps>) {
const t = useTranslations('auth.check');
// const { common } = useGlobalStore();
// const { register } = common;
const formSchema = z.object({
email: z.string().email(t('email')),
// .refine(
// (email) => {
// if (!register.enable_email_domain_suffix) return true;
// const domain = email.split('@')[1] as string;
// return register.email_domain_suffix_list.split('\n').includes(domain);
// },
// {
// message: t('whitelist'),
// },
// ),
});
const form = useForm<z.infer<typeof formSchema>>({
@@ -61,7 +52,7 @@ export default function UserCheckForm({
};
useEffect(() => {
if (initialValues && initialValues.email) {
if (initialValues?.email) {
handleEmailChange(initialValues.email);
}
return () => {
@@ -235,7 +235,7 @@ export default function CouponForm<T extends Record<string, any>>({
)}
<FormField
control={form.control}
name='server'
name='subscribe'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.specifiedServer')}</FormLabel>
+2 -2
View File
@@ -96,9 +96,9 @@ export default function Page() {
defaultChecked={row.getValue('enable')}
onCheckedChange={async (checked) => {
await updateCoupon({
...row,
...row.original,
enable: checked,
} as any);
} as API.UpdateCouponRequest);
ref.current?.refresh();
}}
/>
+14 -3
View File
@@ -36,6 +36,7 @@ const baseProtocolSchema = z.object({
const shadowsocksSchema = z.object({
method: z.string(),
port: portSchema,
server_key: nullableString,
});
const vmessSchema = baseProtocolSchema;
@@ -51,11 +52,13 @@ const hysteria2Schema = z.object({
hop_ports: nullableString,
hop_interval: z.number().nullish(),
obfs_password: nullableString,
security: z.string(),
security_config: securityConfigSchema,
});
const tuicSchema = z.object({
port: portSchema,
security: z.string(),
security_config: securityConfigSchema,
});
@@ -92,9 +95,17 @@ const baseFormSchema = z.object({
speed_limit: z.number().nullish(),
traffic_ratio: z.number().default(1),
group_id: z.number().nullish(),
enable_relay: z.boolean().nullish().default(false),
relay_host: nullableString,
relay_port: portSchema,
relay_mode: z.string().nullish().default('none'),
relay_node: z
.array(
z.object({
host: z.string(),
port: portSchema,
prefix: z.string().nullish(),
}),
)
.nullish()
.default([]),
});
export const formSchema = z.intersection(baseFormSchema, protocolConfigSchema);
+123 -68
View File
@@ -33,14 +33,15 @@ import {
import { Switch } from '@workspace/ui/components/switch';
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Combobox } from '@workspace/ui/custom-components/combobox';
import { ArrayInput } from '@workspace/ui/custom-components/dynamic-Inputs';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { cn } from '@workspace/ui/lib/utils';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { formSchema, protocols } from './form-schema';
interface NodeFormProps<T> {
onSubmit: (data: T) => Promise<boolean> | boolean;
initialValues?: T;
@@ -55,7 +56,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
loading,
trigger,
title,
}: NodeFormProps<T>) {
}: Readonly<NodeFormProps<T>>) {
const t = useTranslations('server.node');
const [open, setOpen] = useState(false);
@@ -75,6 +76,8 @@ export default function NodeForm<T extends { [x: string]: any }>({
const protocol = form.watch('protocol');
const transport = form.watch('config.transport');
const security = form.watch('config.security');
const relayMode = form.watch('relay_mode');
const method = form.watch('config.method');
useEffect(() => {
form?.reset(initialValues);
@@ -105,7 +108,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
{trigger}
</Button>
</SheetTrigger>
<SheetContent className='w-[500px] max-w-full md:max-w-screen-md'>
<SheetContent className='w-[520px] max-w-full md:max-w-screen-md'>
<SheetHeader>
<SheetTitle>{title}</SheetTitle>
</SheetHeader>
@@ -136,7 +139,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
name='group_id'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.nodeGroupId')}</FormLabel>
<FormLabel>{t('form.groupId')}</FormLabel>
<FormControl>
<Combobox<number, false>
placeholder={t('form.selectNodeGroup')}
@@ -145,6 +148,9 @@ export default function NodeForm<T extends { [x: string]: any }>({
value: item.id,
label: item.name,
}))}
onChange={(value) => {
form.setValue(field.name, value || 0);
}}
/>
</FormControl>
<FormMessage />
@@ -187,7 +193,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
onValueChange={(value) => {
form.setValue(field.name, value);
}}
suffix='MB'
suffix='Mbps'
/>
</FormControl>
<FormMessage />
@@ -214,65 +220,6 @@ export default function NodeForm<T extends { [x: string]: any }>({
</FormItem>
)}
/>
<FormField
control={form.control}
name='enable_relay'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.enableRelay')}</FormLabel>
<FormControl>
<div className='pt-2'>
<Switch
checked={!!field.value}
onCheckedChange={(value) => {
form.setValue(field.name, value);
}}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='relay_host'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.relayHost')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='relay_port'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.relayPort')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
type='number'
min={1}
max={65535}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
@@ -358,6 +305,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
<EnhancedInput
{...field}
type='number'
placeholder='1-65535'
min={1}
max={65535}
onValueChange={(value) => {
@@ -369,6 +317,30 @@ export default function NodeForm<T extends { [x: string]: any }>({
</FormItem>
)}
/>
{[
'2022-blake3-aes-128-gcm',
'2022-blake3-aes-256-gcm',
'2022-blake3-chacha20-poly1305',
].includes(method) && (
<FormField
control={form.control}
name='config.server_key'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.serverKey')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
)}
</div>
)}
@@ -389,6 +361,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
<EnhancedInput
{...field}
type='number'
placeholder='1-65535'
onValueChange={(value) => {
form.setValue(field.name, value);
}}
@@ -499,7 +472,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
control={form.control}
name='config.transport'
render={({ field }) => (
<FormItem className='min-w-32'>
<FormItem className='!mt-0 min-w-32'>
<FormControl>
<Select
value={field.value}
@@ -603,7 +576,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
control={form.control}
name='config.security'
render={({ field }) => (
<FormItem className='min-w-32'>
<FormItem className='!mt-0 min-w-32'>
<Select
value={field.value}
onValueChange={(value) => {
@@ -814,6 +787,84 @@ export default function NodeForm<T extends { [x: string]: any }>({
</Card>
</div>
)}
<Card>
<CardHeader className='flex flex-row items-center justify-between p-3'>
<CardTitle>{t('form.relayMode')}</CardTitle>
<FormField
control={form.control}
name='relay_mode'
render={({ field }) => (
<FormItem className='!mt-0 min-w-32'>
<FormControl>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('form.selectRelayMode')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='none'>
{t('form.relayModeOptions.none')}
</SelectItem>
<SelectItem value='all'>{t('form.relayModeOptions.all')}</SelectItem>
<SelectItem value='random'>
{t('form.relayModeOptions.random')}
</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardHeader>
{relayMode !== 'none' && (
<CardContent className='w-full space-y-3 px-3'>
<FormField
control={form.control}
name='relay_node'
render={({ field }) => (
<FormItem>
<FormControl>
<ArrayInput
fields={[
{
name: 'host',
type: 'text',
placeholder: t('form.relayHost'),
},
{
name: 'port',
type: 'number',
min: 1,
max: 65535,
placeholder: t('form.relayPort'),
},
{
name: 'prefix',
type: 'text',
placeholder: t('form.relayPrefix'),
},
]}
value={field.value}
onChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
)}
</Card>
</form>
</Form>
</ScrollArea>
@@ -830,8 +881,12 @@ export default function NodeForm<T extends { [x: string]: any }>({
<Button
disabled={loading}
onClick={form.handleSubmit(handleSubmit, (errors) => {
console.log(errors);
return errors;
const keys = Object.keys(errors);
for (const key of keys) {
const formattedKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
toast.error(`${t(`form.${formattedKey}`)} is ${errors[key]?.message}`);
return false;
}
})}
>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}{' '}
+47 -47
View File
@@ -42,57 +42,57 @@ export function NodeStatusCell({ status }: { status: API.NodeStatus }) {
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div className='flex items-center space-x-2 rounded-md'>
<Badge variant={badgeVariant}>{badgeText}</Badge>
<span className='text-sm font-medium'>
{t('onlineCount')}: {onlineCount}
</span>
</div>
</TooltipTrigger>
<TooltipContent className='bg-muted text-foreground w-80'>
<div className='space-y-4'>
<>
<div className='space-y-2'>
<div className='space-y-1'>
<div className='flex justify-between text-xs'>
<span className='font-medium'>CPU</span>
<span>{formatPercentage(serverStatus?.cpu ?? 0)}</span>
</div>
<Progress value={(serverStatus?.cpu ?? 0) * 100} className='h-2' />
</div>
<div className='space-y-1'>
<div className='flex justify-between text-xs'>
<span className='font-medium'>{t('memory')}</span>
<span>{formatPercentage(serverStatus?.mem ?? 0)}</span>
</div>
<Progress value={(serverStatus?.mem ?? 0) * 100} className='h-2' />
</div>
<div className='space-y-1'>
<div className='flex justify-between text-xs'>
<span className='font-medium'>{t('disk')}</span>
<span>{formatPercentage(serverStatus?.disk ?? 0)}</span>
</div>
<Progress value={(serverStatus?.disk ?? 0) * 100} className='h-2' />
</div>
<div className='flex items-center gap-2 text-xs *:flex-1'>
<div className='flex items-center space-x-1'>
<Badge variant={badgeVariant}>{badgeText}</Badge>
<span className='font-medium'>
{t('onlineCount')}: {onlineCount}
</span>
</div>
<div className='flex flex-col space-y-1'>
<div className='flex justify-between'>
<span>CPU</span>
<span>{formatPercentage(serverStatus?.cpu ?? 0)}</span>
</div>
<div className='text-xs'>
<Progress value={serverStatus?.cpu ?? 0} className='h-2' max={100} />
</div>
<div className='flex flex-col space-y-1'>
<div className='flex justify-between'>
<span>{t('memory')}</span>
<span>{formatPercentage(serverStatus?.mem ?? 0)}</span>
</div>
<Progress value={serverStatus?.mem ?? 0} className='h-2' max={100} />
</div>
<div className='flex flex-col space-y-1'>
<div className='flex justify-between'>
<span>{t('disk')}</span>
<span>{formatPercentage(serverStatus?.disk ?? 0)}</span>
</div>
<Progress value={serverStatus?.disk ?? 0} className='h-2' max={100} />
</div>
{isOnline && (
<div>
{t('lastUpdated')}: {formatDate(serverStatus?.updated_at ?? 0)}
</div>
{isOnline && onlineCount > 0 && (
<div className='space-y-2'>
<h4 className='text-sm font-semibold'>{t('onlineUsers')}</h4>
<ScrollArea className='h-[400px] rounded-md border p-2'>
{online_users.map((user, index) => (
<div key={user.uid} className='py-1 text-xs'>
{user.ip} (UID: {user.uid})
</div>
))}
</ScrollArea>
</div>
)}
</>
)}
</div>
</TooltipContent>
</TooltipTrigger>
{isOnline && onlineCount > 0 && (
<TooltipContent className='bg-muted text-foreground w-80'>
<div className='space-y-4'>
<div className='space-y-2'>
<h4 className='text-sm font-semibold'>{t('onlineUsers')}</h4>
<ScrollArea className='h-[400px] rounded-md border p-2'>
{online_users.map((user, index) => (
<div key={user.uid} className='py-1 text-xs'>
{user.ip} (UID: {user.uid})
</div>
))}
</ScrollArea>
</div>
</div>
</TooltipContent>
)}
</Tooltip>
</TooltipProvider>
);
@@ -135,7 +135,7 @@ export default function NodeTable() {
accessorKey: 'speed_limit',
header: t('speedLimit'),
cell: ({ row }) => (
<Display type='traffic' value={row.getValue('speed_limit')} unlimited />
<Display type='trafficSpeed' value={row.getValue('speed_limit')} unlimited />
),
},
{
@@ -145,10 +145,10 @@ export default function NodeTable() {
},
{
accessorKey: 'groupId',
accessorKey: 'group_id',
header: t('nodeGroup'),
cell: ({ row }) => {
const name = groups?.find((group) => group.id === row.getValue('groupId'))?.name;
const name = groups?.find((group) => group.id === row.getValue('group_id'))?.name;
return name ? <Badge variant='outline'>{name}</Badge> : '--';
},
},
File diff suppressed because it is too large Load Diff
@@ -133,7 +133,14 @@ export default function SubscribeTable() {
{
accessorKey: 'unit_price',
header: t('unitPrice'),
cell: ({ row }) => <Display type='currency' value={row.getValue('unit_price')} />,
cell: ({ row }) => {
return (
<>
<Display type='currency' value={row.getValue('unit_price')} />/
{t(row.original.unit_time ? `form.${row.original.unit_time}` : 'form.Month')}
</>
);
},
},
{
accessorKey: 'replacement',
+209 -58
View File
@@ -1,15 +1,33 @@
'use client';
import { getNodeConfig, updateNodeConfig } from '@/services/admin/system';
import { Icon } from '@iconify/react';
import {
getNodeConfig,
getNodeMultiplier,
setNodeMultiplier,
updateNodeConfig,
} from '@/services/admin/system';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { ChartContainer, ChartTooltip } from '@workspace/ui/components/chart';
import { Label } from '@workspace/ui/components/label';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { ArrayInput } from '@workspace/ui/custom-components/dynamic-Inputs';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { DicesIcon } from 'lucide-react';
import { nanoid } from 'nanoid';
import { useTranslations } from 'next-intl';
import { useMemo, useState } from 'react';
import { Cell, Legend, Pie, PieChart } from 'recharts';
import { toast } from 'sonner';
const COLORS = [
'hsl(var(--chart-1))',
'hsl(var(--chart-2))',
'hsl(var(--chart-3))',
'hsl(var(--chart-4))',
'hsl(var(--chart-5))',
];
export default function Node() {
const t = useTranslations('system.node');
@@ -36,62 +54,195 @@ export default function Node() {
}
}
const [timeSlots, setTimeSlots] = useState<API.TimePeriod[]>([]);
const { data: NodeMultiplier, refetch: refetchNodeMultiplier } = useQuery({
queryKey: ['getNodeMultiplier'],
queryFn: async () => {
const { data } = await getNodeMultiplier();
if (timeSlots.length === 0) {
setTimeSlots(data.data?.periods || []);
}
return data.data?.periods || [];
},
});
const chartTimeSlots = useMemo(() => {
return timeSlots.map((slot) => ({
name: `${slot.start_time} - ${slot.end_time}`,
value: slot.multiplier,
}));
}, [timeSlots]);
const chartConfig = useMemo(() => {
return chartTimeSlots.reduce(
(acc, item, index) => {
acc[item.name] = {
label: item.name,
color: COLORS[index % COLORS.length] || 'hsl(var(--default-chart-color))',
};
return acc;
},
{} as Record<string, { label: string; color: string }>,
);
}, [data]);
return (
<Table>
<TableBody>
<TableRow>
<TableCell>
<Label>{t('communicationKey')}</Label>
<p className='text-muted-foreground text-xs'>{t('communicationKeyDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.node_secret}
onValueBlur={(value) => updateConfig('node_secret', value)}
suffix={
<Icon
icon='uil:arrow-random'
onClick={() => {
updateConfig('node_secret', nanoid());
}}
/>
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('nodePullInterval')}</Label>
<p className='text-muted-foreground text-xs'>{t('nodePullIntervalDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
type='number'
min={0}
onValueBlur={(value) => updateConfig('node_pull_interval', value)}
suffix='S'
value={data?.node_pull_interval}
placeholder={t('inputPlaceholder')}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('nodePushInterval')}</Label>
<p className='text-muted-foreground text-xs'>{t('nodePushIntervalDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
type='number'
min={0}
value={data?.node_push_interval}
onValueBlur={(value) => updateConfig('node_push_interval', value)}
placeholder={t('inputPlaceholder')}
/>
</TableCell>
</TableRow>
</TableBody>
</Table>
<>
<Table>
<TableBody>
<TableRow>
<TableCell>
<Label>{t('communicationKey')}</Label>
<p className='text-muted-foreground text-xs'>{t('communicationKeyDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.node_secret}
onValueBlur={(value) => updateConfig('node_secret', value)}
suffix={
<DicesIcon
onClick={() => {
updateConfig('node_secret', nanoid());
}}
/>
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('nodePullInterval')}</Label>
<p className='text-muted-foreground text-xs'>{t('nodePullIntervalDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
type='number'
min={0}
onValueBlur={(value) => updateConfig('node_pull_interval', value)}
suffix='S'
value={data?.node_pull_interval}
placeholder={t('inputPlaceholder')}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('nodePushInterval')}</Label>
<p className='text-muted-foreground text-xs'>{t('nodePushIntervalDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
type='number'
min={0}
value={data?.node_push_interval}
onValueBlur={(value) => updateConfig('node_push_interval', value)}
placeholder={t('inputPlaceholder')}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('dynamicMultiplier')}</Label>
<p className='text-muted-foreground text-xs'>{t('dynamicMultiplierDescription')}</p>
</TableCell>
<TableCell className='flex justify-end gap-2'>
<Button
size='sm'
variant='outline'
onClick={() => {
setTimeSlots(NodeMultiplier || []);
}}
>
{t('reset')}
</Button>
<Button
size='sm'
onClick={() => {
setNodeMultiplier({
periods: timeSlots,
}).then(async () => {
const result = await refetchNodeMultiplier();
if (result.data) setTimeSlots(result.data);
toast.success(t('saveSuccess'));
});
}}
>
{t('save')}
</Button>
</TableCell>
</TableRow>
</TableBody>
</Table>
<div className='flex flex-col-reverse gap-8 px-4 pt-6 md:flex-row md:items-start'>
<div className='w-full md:w-1/2'>
<ChartContainer config={chartConfig} className='mx-auto aspect-[4/3] max-w-[400px]'>
<PieChart>
<Pie
data={chartTimeSlots}
cx='50%'
cy='50%'
labelLine={false}
outerRadius='80%'
fill='#8884d8'
dataKey='value'
label={({ name, percent, value }) =>
`${value?.toFixed(2)}x (${(percent * 100).toFixed(0)}%)`
}
>
{chartTimeSlots.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<ChartTooltip
content={({ payload }) => {
if (payload && payload.length) {
const data = payload[0]?.payload;
return (
<div className='bg-background rounded-lg border p-2 shadow-sm'>
<div className='grid grid-cols-2 gap-2'>
<div className='flex flex-col'>
<span className='text-muted-foreground text-[0.70rem] uppercase'>
{t('timeSlot')}
</span>
<span className='text-muted-foreground font-bold'>
{data.name || '其他'}
</span>
</div>
<div className='flex flex-col'>
<span className='text-muted-foreground text-[0.70rem] uppercase'>
{t('multiplier')}
</span>
<span className='font-bold'>{data.value.toFixed(2)}x</span>
</div>
</div>
</div>
);
}
return null;
}}
/>
<Legend />
</PieChart>
</ChartContainer>
</div>
<div className='w-full md:w-1/2'>
<ArrayInput<API.TimePeriod>
fields={[
{
name: 'start_time',
prefix: t('startTime'),
type: 'time',
},
{ name: 'end_time', prefix: t('endTime'), type: 'time' },
{ name: 'multiplier', prefix: t('multiplier'), type: 'number' },
]}
value={timeSlots}
onChange={setTimeSlots}
/>
</div>
</div>
</>
);
}
+18 -2
View File
@@ -1,11 +1,12 @@
'use client';
import { Display } from '@/components/display';
import { ProTable, ProTableActions } from '@/components/pro-table';
import { createUser, deleteUser, getUserList, updateUser } from '@/services/admin/user';
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, unitConversion } from '@workspace/ui/utils';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react';
import { toast } from 'sonner';
@@ -77,7 +78,22 @@ export default function Page() {
{
accessorKey: 'balance',
header: t('balance'),
cell: ({ row }) => unitConversion('centsToDollars', row.getValue('balance')),
cell: ({ row }) => <Display type='currency' value={row.getValue('balance')} />,
},
{
accessorKey: 'gift_amount',
header: t('giftAmount'),
cell: ({ row }) => <Display type='currency' value={row.getValue('gift_amount')} />,
},
{
accessorKey: 'commission',
header: t('commission'),
cell: ({ row }) => <Display type='currency' value={row.getValue('commission')} />,
},
{
accessorKey: 'refer_code',
header: t('inviteCode'),
cell: ({ row }) => row.getValue('refer_code') || '--',
},
{
accessorKey: 'referer_id',
+17 -2
View File
@@ -1,10 +1,11 @@
'use client';
import { Display } from '@/components/display';
import { getUserDetail } from '@/services/admin/user';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card';
import { formatDate, unitConversion } from '@workspace/ui/utils';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
@@ -43,7 +44,21 @@ export function UserDetail({ id }: { id: number }) {
</li>
<li className='flex items-center justify-between font-semibold'>
<span className='text-muted-foreground'>{t('balance')}</span>
<span>{unitConversion('centsToDollars', data?.balance)}</span>
<span>
<Display type='currency' value={data?.balance} />
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('giftAmount')}</span>
<span>
<Display type='currency' value={data?.gift_amount} />
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('commission')}</span>
<span>
<Display type='currency' value={data?.commission} />
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('createdAt')}</span>
+55 -2
View File
@@ -1,5 +1,6 @@
'use client';
import useGlobalStore from '@/config/use-global';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react';
import { Button } from '@workspace/ui/components/button';
@@ -43,8 +44,10 @@ export default function UserForm<T extends Record<string, any>>({
loading,
trigger,
title,
}: UserFormProps<T>) {
}: Readonly<UserFormProps<T>>) {
const t = useTranslations('user');
const { common } = useGlobalStore();
const { currency } = common;
const [open, setOpen] = useState(false);
const formSchema = z.object({
@@ -54,6 +57,8 @@ export default function UserForm<T extends Record<string, any>>({
refer_code: z.string().optional(),
is_admin: z.boolean().optional(),
balance: z.number().optional(),
gift_amount: z.number().optional(),
commission: z.number().optional(),
});
const form = useForm({
resolver: zodResolver(formSchema),
@@ -176,7 +181,7 @@ export default function UserForm<T extends Record<string, any>>({
<FormLabel>{t('form.balance')}</FormLabel>
<FormControl>
<EnhancedInput
prefix='¥'
prefix={currency?.currency_symbol ?? '$'}
placeholder={t('form.balancePlaceholder')}
type='number'
{...field}
@@ -192,6 +197,54 @@ export default function UserForm<T extends Record<string, any>>({
</FormItem>
)}
/>
<FormField
control={form.control}
name='gift_amount'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.giftAmount')}</FormLabel>
<FormControl>
<EnhancedInput
prefix={currency?.currency_symbol ?? '$'}
placeholder={t('form.giftAmountPlaceholder')}
type='number'
{...field}
formatInput={(value) => unitConversion('centsToDollars', value)}
formatOutput={(value) => unitConversion('dollarsToCents', value)}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
min={0}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='commission'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.commission')}</FormLabel>
<FormControl>
<EnhancedInput
prefix={currency?.currency_symbol ?? '$'}
placeholder={t('form.commissionPlaceholder')}
type='number'
{...field}
formatInput={(value) => unitConversion('centsToDollars', value)}
formatOutput={(value) => unitConversion('dollarsToCents', value)}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
min={0}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='is_admin'
+11 -7
View File
@@ -75,6 +75,8 @@ export default async function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
const Authorization = (await cookies()).get('Authorization')?.value;
const locale = await getLocale();
const messages = await getMessages();
@@ -86,13 +88,15 @@ export default async function RootLayout({
console.log('Error fetching global config:', error);
}
try {
user = await currentUser({
skipErrorHandler: true,
Authorization: (await cookies()).get('Authorization')?.value,
}).then((res) => res.data.data);
} catch (error) {
console.log('Error fetching current user:', error);
if (Authorization) {
try {
user = await currentUser({
skipErrorHandler: true,
Authorization,
}).then((res) => res.data.data);
} catch (error) {
console.log('Error fetching current user:', error);
}
}
return (
@@ -115,7 +115,10 @@ export function RevenueStatisticsCard() {
y={viewBox.cy}
className='fill-foreground text-2xl font-bold'
>
{RevenueStatistics?.today.amount_total}
{unitConversion(
'centsToDollars',
RevenueStatistics?.today.amount_total,
)}
</tspan>
</text>
);
+7 -3
View File
@@ -4,7 +4,7 @@ import useGlobalStore from '@/config/use-global';
import { formatBytes, unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
type DisplayType = 'currency' | 'traffic' | 'number';
type DisplayType = 'currency' | 'traffic' | 'number' | 'trafficSpeed';
interface DisplayProps<T> {
value?: T;
@@ -26,12 +26,16 @@ export function Display<T extends number | undefined | null>({
return formattedValue;
}
if (['traffic', 'number'].includes(type) && unlimited && !value) {
if (['traffic', 'trafficSpeed', 'number'].includes(type) && unlimited && !value) {
return t('unlimited');
}
if (type === 'traffic') {
return value ? formatBytes(value as number) : '0';
return value ? formatBytes(value) : '0';
}
if (type === 'trafficSpeed') {
return value ? formatBytes(value).replace('B', 'b') + 'ps' : '0';
}
if (type === 'number') {
+1
View File
@@ -22,6 +22,7 @@ export default function Providers({
defaultOptions: {
queries: {
staleTime: 5 * 1000,
retry: false,
},
},
}),
+8 -5
View File
@@ -4,10 +4,13 @@ import packageJSON from '../package.json';
export const locales = packageJSON.i18n.outputLocales;
export const defaultLocale = packageJSON.i18n.entry;
export const NEXT_PUBLIC_DEFAULT_LANGUAGE = env('NEXT_PUBLIC_DEFAULT_LANGUAGE') || defaultLocale;
export const NEXT_PUBLIC_DEFAULT_LANGUAGE =
env('NEXT_PUBLIC_DEFAULT_LANGUAGE') ?? process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE ?? defaultLocale;
export const NEXT_PUBLIC_SITE_URL = env('NEXT_PUBLIC_SITE_URL');
export const NEXT_PUBLIC_API_URL = env('NEXT_PUBLIC_API_URL');
export const NEXT_PUBLIC_SITE_URL = env('NEXT_PUBLIC_SITE_URL') ?? process.env.NEXT_PUBLIC_SITE_URL;
export const NEXT_PUBLIC_API_URL = env('NEXT_PUBLIC_API_URL') ?? process.env.NEXT_PUBLIC_API_URL;
export const NEXT_PUBLIC_DEFAULT_USER_EMAIL = env('NEXT_PUBLIC_DEFAULT_USER_EMAIL');
export const NEXT_PUBLIC_DEFAULT_USER_PASSWORD = env('NEXT_PUBLIC_DEFAULT_USER_PASSWORD');
export const NEXT_PUBLIC_DEFAULT_USER_EMAIL =
env('NEXT_PUBLIC_DEFAULT_USER_EMAIL') ?? process.env.NEXT_PUBLIC_DEFAULT_USER_EMAIL;
export const NEXT_PUBLIC_DEFAULT_USER_PASSWORD =
env('NEXT_PUBLIC_DEFAULT_USER_PASSWORD') ?? process.env.NEXT_PUBLIC_DEFAULT_USER_PASSWORD;
+2
View File
@@ -42,6 +42,8 @@
"50002": "Tento kupón již byl použit, nelze ho použít znovu.",
"60001": "Předplatné vypršelo, obnovte ho prosím a použijte znovu.",
"60002": "Toto předplatné nelze momentálně použít, zkuste to prosím později.",
"60003": "Bylo zjištěno existující předplatné. Zrušte ho, než budete pokračovat.",
"60004": "Nelze momentálně odstranit, protože předplatné má aktivní uživatele.",
"70001": "Ověřovací kód je nesprávný, zadejte ho prosím znovu.",
"80001": "Úkol nebyl úspěšně přidán do fronty, zkuste to prosím později.",
"90001": "Vypněte prosím režim DEBUG a zkuste to znovu.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Potvrdit",
"edit": "Upravit",
"editSecurity": "Upravit nastavení zabezpečení",
"enableRelay": "Povolit přenos",
"enableTLS": "Povolit TLS",
"encryptionMethod": "Metoda šifrování",
"flow": "Algoritmus řízení toku",
"groupId": "Skupina uzlů",
"hopInterval": "Interval skoků",
"hopPorts": "Porty skoků",
"hopPortsPlaceholder": "Více portů oddělených čárkou",
"name": "Název",
"nodeGroupId": "ID skupiny uzlů",
"obfsPassword": "Heslo pro zmatení",
"obfsPasswordPlaceholder": "Nechte prázdné, pokud nechcete zmást",
"path": "Cesta",
@@ -65,7 +64,14 @@
"port": "Port služby",
"protocol": "Protokol",
"relayHost": "Adresa přenosu",
"relayMode": "Režim relé",
"relayModeOptions": {
"all": "Vše",
"none": "Žádný",
"random": "Náhodný"
},
"relayPort": "Port přenosu",
"relayPrefix": "Předpona relé",
"remarks": "Poznámky",
"security": "Zabezpečení",
"securityConfig": "Nastavení zabezpečení",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Vyberte metodu šifrování",
"selectNodeGroup": "Vyberte skupinu uzlů",
"selectProtocol": "Vyberte protokol",
"selectRelayMode": "Vyberte režim relé",
"serverAddr": "Adresa serveru",
"serverKey": "Klíč serveru",
"serverName": "Název služby",
"speedLimit": "Omezení rychlosti",
"speedLimitPlaceholder": "Bez omezení",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Procento slevy",
"discount_price": "Cena po slevě",
"duration": "Doba trvání (měsíce)",
"groupId": "Skupina předplatného",
"inventory": "Sklad",
"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ů",
"speedLimit": "Omezení rychlosti (Mbps)",
"subscribeGroup": "Skupina předplatného",
"servers": "Servery",
"speedLimit": "Omezení rychlosti ",
"traffic": "Přenos dat",
"unitPrice": "Jednotková cena",
"unitTime": "Jednotka času"
@@ -83,6 +99,6 @@
"subscribeGroup": "Skupina předplatných"
},
"traffic": "provoz",
"unitPrice": "Cena/měsíc",
"unitPrice": "Jednotková cena",
"updateSuccess": "Aktualizace byla úspěšná"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Úspěšně uloženo"
},
"node": {
"addTimeSlot": "Přidat časový úsek",
"communicationKey": "Komunikační klíč",
"communicationKeyDescription": "Klíč pro komunikaci uzlu, aby se zajistilo, že data nebudou zachycena jinými osobami",
"delete": "Smazat",
"dynamicMultiplier": "Dynamický násobitel",
"dynamicMultiplierDescription": "Dynamický násobitel označuje zpracování posunutých dat s různými násobiteli pro různé uzly během různých časových období.",
"endTime": "Čas konce",
"inputPlaceholder": "Prosím zadejte",
"multiplier": "Násobitel",
"nodePullInterval": "Interval stahování uzlu",
"nodePullIntervalDescription": "Frekvence, s jakou uzel získává data z panelu (v sekundách)",
"nodePushInterval": "Interval odesílání uzlu",
"nodePushIntervalDescription": "Frekvence, s jakou uzel odesílá data do panelu",
"saveSuccess": "Úspěšně uloženo"
"reset": "Resetovat",
"save": "Uložit",
"saveSuccess": "Úspěšně uloženo",
"startTime": "Čas začátku",
"timeSlot": "Časový úsek"
},
"register": {
"emailSuffixWhitelist": "Seznam povolených přípon e-mailů",
+7
View File
@@ -2,6 +2,7 @@
"actions": "akce",
"balance": "Zůstatek",
"cancel": "zrušit",
"commission": "Provize",
"confirm": "Potvrdit",
"confirmDelete": "Opravdu chcete smazat?",
"create": "Vytvořit",
@@ -19,7 +20,11 @@
"balance": "Zůstatek",
"balancePlaceholder": "Zůstatek",
"cancel": "Zrušit",
"commission": "Provize",
"commissionPlaceholder": "Zadejte provizi",
"confirm": "Potvrdit",
"giftAmount": "Částka daru",
"giftAmountPlaceholder": "Zadejte částku daru",
"invalidEmailFormat": "Neplatný formát e-mailu",
"inviteCode": "Pozvánkový kód",
"inviteCodePlaceholder": "Zadejte pozvánkový kód (ponechte prázdné pro automatické generování)",
@@ -31,6 +36,8 @@
"userEmail": "E-mail uživatele",
"userEmailPlaceholder": "Zadejte e-mail uživatele"
},
"giftAmount": "Částka dárku",
"inviteCode": "Pozvánkový kód",
"referer": "Doporučitel",
"updateSuccess": "Aktualizace byla úspěšná",
"userList": "Seznam uživatelů",
+2
View File
@@ -42,6 +42,8 @@
"50002": "Dieser Gutschein wurde bereits verwendet und kann nicht erneut verwendet werden.",
"60001": "Das Abonnement ist abgelaufen, bitte erneuern und dann verwenden.",
"60002": "Das Abonnement kann derzeit nicht verwendet werden, bitte versuchen Sie es später erneut.",
"60003": "Ein bestehendes Abonnement wurde erkannt. Bitte kündigen Sie es, bevor Sie fortfahren.",
"60004": "Kann derzeit nicht gelöscht werden, da das Abonnement aktive Benutzer hat.",
"70001": "Der Bestätigungscode ist falsch, bitte erneut eingeben.",
"80001": "Die Aufgabe wurde nicht erfolgreich in die Warteschlange aufgenommen, bitte versuchen Sie es später erneut.",
"90001": "Bitte deaktivieren Sie den DEBUG-Modus und versuchen Sie es erneut.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Bestätigen",
"edit": "Bearbeiten",
"editSecurity": "Sicherheitskonfiguration bearbeiten",
"enableRelay": "Relay aktivieren",
"enableTLS": "TLS aktivieren",
"encryptionMethod": "Verschlüsselungsmethode",
"flow": "Flusskontrollalgorithmus",
"groupId": "Knotengruppe",
"hopInterval": "Sprungintervall",
"hopPorts": "Sprungports",
"hopPortsPlaceholder": "Mehrere Ports durch Kommas trennen",
"name": "Name",
"nodeGroupId": "Knotengruppen-ID",
"obfsPassword": "Verschleierungspasswort",
"obfsPasswordPlaceholder": "Leer lassen für keine Verschleierung",
"path": "Pfad",
@@ -65,7 +64,14 @@
"port": "Serverport",
"protocol": "Protokoll",
"relayHost": "Relay-Adresse",
"relayMode": "Relaismodus",
"relayModeOptions": {
"all": "Alle",
"none": "Keine",
"random": "Zufällig"
},
"relayPort": "Relay-Port",
"relayPrefix": "Relaispräfix",
"remarks": "Bemerkungen",
"security": "Sicherheit",
"securityConfig": "Sicherheitskonfiguration",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Verschlüsselungsmethode auswählen",
"selectNodeGroup": "Knotengruppe auswählen",
"selectProtocol": "Protokoll auswählen",
"selectRelayMode": "Relaismodus auswählen",
"serverAddr": "Serveradresse",
"serverKey": "Server-Schlüssel",
"serverName": "Dienstname",
"speedLimit": "Geschwindigkeitsbegrenzung",
"speedLimitPlaceholder": "Keine Begrenzung",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Rabattprozentsatz",
"discount_price": "Rabattpreis",
"duration": "Dauer (Monate)",
"groupId": "Abonnementgruppe",
"inventory": "Bestand",
"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",
"speedLimit": "Geschwindigkeitsbegrenzung (Mbps)",
"subscribeGroup": "Abonnementgruppe",
"servers": "Server",
"speedLimit": "Geschwindigkeitsbegrenzung ",
"traffic": "Datenvolumen",
"unitPrice": "Einheitspreis",
"unitTime": "Zeiteinheit"
@@ -83,6 +99,6 @@
"subscribeGroup": "Abonnieren Gruppe"
},
"traffic": "Verkehr",
"unitPrice": "Preis/Monat",
"unitPrice": "Stückpreis",
"updateSuccess": "Aktualisierung erfolgreich"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Erfolgreich gespeichert"
},
"node": {
"addTimeSlot": "Zeitfenster hinzufügen",
"communicationKey": "Kommunikationsschlüssel",
"communicationKeyDescription": "Schlüssel für die Kommunikation des Knotens, um sicherzustellen, dass Daten nicht von anderen abgefangen werden",
"delete": "Löschen",
"dynamicMultiplier": "Dynamischer Multiplikator",
"dynamicMultiplierDescription": "Dynamischer Multiplikator bezieht sich auf die Verarbeitung von übermittelten Daten mit unterschiedlichen Multiplikatoren für verschiedene Knoten während unterschiedlicher Zeiträume.",
"endTime": "Endzeit",
"inputPlaceholder": "Bitte eingeben",
"multiplier": "Multiplikator",
"nodePullInterval": "Knotenabfrageintervall",
"nodePullIntervalDescription": "Häufigkeit, mit der der Knoten Daten vom Panel abruft (Sekunden)",
"nodePushInterval": "Knotenübertragungsintervall",
"nodePushIntervalDescription": "Häufigkeit, mit der der Knoten Daten an das Panel überträgt",
"saveSuccess": "Erfolgreich gespeichert"
"reset": "Zurücksetzen",
"save": "Speichern",
"saveSuccess": "Erfolgreich gespeichert",
"startTime": "Startzeit",
"timeSlot": "Zeitfenster"
},
"register": {
"emailSuffixWhitelist": "E-Mail-Suffix-Whitelist",
+7
View File
@@ -2,6 +2,7 @@
"actions": "Aktionen",
"balance": "Kontostand",
"cancel": "Abbrechen",
"commission": "Provision",
"confirm": "Bestätigen",
"confirmDelete": "Sind Sie sicher, dass Sie löschen möchten?",
"create": "Erstellen",
@@ -19,7 +20,11 @@
"balance": "Kontostand",
"balancePlaceholder": "Kontostand",
"cancel": "Abbrechen",
"commission": "Provision",
"commissionPlaceholder": "Geben Sie die Provision ein",
"confirm": "Bestätigen",
"giftAmount": "Geschenkbetrag",
"giftAmountPlaceholder": "Geben Sie den Geschenkbetrag ein",
"invalidEmailFormat": "Ungültiges E-Mail-Format",
"inviteCode": "Einladungscode",
"inviteCodePlaceholder": "Bitte Einladungscode eingeben (leer lassen für automatische Generierung)",
@@ -31,6 +36,8 @@
"userEmail": "Benutzer-E-Mail",
"userEmailPlaceholder": "Bitte Benutzer-E-Mail eingeben"
},
"giftAmount": "Geschenkbetrag",
"inviteCode": "Einladungscode",
"referer": "Empfehler",
"updateSuccess": "Aktualisierung erfolgreich",
"userList": "Benutzerliste",
+2
View File
@@ -42,6 +42,8 @@
"50002": "The coupon has been used, cannot be used again.",
"60001": "Subscription has expired, please renew before using.",
"60002": "Unable to use the subscription at the moment, please try again later.",
"60003": "An existing subscription is detected. Please cancel it before proceeding.",
"60004": "Unable to delete at the moment as the subscription has active users.",
"70001": "Incorrect verification code, please re-enter.",
"80001": "Task was not successfully queued, please try again later.",
"90001": "Please disable DEBUG mode and try again.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Confirm",
"edit": "Edit",
"editSecurity": "Edit Security Configuration",
"enableRelay": "Enable Relay",
"enableTLS": "Enable TLS",
"encryptionMethod": "Encryption Method",
"flow": "Flow Control Algorithm",
"groupId": "Node Group",
"hopInterval": "Hop Interval",
"hopPorts": "Hop Ports",
"hopPortsPlaceholder": "Separate multiple ports with commas",
"name": "Name",
"nodeGroupId": "Node Group ID",
"obfsPassword": "Obfuscation Password",
"obfsPasswordPlaceholder": "Leave blank for no obfuscation",
"path": "Path",
@@ -65,7 +64,14 @@
"port": "Server Port",
"protocol": "Protocol",
"relayHost": "Relay Host",
"relayMode": "Relay Mode",
"relayModeOptions": {
"all": "All",
"none": "None",
"random": "Random"
},
"relayPort": "Relay Port",
"relayPrefix": "Relay Prefix",
"remarks": "Remarks",
"security": "Security",
"securityConfig": "Security Configuration",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Select Encryption Method",
"selectNodeGroup": "Select Node Group",
"selectProtocol": "Select Protocol",
"selectRelayMode": "Select Relay Mode",
"serverAddr": "Server Address",
"serverKey": "Server Key",
"serverName": "Service Name",
"speedLimit": "Speed Limit",
"speedLimitPlaceholder": "Unlimited",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Discount Percentage",
"discount_price": "Discount Price",
"duration": "Duration (months)",
"groupId": "Subscription Group",
"inventory": "Inventory",
"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",
"speedLimit": "Speed Limit (Mbps)",
"subscribeGroup": "Subscription Group",
"servers": "Servers",
"speedLimit": "Speed Limit ",
"traffic": "Traffic",
"unitPrice": "Unit Price",
"unitTime": "Unit Time"
@@ -83,6 +99,6 @@
"subscribeGroup": "Subscription Group"
},
"traffic": "Traffic",
"unitPrice": "Price/Month",
"unitPrice": "Unit Price",
"updateSuccess": "Update Successful"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Save Successful"
},
"node": {
"addTimeSlot": "Add Time Slot",
"communicationKey": "Communication Key",
"communicationKeyDescription": "Key for node communication to ensure data security",
"delete": "Delete",
"dynamicMultiplier": "Dynamic Multiplier",
"dynamicMultiplierDescription": "Dynamic Multiplier refers to processing pushed data with different multipliers for different nodes during different time periods.",
"endTime": "End Time",
"inputPlaceholder": "Enter",
"multiplier": "Multiplier",
"nodePullInterval": "Node Pull Interval",
"nodePullIntervalDescription": "Frequency (in seconds) for nodes to fetch data from the panel",
"nodePushInterval": "Node Push Interval",
"nodePushIntervalDescription": "Frequency for nodes to push data to the panel",
"saveSuccess": "Save Successful"
"reset": "Reset",
"save": "Save",
"saveSuccess": "Save Successful",
"startTime": "Start Time",
"timeSlot": "Time Slot"
},
"register": {
"emailSuffixWhitelist": "Email Suffix Whitelist",
+7
View File
@@ -2,6 +2,7 @@
"actions": "Actions",
"balance": "Balance",
"cancel": "Cancel",
"commission": "Commission",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"create": "Create",
@@ -19,7 +20,11 @@
"balance": "Balance",
"balancePlaceholder": "Balance",
"cancel": "Cancel",
"commission": "Commission",
"commissionPlaceholder": "Enter commission",
"confirm": "Confirm",
"giftAmount": "Gift Amount",
"giftAmountPlaceholder": "Enter gift amount",
"invalidEmailFormat": "Invalid email format",
"inviteCode": "Invite Code",
"inviteCodePlaceholder": "Enter invite code (leave blank to generate)",
@@ -31,6 +36,8 @@
"userEmail": "User Email",
"userEmailPlaceholder": "Enter user email"
},
"giftAmount": "Gift Amount",
"inviteCode": "Invite Code",
"referer": "Referer",
"updateSuccess": "Update successful",
"userList": "User List",
+2
View File
@@ -42,6 +42,8 @@
"50002": "El cupón ya ha sido utilizado, no se puede usar nuevamente.",
"60001": "La suscripción ha expirado, por favor renueve para continuar usándola.",
"60002": "No se puede usar la suscripción por el momento, por favor intente más tarde.",
"60003": "Se ha detectado una suscripción existente. Por favor, cancélala antes de continuar.",
"60004": "No se puede eliminar en este momento ya que la suscripción tiene usuarios activos.",
"70001": "El código de verificación es incorrecto, por favor ingréselo nuevamente.",
"80001": "La tarea no se agregó exitosamente a la cola, por favor intente de nuevo más tarde.",
"90001": "Por favor desactive el modo DEBUG e intente nuevamente.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Confirmar",
"edit": "Editar",
"editSecurity": "Editar configuración de seguridad",
"enableRelay": "Habilitar retransmisión",
"enableTLS": "Habilitar TLS",
"encryptionMethod": "Método de encriptación",
"flow": "Algoritmo de control de flujo",
"groupId": "Grupo de Nodo",
"hopInterval": "Intervalo de salto",
"hopPorts": "Puertos de salto",
"hopPortsPlaceholder": "Varios puertos separados por comas",
"name": "Nombre",
"nodeGroupId": "ID del grupo de nodos",
"obfsPassword": "Contraseña de ofuscación",
"obfsPasswordPlaceholder": "Dejar en blanco para no ofuscar",
"path": "Ruta",
@@ -65,7 +64,14 @@
"port": "Puerto del servidor",
"protocol": "Protocolo",
"relayHost": "Dirección de retransmisión",
"relayMode": "Modo de retransmisión",
"relayModeOptions": {
"all": "Todos",
"none": "Ninguno",
"random": "Aleatorio"
},
"relayPort": "Puerto de retransmisión",
"relayPrefix": "Prefijo de retransmisión",
"remarks": "Observaciones",
"security": "Seguridad",
"securityConfig": "Configuración de seguridad",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Seleccionar método de encriptación",
"selectNodeGroup": "Seleccionar grupo de nodos",
"selectProtocol": "Seleccionar protocolo",
"selectRelayMode": "Seleccionar modo de retransmisión",
"serverAddr": "Dirección del servidor",
"serverKey": "Clave del Servidor",
"serverName": "Nombre del servicio",
"speedLimit": "Límite de velocidad",
"speedLimitPlaceholder": "Sin límite",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Porcentaje de descuento",
"discount_price": "Precio con descuento",
"duration": "Duración (meses)",
"groupId": "Grupo de Suscripción",
"inventory": "Inventario",
"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",
"speedLimit": "Límite de velocidad (Mbps)",
"subscribeGroup": "Grupo de suscripción",
"servers": "Servidores",
"speedLimit": "Límite de velocidad ",
"traffic": "Tráfico",
"unitPrice": "Precio unitario",
"unitTime": "Unidad de tiempo"
@@ -83,6 +99,6 @@
"subscribeGroup": "Grupo de suscripción"
},
"traffic": "tráfico",
"unitPrice": "Precio/mes",
"unitPrice": "Precio Unitario",
"updateSuccess": "Actualización exitosa"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Guardado exitosamente"
},
"node": {
"addTimeSlot": "Agregar Franja Horaria",
"communicationKey": "Clave de comunicación",
"communicationKeyDescription": "Clave para la comunicación del nodo, para asegurar que los datos no sean interceptados por otros",
"delete": "Eliminar",
"dynamicMultiplier": "Multiplicador Dinámico",
"dynamicMultiplierDescription": "El Multiplicador Dinámico se refiere al procesamiento de datos enviados con diferentes multiplicadores para diferentes nodos durante distintos períodos de tiempo.",
"endTime": "Hora de Fin",
"inputPlaceholder": "Por favor, ingrese",
"multiplier": "Multiplicador",
"nodePullInterval": "Intervalo de extracción del nodo",
"nodePullIntervalDescription": "Frecuencia con la que el nodo obtiene datos del panel (segundos)",
"nodePushInterval": "Intervalo de envío del nodo",
"nodePushIntervalDescription": "Frecuencia con la que el nodo envía datos al panel",
"saveSuccess": "Guardado exitosamente"
"reset": "Restablecer",
"save": "Guardar",
"saveSuccess": "Guardado exitosamente",
"startTime": "Hora de Inicio",
"timeSlot": "Franja Horaria"
},
"register": {
"emailSuffixWhitelist": "Lista blanca de sufijos de correo electrónico",
+7
View File
@@ -2,6 +2,7 @@
"actions": "acciones",
"balance": "Saldo",
"cancel": "Cancelar",
"commission": "Comisión",
"confirm": "Confirmar",
"confirmDelete": "¿Está seguro de que desea eliminar?",
"create": "Crear",
@@ -19,7 +20,11 @@
"balance": "Saldo",
"balancePlaceholder": "Saldo",
"cancel": "Cancelar",
"commission": "Comisión",
"commissionPlaceholder": "Ingrese la comisión",
"confirm": "Confirmar",
"giftAmount": "Monto del Regalo",
"giftAmountPlaceholder": "Ingrese el monto del regalo",
"invalidEmailFormat": "Formato de correo electrónico no válido",
"inviteCode": "Código de invitación",
"inviteCodePlaceholder": "Por favor, introduzca el código de invitación (déjelo en blanco para generar automáticamente)",
@@ -31,6 +36,8 @@
"userEmail": "Correo electrónico del usuario",
"userEmailPlaceholder": "Por favor, introduzca el correo electrónico del usuario"
},
"giftAmount": "Monto del Regalo",
"inviteCode": "Código de invitación",
"referer": "Recomendador",
"updateSuccess": "Actualización exitosa",
"userList": "Lista de usuarios",
+2
View File
@@ -42,6 +42,8 @@
"50002": "El cupón ya ha sido utilizado, no se puede usar de nuevo.",
"60001": "La suscripción ha expirado, por favor renueva para continuar usando.",
"60002": "No se puede usar la suscripción por el momento, por favor intenta más tarde.",
"60003": "Se ha detectado una suscripción existente. Por favor, cancélala antes de continuar.",
"60004": "No se puede eliminar en este momento ya que la suscripción tiene usuarios activos.",
"70001": "El código de verificación es incorrecto, por favor ingrésalo de nuevo.",
"80001": "La tarea no se agregó exitosamente a la cola, por favor intenta de nuevo más tarde.",
"90001": "Por favor desactiva el modo DEBUG e intenta de nuevo.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Confirmar",
"edit": "Editar",
"editSecurity": "Editar configuración de seguridad",
"enableRelay": "Habilitar retransmisión",
"enableTLS": "Habilitar TLS",
"encryptionMethod": "Método de encriptación",
"flow": "Algoritmo de control de flujo",
"groupId": "Grupo de Nodo",
"hopInterval": "Intervalo de salto",
"hopPorts": "Puertos de salto",
"hopPortsPlaceholder": "Varios puertos separados por comas",
"name": "Nombre",
"nodeGroupId": "ID del grupo de nodos",
"obfsPassword": "Contraseña de ofuscación",
"obfsPasswordPlaceholder": "Dejar en blanco para no ofuscar",
"path": "Ruta",
@@ -65,7 +64,14 @@
"port": "Puerto del servidor",
"protocol": "Protocolo",
"relayHost": "Dirección de retransmisión",
"relayMode": "Modo de retransmisión",
"relayModeOptions": {
"all": "Todos",
"none": "Ninguno",
"random": "Aleatorio"
},
"relayPort": "Puerto de retransmisión",
"relayPrefix": "Prefijo de retransmisión",
"remarks": "Comentarios",
"security": "Seguridad",
"securityConfig": "Configuración de seguridad",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Seleccionar método de encriptación",
"selectNodeGroup": "Seleccionar grupo de nodos",
"selectProtocol": "Seleccionar protocolo",
"selectRelayMode": "Seleccionar modo de retransmisión",
"serverAddr": "Dirección del servidor",
"serverKey": "Clave del Servidor",
"serverName": "Nombre del servicio",
"speedLimit": "Límite de velocidad",
"speedLimitPlaceholder": "Sin límite",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Porcentaje de descuento",
"discount_price": "Precio con descuento",
"duration": "Duración (meses)",
"groupId": "Grupo de Suscripción",
"inventory": "Inventario",
"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",
"speedLimit": "Límite de velocidad (Mbps)",
"subscribeGroup": "Grupo de suscripción",
"servers": "Servidores",
"speedLimit": "Límite de velocidad ",
"traffic": "Tráfico",
"unitPrice": "Precio unitario",
"unitTime": "Unidad de tiempo"
@@ -83,6 +99,6 @@
"subscribeGroup": "Grupo de suscripción"
},
"traffic": "tráfico",
"unitPrice": "Precio/mes",
"unitPrice": "Precio Unitario",
"updateSuccess": "Actualización exitosa"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Guardado exitosamente"
},
"node": {
"addTimeSlot": "Agregar Franja Horaria",
"communicationKey": "Clave de comunicación",
"communicationKeyDescription": "Clave para la comunicación del nodo, para asegurar que los datos no sean interceptados por otros",
"delete": "Eliminar",
"dynamicMultiplier": "Multiplicador Dinámico",
"dynamicMultiplierDescription": "El Multiplicador Dinámico se refiere al procesamiento de datos enviados con diferentes multiplicadores para diferentes nodos durante distintos períodos de tiempo.",
"endTime": "Hora de Fin",
"inputPlaceholder": "Por favor ingrese",
"multiplier": "Multiplicador",
"nodePullInterval": "Intervalo de extracción del nodo",
"nodePullIntervalDescription": "Frecuencia con la que el nodo obtiene datos del panel (segundos)",
"nodePushInterval": "Intervalo de envío del nodo",
"nodePushIntervalDescription": "Frecuencia con la que el nodo envía datos al panel",
"saveSuccess": "Guardado exitosamente"
"reset": "Restablecer",
"save": "Guardar",
"saveSuccess": "Guardado exitosamente",
"startTime": "Hora de Inicio",
"timeSlot": "Franja Horaria"
},
"register": {
"emailSuffixWhitelist": "Lista blanca de sufijos de correo electrónico",
+7
View File
@@ -2,6 +2,7 @@
"actions": "acciones",
"balance": "Saldo",
"cancel": "Cancelar",
"commission": "Comisión",
"confirm": "Confirmar",
"confirmDelete": "¿Está seguro de que desea eliminar?",
"create": "Crear",
@@ -19,7 +20,11 @@
"balance": "Saldo",
"balancePlaceholder": "Saldo",
"cancel": "Cancelar",
"commission": "Comisión",
"commissionPlaceholder": "Ingrese la comisión",
"confirm": "Confirmar",
"giftAmount": "Monto del Regalo",
"giftAmountPlaceholder": "Ingrese el monto del regalo",
"invalidEmailFormat": "Formato de correo electrónico no válido",
"inviteCode": "Código de invitación",
"inviteCodePlaceholder": "Ingrese el código de invitación (déjelo en blanco para generar automáticamente)",
@@ -31,6 +36,8 @@
"userEmail": "Correo electrónico del usuario",
"userEmailPlaceholder": "Ingrese el correo electrónico del usuario"
},
"giftAmount": "Monto del Regalo",
"inviteCode": "Código de Invitación",
"referer": "Recomendador",
"updateSuccess": "Actualización exitosa",
"userList": "Lista de usuarios",
+2
View File
@@ -42,6 +42,8 @@
"50002": "کوپن استفاده شده است، نمی‌توان دوباره استفاده کرد.",
"60001": "اشتراک منقضی شده است، لطفاً قبل از استفاده تمدید کنید.",
"60002": "در حال حاضر نمی‌توان از اشتراک استفاده کرد، لطفاً بعداً دوباره تلاش کنید.",
"60003": "یک اشتراک موجود شناسایی شد. لطفاً قبل از ادامه آن را لغو کنید.",
"60004": "در حال حاضر امکان حذف وجود ندارد زیرا اشتراک دارای کاربران فعال است.",
"70001": "کد تأیید نادرست است، لطفاً دوباره وارد کنید.",
"80001": "وظیفه به‌طور موفقیت‌آمیز در صف قرار نگرفت، لطفاً بعداً دوباره تلاش کنید.",
"90001": "لطفاً حالت DEBUG را غیرفعال کرده و دوباره تلاش کنید.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "تأیید",
"edit": "ویرایش",
"editSecurity": "ویرایش تنظیمات امنیتی",
"enableRelay": "فعال‌سازی رله",
"enableTLS": "فعال‌سازی TLS",
"encryptionMethod": "روش رمزنگاری",
"flow": "الگوریتم کنترل جریان",
"groupId": "گروه نود",
"hopInterval": "فاصله پرش",
"hopPorts": "پورت‌های پرش",
"hopPortsPlaceholder": "پورت‌های متعدد را با کاما جدا کنید",
"name": "نام",
"nodeGroupId": "شناسه گروه گره",
"obfsPassword": "رمز عبور مبهم‌سازی",
"obfsPasswordPlaceholder": "برای عدم مبهم‌سازی خالی بگذارید",
"path": "مسیر",
@@ -65,7 +64,14 @@
"port": "پورت سرور",
"protocol": "پروتکل",
"relayHost": "میزبان رله",
"relayMode": "حالت رله",
"relayModeOptions": {
"all": "همه",
"none": "هیچ‌کدام",
"random": "تصادفی"
},
"relayPort": "پورت رله",
"relayPrefix": "پیشوند رله",
"remarks": "توضیحات",
"security": "امنیت",
"securityConfig": "پیکربندی امنیتی",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "انتخاب روش رمزنگاری",
"selectNodeGroup": "انتخاب گروه گره",
"selectProtocol": "انتخاب پروتکل",
"selectRelayMode": "انتخاب حالت رله",
"serverAddr": "آدرس سرور",
"serverKey": "کلید سرور",
"serverName": "نام سرویس",
"speedLimit": "محدودیت سرعت",
"speedLimitPlaceholder": "نامحدود",
+18 -2
View File
@@ -19,9 +19,14 @@
"Hour": "ساعت",
"Minute": "دقیقه",
"Month": "ماه",
"NoLimit": "بدون محدودیت",
"Year": "سال",
"annualReset": "بازنشانی سالانه",
"basic": "پایه",
"cancel": "لغو",
"confirm": "تأیید",
"deductionRatio": "پیکربندی کسر خودکار/دستی",
"deductionRatioDescription": "برای کسر استفاده می‌شود. به طور پیش‌فرض، سیستم از یک الگوریتم محاسبه خودکار استفاده می‌کند. هنگامی که نسبت دستی ارائه می‌شود، سیستم نسبت‌ها را بر اساس زمان و نسبت ترافیک محاسبه می‌کند و اطمینان حاصل می‌کند که مجموع به ۱۰۰٪ می‌رسد.",
"description": "توضیحات",
"deviceLimit": "محدودیت دستگاه",
"discount": "تخفیف",
@@ -30,17 +35,28 @@
"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": "محدودیت سرعت (مگابیت بر ثانیه)",
"subscribeGroup": "گروه اشتراک",
"traffic": "ترافیک",
"unitPrice": "قیمت واحد",
"unitTime": "واحد زمان"
@@ -83,6 +99,6 @@
"subscribeGroup": "گروه اشتراک"
},
"traffic": "ترافیک",
"unitPrice": "قیمت/ماه",
"unitPrice": "قیمت واحد",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "ذخیره‌سازی موفقیت‌آمیز"
},
"node": {
"addTimeSlot": "افزودن بازه زمانی",
"communicationKey": "کلید ارتباطی",
"communicationKeyDescription": "کلید برای ارتباط گره به منظور اطمینان از امنیت داده‌ها",
"delete": "حذف",
"dynamicMultiplier": "ضریب پویا",
"dynamicMultiplierDescription": "ضریب پویا به پردازش داده‌های ارسال شده با ضرایب مختلف برای گره‌های مختلف در دوره‌های زمانی مختلف اشاره دارد.",
"endTime": "زمان پایان",
"inputPlaceholder": "وارد کنید",
"multiplier": "ضریب",
"nodePullInterval": "فاصله زمانی کشیدن گره",
"nodePullIntervalDescription": "فرکانس (به ثانیه) برای گره‌ها جهت دریافت داده از پنل",
"nodePushInterval": "فاصله زمانی فشار گره",
"nodePushIntervalDescription": "فرکانس برای گره‌ها جهت ارسال داده به پنل",
"saveSuccess": "ذخیره با موفقیت انجام شد"
"reset": "بازنشانی",
"save": "ذخیره",
"saveSuccess": "ذخیره با موفقیت انجام شد",
"startTime": "زمان شروع",
"timeSlot": "بازه زمانی"
},
"register": {
"emailSuffixWhitelist": "لیست سفید پسوند ایمیل",
+7
View File
@@ -2,6 +2,7 @@
"actions": "اقدامات",
"balance": "تعادل",
"cancel": "لغو",
"commission": "کمیسیون",
"confirm": "تأیید",
"confirmDelete": "آیا مطمئن هستید که می‌خواهید حذف کنید؟",
"create": "ایجاد",
@@ -19,7 +20,11 @@
"balance": "موجودی",
"balancePlaceholder": "موجودی",
"cancel": "لغو",
"commission": "کمیسیون",
"commissionPlaceholder": "کمیسیون را وارد کنید",
"confirm": "تأیید",
"giftAmount": "مبلغ هدیه",
"giftAmountPlaceholder": "مبلغ هدیه را وارد کنید",
"invalidEmailFormat": "فرمت ایمیل نامعتبر است",
"inviteCode": "کد دعوت",
"inviteCodePlaceholder": "کد دعوت را وارد کنید (برای تولید خالی بگذارید)",
@@ -31,6 +36,8 @@
"userEmail": "ایمیل کاربر",
"userEmailPlaceholder": "ایمیل کاربر را وارد کنید"
},
"giftAmount": "مقدار هدیه",
"inviteCode": "کد دعوت",
"referer": "ارجاع‌دهنده",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد",
"userList": "فهرست کاربران",
+2
View File
@@ -42,6 +42,8 @@
"50002": "Kuponki on jo käytetty, sitä ei voi käyttää uudelleen.",
"60001": "Tilauksesi on vanhentunut, uusi tilaus ja käytä uudelleen.",
"60002": "Tilausta ei voi käyttää tällä hetkellä, yritä myöhemmin uudelleen.",
"60003": "Olemassa oleva tilaus havaittu. Peruuta se ennen jatkamista.",
"60004": "Ei voi poistaa tällä hetkellä, koska tilauksella on aktiivisia käyttäjiä.",
"70001": "Vahvistuskoodi on virheellinen, syötä se uudelleen.",
"80001": "Tehtävää ei lisätty jonoon, yritä myöhemmin uudelleen.",
"90001": "Sulje DEBUG-tila ja yritä uudelleen.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Vahvista",
"edit": "Muokkaa",
"editSecurity": "Muokkaa suojausasetuksia",
"enableRelay": "Ota välitys käyttöön",
"enableTLS": "Ota TLS käyttöön",
"encryptionMethod": "Salausmenetelmä",
"flow": "Virtausalgoritmi",
"groupId": "Solmu Ryhmä",
"hopInterval": "Hyppyväli",
"hopPorts": "Hyppyportit",
"hopPortsPlaceholder": "Erota useat portit pilkulla",
"name": "Nimi",
"nodeGroupId": "Solmuryhmän ID",
"obfsPassword": "Hämäyssalasana",
"obfsPasswordPlaceholder": "Jätä tyhjäksi, jos ei hämäystä",
"path": "Polku",
@@ -65,7 +64,14 @@
"port": "Palvelinportti",
"protocol": "Protokolla",
"relayHost": "Välityksen osoite",
"relayMode": "Välitystila",
"relayModeOptions": {
"all": "Kaikki",
"none": "Ei mitään",
"random": "Satunnainen"
},
"relayPort": "Välityksen portti",
"relayPrefix": "Välitys etuliite",
"remarks": "Huomautukset",
"security": "Turvallisuus",
"securityConfig": "Turvallisuusasetukset",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Valitse salausmenetelmä",
"selectNodeGroup": "Valitse solmuryhmä",
"selectProtocol": "Valitse protokolla",
"selectRelayMode": "Valitse välitystila",
"serverAddr": "Palvelimen osoite",
"serverKey": "Palvelimen avain",
"serverName": "Palvelimen nimi",
"speedLimit": "Nopeusrajoitus",
"speedLimitPlaceholder": "Ei rajoitusta",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Alennusprosentti",
"discount_price": "Alennettu hinta",
"duration": "Kesto (kuukautta)",
"groupId": "Tilausryhmä",
"inventory": "Varasto",
"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ä",
"speedLimit": "Nopeusrajoitus (Mbps)",
"subscribeGroup": "Tilausryhmä",
"servers": "Palvelimet",
"speedLimit": "Nopeusrajoitus ",
"traffic": "Liikenne",
"unitPrice": "Yksikköhinta",
"unitTime": "Aikayksikkö"
@@ -83,6 +99,6 @@
"subscribeGroup": "Tilaa ryhmä"
},
"traffic": "liikenne",
"unitPrice": "Hinta/kk",
"unitPrice": "Yksikköhinta",
"updateSuccess": "Päivitys onnistui"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Tallennus onnistui"
},
"node": {
"addTimeSlot": "Lisää aikaväli",
"communicationKey": "Viestintäavain",
"communicationKeyDescription": "Solmun viestinnän avain, joka varmistaa, että tiedot eivät joudu muiden sieppaamiksi",
"delete": "Poista",
"dynamicMultiplier": "Dynaaminen Kerroin",
"dynamicMultiplierDescription": "Dynaaminen Kerroin viittaa siihen, että käsitellään siirrettyä dataa eri kertoimilla eri solmuille eri ajanjaksoina.",
"endTime": "Lopetusaika",
"inputPlaceholder": "Ole hyvä ja syötä",
"multiplier": "Kerroin",
"nodePullInterval": "Solmun noutoväli",
"nodePullIntervalDescription": "Kuinka usein solmu hakee tietoja paneelista (sekunteina)",
"nodePushInterval": "Solmun lähetysväli",
"nodePushIntervalDescription": "Kuinka usein solmu lähettää tietoja paneeliin",
"saveSuccess": "Tallennus onnistui"
"reset": "Nollaa",
"save": "Tallenna",
"saveSuccess": "Tallennus onnistui",
"startTime": "Aloitusaika",
"timeSlot": "Aikaväli"
},
"register": {
"emailSuffixWhitelist": "Sähköpostin jälkiliitteen sallittu luettelo",
+7
View File
@@ -2,6 +2,7 @@
"actions": "toiminnot",
"balance": "Saldo",
"cancel": "Peruuta",
"commission": "Komissio",
"confirm": "Vahvista",
"confirmDelete": "Oletko varma, että haluat poistaa?",
"create": "Luo",
@@ -19,7 +20,11 @@
"balance": "Saldo",
"balancePlaceholder": "Saldo",
"cancel": "Peruuta",
"commission": "Komissio",
"commissionPlaceholder": "Syötä komissio",
"confirm": "Vahvista",
"giftAmount": "Lahjan määrä",
"giftAmountPlaceholder": "Syötä lahjan määrä",
"invalidEmailFormat": "Virheellinen sähköpostimuoto",
"inviteCode": "Kutsukoodi",
"inviteCodePlaceholder": "Syötä kutsukoodi (jätä tyhjäksi, jos haluat luoda automaattisesti)",
@@ -31,6 +36,8 @@
"userEmail": "Käyttäjän sähköposti",
"userEmailPlaceholder": "Syötä käyttäjän sähköposti"
},
"giftAmount": "Lahjan määrä",
"inviteCode": "Kutsukoodi",
"referer": "Suosittelija",
"updateSuccess": "Päivitys onnistui",
"userList": "Käyttäjälista",
+2
View File
@@ -42,6 +42,8 @@
"50002": "Ce coupon a déjà été utilisé, il ne peut pas être réutilisé.",
"60001": "L'abonnement a expiré, veuillez le renouveler avant de l'utiliser.",
"60002": "Impossible d'utiliser cet abonnement pour le moment, veuillez réessayer plus tard.",
"60003": "Un abonnement existant a été détecté. Veuillez l'annuler avant de continuer.",
"60004": "Impossible de supprimer pour le moment car l'abonnement a des utilisateurs actifs.",
"70001": "Le code de vérification est incorrect, veuillez le ressaisir.",
"80001": "La tâche n'a pas été ajoutée avec succès à la file d'attente, veuillez réessayer plus tard.",
"90001": "Veuillez désactiver le mode DEBUG et réessayer.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Confirmer",
"edit": "Éditer",
"editSecurity": "Éditer la configuration de sécurité",
"enableRelay": "Activer le relais",
"enableTLS": "Activer TLS",
"encryptionMethod": "Méthode de cryptage",
"flow": "Algorithme de contrôle de flux",
"groupId": "Groupe de nœuds",
"hopInterval": "Intervalle de saut",
"hopPorts": "Ports de saut",
"hopPortsPlaceholder": "Séparer plusieurs ports par des virgules",
"name": "Nom",
"nodeGroupId": "ID du groupe de nœuds",
"obfsPassword": "Mot de passe d'obfuscation",
"obfsPasswordPlaceholder": "Laisser vide pour ne pas obfusquer",
"path": "Chemin",
@@ -65,7 +64,14 @@
"port": "Port de service",
"protocol": "Protocole",
"relayHost": "Adresse de relais",
"relayMode": "Mode relais",
"relayModeOptions": {
"all": "Tous",
"none": "Aucun",
"random": "Aléatoire"
},
"relayPort": "Port de relais",
"relayPrefix": "Préfixe relais",
"remarks": "Remarques",
"security": "Sécurité",
"securityConfig": "Configuration de sécurité",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Sélectionner la méthode de cryptage",
"selectNodeGroup": "Sélectionner le groupe de nœuds",
"selectProtocol": "Sélectionner le protocole",
"selectRelayMode": "Sélectionner le mode relais",
"serverAddr": "Adresse du serveur",
"serverKey": "Clé du serveur",
"serverName": "Nom du service",
"speedLimit": "Limite de vitesse",
"speedLimitPlaceholder": "Illimité",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Pourcentage de remise",
"discount_price": "Prix remisé",
"duration": "Durée (mois)",
"groupId": "Groupe d'abonnement",
"inventory": "Stock",
"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",
"speedLimit": "Limite de vitesse (Mbps)",
"subscribeGroup": "Groupe d'abonnement",
"servers": "Serveurs",
"speedLimit": "Limite de vitesse ",
"traffic": "Trafic",
"unitPrice": "Prix unitaire",
"unitTime": "Unité de temps"
@@ -83,6 +99,6 @@
"subscribeGroup": "Groupe d'abonnement"
},
"traffic": "trafic",
"unitPrice": "Prix/mois",
"unitPrice": "Prix unitaire",
"updateSuccess": "Mise à jour réussie"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Enregistrement réussi"
},
"node": {
"addTimeSlot": "Ajouter un créneau horaire",
"communicationKey": "Clé de communication",
"communicationKeyDescription": "Clé pour la communication du nœud, afin de garantir que les données ne soient pas interceptées par d'autres",
"delete": "Supprimer",
"dynamicMultiplier": "Multiplicateur Dynamique",
"dynamicMultiplierDescription": "Le Multiplicateur Dynamique fait référence au traitement des données poussées avec différents multiplicateurs pour différents nœuds pendant différentes périodes.",
"endTime": "Heure de Fin",
"inputPlaceholder": "Veuillez entrer",
"multiplier": "Multiplicateur",
"nodePullInterval": "Intervalle de récupération du nœud",
"nodePullIntervalDescription": "Fréquence à laquelle le nœud récupère les données du panneau (en secondes)",
"nodePushInterval": "Intervalle de poussée du nœud",
"nodePushIntervalDescription": "Fréquence à laquelle le nœud pousse les données vers le panneau",
"saveSuccess": "Enregistrement réussi"
"reset": "Réinitialiser",
"save": "Enregistrer",
"saveSuccess": "Enregistrement réussi",
"startTime": "Heure de Début",
"timeSlot": "Créneau horaire"
},
"register": {
"emailSuffixWhitelist": "Liste blanche des suffixes d'email",
+7
View File
@@ -2,6 +2,7 @@
"actions": "actions",
"balance": "Solde",
"cancel": "Annuler",
"commission": "Commission",
"confirm": "Confirmer",
"confirmDelete": "Êtes-vous sûr de vouloir supprimer ?",
"create": "Créer",
@@ -19,7 +20,11 @@
"balance": "Solde",
"balancePlaceholder": "Solde",
"cancel": "Annuler",
"commission": "Commission",
"commissionPlaceholder": "Entrez la commission",
"confirm": "Confirmer",
"giftAmount": "Montant du cadeau",
"giftAmountPlaceholder": "Entrez le montant du cadeau",
"invalidEmailFormat": "Format d'e-mail invalide",
"inviteCode": "Code d'invitation",
"inviteCodePlaceholder": "Veuillez entrer le code d'invitation (laissez vide pour générer automatiquement)",
@@ -31,6 +36,8 @@
"userEmail": "E-mail de l'utilisateur",
"userEmailPlaceholder": "Veuillez entrer l'e-mail de l'utilisateur"
},
"giftAmount": "Montant du cadeau",
"inviteCode": "Code d'invitation",
"referer": "Référent",
"updateSuccess": "Mise à jour réussie",
"userList": "Liste des utilisateurs",
+2
View File
@@ -42,6 +42,8 @@
"50002": "यह कूपन पहले ही उपयोग किया जा चुका है, इसे पुनः उपयोग नहीं किया जा सकता।",
"60001": "सदस्यता की समय सीमा समाप्त हो गई है, कृपया नवीनीकरण के बाद उपयोग करें।",
"60002": "अस्थायी रूप से इस सदस्यता का उपयोग नहीं किया जा सकता, कृपया थोड़ी देर बाद पुनः प्रयास करें।",
"60003": "एक मौजूदा सदस्यता का पता चला है। कृपया आगे बढ़ने से पहले इसे रद्द करें।",
"60004": "वर्तमान में हटाने में असमर्थ क्योंकि सदस्यता में सक्रिय उपयोगकर्ता हैं।",
"70001": "सत्यापन कोड गलत है, कृपया पुनः दर्ज करें।",
"80001": "कार्य सफलतापूर्वक कतार में नहीं जोड़ा गया, कृपया थोड़ी देर बाद पुनः प्रयास करें।",
"90001": "कृपया DEBUG मोड बंद करें और फिर पुनः प्रयास करें।",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "पुष्टि करें",
"edit": "संपादित करें",
"editSecurity": "सुरक्षा कॉन्फ़िगरेशन संपादित करें",
"enableRelay": "रिले सक्षम करें",
"enableTLS": "TLS सक्षम करें",
"encryptionMethod": "एन्क्रिप्शन विधि",
"flow": "फ्लो कंट्रोल एल्गोरिदम",
"groupId": "नोड समूह",
"hopInterval": "हॉप अंतराल",
"hopPorts": "हॉप पोर्ट्स",
"hopPortsPlaceholder": "कई पोर्ट्स को कॉमा से अलग करें",
"name": "नाम",
"nodeGroupId": "नोड समूह ID",
"obfsPassword": "ऑबफ्स पासवर्ड",
"obfsPasswordPlaceholder": "खाली छोड़ें तो ऑबफ्स नहीं होगा",
"path": "पथ",
@@ -65,7 +64,14 @@
"port": "सर्वर पोर्ट",
"protocol": "प्रोटोकॉल",
"relayHost": "रिले पता",
"relayMode": "रिले मोड",
"relayModeOptions": {
"all": "सभी",
"none": "कोई नहीं",
"random": "यादृच्छिक"
},
"relayPort": "रिले पोर्ट",
"relayPrefix": "रिले उपसर्ग",
"remarks": "टिप्पणियाँ",
"security": "सुरक्षा",
"securityConfig": "सुरक्षा कॉन्फ़िगरेशन",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "एन्क्रिप्शन विधि चुनें",
"selectNodeGroup": "नोड समूह चुनें",
"selectProtocol": "प्रोटोकॉल चुनें",
"selectRelayMode": "रिले मोड चुनें",
"serverAddr": "सर्वर पता",
"serverKey": "सर्वर कुंजी",
"serverName": "सेवा नाम",
"speedLimit": "गति सीमा",
"speedLimitPlaceholder": "कोई सीमा नहीं",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "घंटा",
"Minute": "मिनट",
"Month": "महीना",
"NoLimit": "कोई सीमा नहीं",
"Year": "वर्ष",
"annualReset": "वार्षिक रीसेट",
"basic": "मूल",
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"deductionRatio": "स्वचालित/मैनुअल कटौती कॉन्फ़िगरेशन",
"deductionRatioDescription": "कटौती के लिए उपयोग किया जाता है। डिफ़ॉल्ट रूप से, सिस्टम एक स्वचालित गणना एल्गोरिदम अपनाता है। जब एक मैनुअल अनुपात प्रदान किया जाता है, तो सिस्टम समय और ट्रैफ़िक अनुपात के आधार पर अनुपात की गणना करता है, यह सुनिश्चित करते हुए कि कुल 100% के बराबर हो।",
"description": "विवरण",
"deviceLimit": "उपकरण सीमा",
"discount": "छूट",
@@ -30,17 +35,28 @@
"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": "सर्वर समूह",
"speedLimit": "गति सीमा (Mbps)",
"subscribeGroup": "सदस्यता समूह",
"servers": "सर्वर",
"speedLimit": "गति सीमा ",
"traffic": "ट्रैफिक",
"unitPrice": "इकाई मूल्य",
"unitTime": "इकाई समय"
@@ -83,6 +99,6 @@
"subscribeGroup": "समूह सदस्यता"
},
"traffic": "ट्रैफिक",
"unitPrice": "मूल्य/माह",
"unitPrice": "इकाई मूल्य",
"updateSuccess": "अपडेट सफल"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "सफलतापूर्वक सहेजा गया"
},
"node": {
"addTimeSlot": "समय स्लॉट जोड़ें",
"communicationKey": "संचार कुंजी",
"communicationKeyDescription": "डेटा को अन्य लोगों द्वारा अवरोधित होने से बचाने के लिए नोड संचार की कुंजी",
"delete": "हटाएं",
"dynamicMultiplier": "डायनामिक मल्टीप्लायर",
"dynamicMultiplierDescription": "डायनामिक मल्टीप्लायर का मतलब है विभिन्न समय अवधियों के दौरान विभिन्न नोड्स के लिए अलग-अलग मल्टीप्लायर के साथ प्रोसेस किए गए डेटा को प्रोसेस करना।",
"endTime": "समाप्ति समय",
"inputPlaceholder": "कृपया दर्ज करें",
"multiplier": "मल्टीप्लायर",
"nodePullInterval": "नोड पुल अंतराल",
"nodePullIntervalDescription": "पैनल से डेटा प्राप्त करने के लिए नोड की आवृत्ति (सेकंड में)",
"nodePushInterval": "नोड पुश अंतराल",
"nodePushIntervalDescription": "नोड द्वारा डेटा को पैनल पर भेजने की आवृत्ति",
"saveSuccess": "सफलतापूर्वक सहेजा गया"
"reset": "रीसेट",
"save": "सहेजें",
"saveSuccess": "सफलतापूर्वक सहेजा गया",
"startTime": "प्रारंभ समय",
"timeSlot": "समय स्लॉट"
},
"register": {
"emailSuffixWhitelist": "ईमेल प्रत्यय श्वेतसूची",
+7
View File
@@ -2,6 +2,7 @@
"actions": "क्रियाएँ",
"balance": "शेष",
"cancel": "रद्द करें",
"commission": "आयोग",
"confirm": "पुष्टि करें",
"confirmDelete": "क्या आप वाकई हटाना चाहते हैं?",
"create": "सृजन",
@@ -19,7 +20,11 @@
"balance": "शेष राशि",
"balancePlaceholder": "शेष राशि",
"cancel": "रद्द करें",
"commission": "कमीशन",
"commissionPlaceholder": "कमीशन दर्ज करें",
"confirm": "पुष्टि करें",
"giftAmount": "उपहार राशि",
"giftAmountPlaceholder": "उपहार राशि दर्ज करें",
"invalidEmailFormat": "अमान्य ईमेल प्रारूप",
"inviteCode": "आमंत्रण कोड",
"inviteCodePlaceholder": "कृपया आमंत्रण कोड दर्ज करें (खाली छोड़ने पर स्वचालित रूप से उत्पन्न होगा)",
@@ -31,6 +36,8 @@
"userEmail": "उपयोगकर्ता ईमेल",
"userEmailPlaceholder": "कृपया उपयोगकर्ता ईमेल दर्ज करें"
},
"giftAmount": "उपहार राशि",
"inviteCode": "आमंत्रण कोड",
"referer": "सिफारिशकर्ता",
"updateSuccess": "अपडेट सफल",
"userList": "उपयोगकर्ता सूची",
+2
View File
@@ -42,6 +42,8 @@
"50002": "A kupon már felhasználásra került, nem használható újra.",
"60001": "Az előfizetés lejárt, kérjük, újítsa meg, majd használja.",
"60002": "Az előfizetés jelenleg nem használható, kérjük, próbálja meg később újra.",
"60003": "Létező előfizetés észlelve. Kérjük, törölje azt a folytatás előtt.",
"60004": "Jelenleg nem törölhető, mivel az előfizetésnek aktív felhasználói vannak.",
"70001": "A megerősítő kód hibás, kérjük, írja be újra.",
"80001": "A feladat nem került sikeresen a sorba, kérjük, próbálja meg később újra.",
"90001": "Kérjük, kapcsolja ki a DEBUG módot, majd próbálja újra.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Megerősít",
"edit": "Szerkesztés",
"editSecurity": "Biztonsági beállítások szerkesztése",
"enableRelay": "Átjátszás engedélyezése",
"enableTLS": "TLS engedélyezése",
"encryptionMethod": "Titkosítási módszer",
"flow": "Áramlásszabályozási algoritmus",
"groupId": "Csomópont csoport",
"hopInterval": "Ugrási intervallum",
"hopPorts": "Ugrási portok",
"hopPortsPlaceholder": "Több portot vesszővel elválasztva",
"name": "Név",
"nodeGroupId": "Csomópont csoport ID",
"obfsPassword": "Zavaró jelszó",
"obfsPasswordPlaceholder": "Hagyja üresen, ha nem zavarosít",
"path": "Útvonal",
@@ -65,7 +64,14 @@
"port": "Szolgáltatási port",
"protocol": "Protokoll",
"relayHost": "Átjátszó cím",
"relayMode": "Relé mód",
"relayModeOptions": {
"all": "Összes",
"none": "Nincs",
"random": "Véletlenszerű"
},
"relayPort": "Átjátszó port",
"relayPrefix": "Relé előtag",
"remarks": "Megjegyzések",
"security": "Biztonság",
"securityConfig": "Biztonsági beállítások",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Válasszon titkosítási módszert",
"selectNodeGroup": "Válasszon csomópont csoportot",
"selectProtocol": "Válasszon protokollt",
"selectRelayMode": "Válassza ki a relé módot",
"serverAddr": "Szerver cím",
"serverKey": "Szerver kulcs",
"serverName": "Szolgáltatás neve",
"speedLimit": "Sebességkorlátozás",
"speedLimitPlaceholder": "Korlátlan",
+19 -3
View File
@@ -19,9 +19,14 @@
"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",
@@ -30,17 +35,28 @@
"discountPercent": "Kedvezmény százalék",
"discount_price": "Kedvezményes ár",
"duration": "Időtartam (hónap)",
"groupId": "Előfizetési csoport",
"inventory": "Készlet",
"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",
"speedLimit": "Sebességkorlát (Mbps)",
"subscribeGroup": "Előfizetési csoport",
"servers": "Szerverek",
"speedLimit": "Sebességkorlát ",
"traffic": "Forgalom",
"unitPrice": "Egységár",
"unitTime": "Időegység"
@@ -83,6 +99,6 @@
"subscribeGroup": "Feliratkozási csoport"
},
"traffic": "forgalom",
"unitPrice": "Ár/hó",
"unitPrice": "Egységár",
"updateSuccess": "Sikeres frissítés"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Sikeres mentés"
},
"node": {
"addTimeSlot": "Időrés hozzáadása",
"communicationKey": "Kommunikációs kulcs",
"communicationKeyDescription": "A csomópontok közötti kommunikáció kulcsa, amely biztosítja, hogy az adatokat ne lehessen elfogni mások által",
"delete": "Törlés",
"dynamicMultiplier": "Dinamikus Szorzó",
"dynamicMultiplierDescription": "A Dinamikus Szorzó arra utal, hogy a különböző csomópontoknál különböző szorzókkal dolgozzák fel a továbbított adatokat különböző időszakokban.",
"endTime": "Befejezési Idő",
"inputPlaceholder": "Kérjük, írja be",
"multiplier": "Szorzó",
"nodePullInterval": "Csomópont lehívási intervallum",
"nodePullIntervalDescription": "A csomópont milyen gyakran kér le adatokat a panelről (másodpercben)",
"nodePushInterval": "Csomópont küldési intervallum",
"nodePushIntervalDescription": "A csomópont milyen gyakran küld adatokat a panelre",
"saveSuccess": "Sikeres mentés"
"reset": "Visszaállítás",
"save": "Mentés",
"saveSuccess": "Sikeres mentés",
"startTime": "Kezdési Idő",
"timeSlot": "Időpont"
},
"register": {
"emailSuffixWhitelist": "E-mail végződés fehérlista",
+7
View File
@@ -2,6 +2,7 @@
"actions": "műveletek",
"balance": "Egyenleg",
"cancel": "Mégse",
"commission": "Jutalék",
"confirm": "Megerősítés",
"confirmDelete": "Biztosan törölni szeretné?",
"create": "Létrehozás",
@@ -19,7 +20,11 @@
"balance": "Egyenleg",
"balancePlaceholder": "Egyenleg",
"cancel": "Mégse",
"commission": "Jutalék",
"commissionPlaceholder": "Adja meg a jutalékot",
"confirm": "Megerősít",
"giftAmount": "Ajándék összege",
"giftAmountPlaceholder": "Adja meg az ajándék összegét",
"invalidEmailFormat": "Érvénytelen e-mail formátum",
"inviteCode": "Meghívókód",
"inviteCodePlaceholder": "Kérjük, adja meg a meghívókódot (ha üres, automatikusan generálódik)",
@@ -31,6 +36,8 @@
"userEmail": "Felhasználói e-mail",
"userEmailPlaceholder": "Kérjük, adja meg a felhasználói e-mail címet"
},
"giftAmount": "Ajándék Összeg",
"inviteCode": "Meghívókód",
"referer": "Ajánló",
"updateSuccess": "Sikeres frissítés",
"userList": "Felhasználói lista",
+2
View File
@@ -42,6 +42,8 @@
"50002": "このクーポンは既に使用されています。再利用できません。",
"60001": "サブスクリプションの有効期限が切れています。更新してからご利用ください。",
"60002": "このサブスクリプションは現在使用できません。しばらくしてから再試行してください。",
"60003": "既存のサブスクリプションが検出されました。続行する前にキャンセルしてください。",
"60004": "サブスクリプションにアクティブなユーザーがいるため、現在削除できません。",
"70001": "認証コードが間違っています。再入力してください。",
"80001": "タスクがキューに正常に追加されませんでした。しばらくしてから再試行してください。",
"90001": "DEBUGモードをオフにしてから再試行してください。",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "確認",
"edit": "編集",
"editSecurity": "セキュリティ設定を編集",
"enableRelay": "リレーを有効化",
"enableTLS": "TLSを有効化",
"encryptionMethod": "暗号化方式",
"flow": "フロー制御アルゴリズム",
"groupId": "ノードグループ",
"hopInterval": "ホップ間隔",
"hopPorts": "ホップポート",
"hopPortsPlaceholder": "複数のポートはカンマで区切る",
"name": "名前",
"nodeGroupId": "ノードグループID",
"obfsPassword": "オブフスケーションパスワード",
"obfsPasswordPlaceholder": "空白の場合はオブフスケーションなし",
"path": "パス",
@@ -65,7 +64,14 @@
"port": "サーバーポート",
"protocol": "プロトコル",
"relayHost": "リレーアドレス",
"relayMode": "リレーモード",
"relayModeOptions": {
"all": "すべて",
"none": "なし",
"random": "ランダム"
},
"relayPort": "リレーポート",
"relayPrefix": "リレープレフィックス",
"remarks": "備考",
"security": "セキュリティ",
"securityConfig": "セキュリティ設定",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "暗号化方式を選択",
"selectNodeGroup": "ノードグループを選択",
"selectProtocol": "プロトコルを選択",
"selectRelayMode": "リレーモードを選択",
"serverAddr": "サーバーアドレス",
"serverKey": "サーバーキー",
"serverName": "サービス名",
"speedLimit": "速度制限",
"speedLimitPlaceholder": "無制限",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "時",
"Minute": "分",
"Month": "月",
"NoLimit": "制限なし",
"Year": "年",
"annualReset": "毎年リセット",
"basic": "基本",
"cancel": "キャンセル",
"confirm": "確認",
"deductionRatio": "自動/手動控除設定",
"deductionRatioDescription": "控除に使用されます。デフォルトでは、システムは自動計算アルゴリズムを採用します。手動比率が提供されると、システムは時間とトラフィックの比率に基づいて割合を計算し、合計が100%になるようにします。",
"description": "説明",
"deviceLimit": "デバイス制限",
"discount": "割引",
@@ -30,17 +35,28 @@
"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": "サーバーグループ",
"speedLimit": "速度制限(Mbps",
"subscribeGroup": "サブスクリプショングループ",
"servers": "サーバー",
"speedLimit": "速度制限",
"traffic": "トラフィック",
"unitPrice": "単価",
"unitTime": "単位時間"
@@ -83,6 +99,6 @@
"subscribeGroup": "購読グループ"
},
"traffic": "トラフィック",
"unitPrice": "価格/月",
"unitPrice": "価",
"updateSuccess": "更新が成功しました"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "保存に成功しました"
},
"node": {
"addTimeSlot": "時間枠を追加",
"communicationKey": "通信キー",
"communicationKeyDescription": "ノード通信のためのキーで、データが他人に傍受されないようにします",
"delete": "削除",
"dynamicMultiplier": "動的乗数",
"dynamicMultiplierDescription": "動的乗数は、異なる時間帯に異なるノードに対して異なる乗数でプッシュされたデータを処理することを指します。",
"endTime": "終了時間",
"inputPlaceholder": "入力してください",
"multiplier": "乗数",
"nodePullInterval": "ノード取得間隔",
"nodePullIntervalDescription": "ノードがパネルからデータを取得する頻度(秒)",
"nodePushInterval": "ノード送信間隔",
"nodePushIntervalDescription": "ノードがデータをパネルに送信する頻度",
"saveSuccess": "保存成功"
"reset": "リセット",
"save": "保存",
"saveSuccess": "保存成功",
"startTime": "開始時間",
"timeSlot": "時間枠"
},
"register": {
"emailSuffixWhitelist": "メールサフィックスホワイトリスト",
+7
View File
@@ -2,6 +2,7 @@
"actions": "アクション",
"balance": "残高",
"cancel": "キャンセル",
"commission": "手数料",
"confirm": "確認",
"confirmDelete": "削除してもよろしいですか?",
"create": "作成",
@@ -19,7 +20,11 @@
"balance": "残高",
"balancePlaceholder": "残高",
"cancel": "キャンセル",
"commission": "手数料",
"commissionPlaceholder": "手数料を入力してください",
"confirm": "確認",
"giftAmount": "ギフト金額",
"giftAmountPlaceholder": "ギフト金額を入力してください",
"invalidEmailFormat": "無効なメール形式",
"inviteCode": "招待コード",
"inviteCodePlaceholder": "招待コードを入力してください(空白の場合は自動生成されます)",
@@ -31,6 +36,8 @@
"userEmail": "ユーザーのメール",
"userEmailPlaceholder": "ユーザーのメールを入力してください"
},
"giftAmount": "ギフト金額",
"inviteCode": "招待コード",
"referer": "推薦者",
"updateSuccess": "更新が成功しました",
"userList": "ユーザーリスト",
+2
View File
@@ -42,6 +42,8 @@
"50002": "해당 쿠폰이 이미 사용되었습니다. 반복 사용할 수 없습니다.",
"60001": "구독이 만료되었습니다. 갱신 후 사용해 주세요.",
"60002": "현재 구독을 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.",
"60003": "기존 구독이 감지되었습니다. 계속하기 전에 취소해 주세요.",
"60004": "구독에 활성 사용자가 있어 현재 삭제할 수 없습니다.",
"70001": "인증 코드가 잘못되었습니다. 다시 입력해 주세요.",
"80001": "작업이 큐에 성공적으로 추가되지 않았습니다. 잠시 후 다시 시도해 주세요.",
"90001": "DEBUG 모드를 끈 후 다시 시도해 주세요.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "확인",
"edit": "편집",
"editSecurity": "보안 설정 편집",
"enableRelay": "중계 활성화",
"enableTLS": "TLS 활성화",
"encryptionMethod": "암호화 방법",
"flow": "흐름 제어 알고리즘",
"groupId": "노드 그룹",
"hopInterval": "홉 간격",
"hopPorts": "홉 포트",
"hopPortsPlaceholder": "여러 포트는 쉼표로 구분",
"name": "이름",
"nodeGroupId": "노드 그룹 ID",
"obfsPassword": "난독화 비밀번호",
"obfsPasswordPlaceholder": "비워두면 난독화 안 함",
"path": "경로",
@@ -65,7 +64,14 @@
"port": "서비스 포트",
"protocol": "프로토콜",
"relayHost": "중계 주소",
"relayMode": "릴레이 모드",
"relayModeOptions": {
"all": "모두",
"none": "없음",
"random": "무작위"
},
"relayPort": "중계 포트",
"relayPrefix": "릴레이 접두사",
"remarks": "비고",
"security": "보안",
"securityConfig": "보안 설정",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "암호화 방법 선택",
"selectNodeGroup": "노드 그룹 선택",
"selectProtocol": "프로토콜 선택",
"selectRelayMode": "릴레이 모드 선택",
"serverAddr": "서버 주소",
"serverKey": "서버 키",
"serverName": "서비스 이름",
"speedLimit": "속도 제한",
"speedLimitPlaceholder": "제한 없음",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "시",
"Minute": "분",
"Month": "월",
"NoLimit": "제한 없음",
"Year": "년",
"annualReset": "연간 초기화",
"basic": "기본",
"cancel": "취소",
"confirm": "확인",
"deductionRatio": "자동/수동 공제 설정",
"deductionRatioDescription": "공제에 사용됩니다. 기본적으로 시스템은 자동 계산 알고리즘을 채택합니다. 수동 비율이 제공되면 시스템은 시간 및 트래픽 비율에 따라 비율을 계산하여 총합이 100%가 되도록 합니다.",
"description": "설명",
"deviceLimit": "기기 제한",
"discount": "할인",
@@ -30,17 +35,28 @@
"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": "서버 그룹",
"speedLimit": "속도 제한 (Mbps)",
"subscribeGroup": "구독 그룹",
"servers": "서버",
"speedLimit": "속도 제한 ",
"traffic": "트래픽",
"unitPrice": "단가",
"unitTime": "단위 시간"
@@ -83,6 +99,6 @@
"subscribeGroup": "구독 그룹"
},
"traffic": "트래픽",
"unitPrice": "가격/월",
"unitPrice": "가",
"updateSuccess": "업데이트 성공"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "저장 성공"
},
"node": {
"addTimeSlot": "시간 슬롯 추가",
"communicationKey": "통신 키",
"communicationKeyDescription": "데이터가 다른 사람에게 가로채이지 않도록 보장하는 노드 통신 키",
"delete": "삭제",
"dynamicMultiplier": "동적 배수",
"dynamicMultiplierDescription": "동적 배수는 서로 다른 시간대에 서로 다른 노드에 대해 다른 배수를 사용하여 처리된 데이터를 의미합니다.",
"endTime": "종료 시간",
"inputPlaceholder": "입력하세요",
"multiplier": "배수",
"nodePullInterval": "노드 가져오기 간격",
"nodePullIntervalDescription": "노드가 패널에서 데이터를 가져오는 빈도(초)",
"nodePushInterval": "노드 푸시 간격",
"nodePushIntervalDescription": "노드가 데이터를 패널로 푸시하는 빈도",
"saveSuccess": "저장 성공"
"reset": "재설정",
"save": "저장",
"saveSuccess": "저장 성공",
"startTime": "시작 시간",
"timeSlot": "시간대"
},
"register": {
"emailSuffixWhitelist": "이메일 접미사 화이트리스트",
+7
View File
@@ -2,6 +2,7 @@
"actions": "작업",
"balance": "잔액",
"cancel": "취소",
"commission": "커미션",
"confirm": "확인",
"confirmDelete": "삭제하시겠습니까?",
"create": "생성",
@@ -19,7 +20,11 @@
"balance": "잔액",
"balancePlaceholder": "잔액",
"cancel": "취소",
"commission": "수수료",
"commissionPlaceholder": "수수료 입력",
"confirm": "확인",
"giftAmount": "선물 금액",
"giftAmountPlaceholder": "선물 금액 입력",
"invalidEmailFormat": "유효하지 않은 이메일 형식",
"inviteCode": "초대 코드",
"inviteCodePlaceholder": "초대 코드를 입력하세요 (비워두면 자동 생성)",
@@ -31,6 +36,8 @@
"userEmail": "사용자 이메일",
"userEmailPlaceholder": "사용자 이메일을 입력하세요"
},
"giftAmount": "선물 금액",
"inviteCode": "초대 코드",
"referer": "추천인",
"updateSuccess": "업데이트 성공",
"userList": "사용자 목록",
+2
View File
@@ -42,6 +42,8 @@
"50002": "Kupongen er allerede brukt og kan ikke brukes igjen.",
"60001": "Abonnementet er utløpt, vennligst forny det før bruk.",
"60002": "Kan for øyeblikket ikke bruke abonnementet, vennligst prøv igjen senere.",
"60003": "Et eksisterende abonnement er oppdaget. Vennligst avbryt det før du fortsetter.",
"60004": "Kan ikke slettes for øyeblikket da abonnementet har aktive brukere.",
"70001": "Verifikasjonskoden er feil, vennligst skriv den inn på nytt.",
"80001": "Oppgaven ble ikke vellykket lagt til i køen, vennligst prøv igjen senere.",
"90001": "Vennligst deaktiver DEBUG-modus og prøv igjen.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Bekreft",
"edit": "Rediger",
"editSecurity": "Rediger sikkerhetskonfigurasjon",
"enableRelay": "Aktiver relé",
"enableTLS": "Aktiver TLS",
"encryptionMethod": "Krypteringsmetode",
"flow": "Flytkontrollalgoritme",
"groupId": "Nodegruppe",
"hopInterval": "Hoppintervall",
"hopPorts": "Hoppporter",
"hopPortsPlaceholder": "Flere porter separeres med komma",
"name": "Navn",
"nodeGroupId": "Nodegruppe-ID",
"obfsPassword": "Forvirringspassord",
"obfsPasswordPlaceholder": "La stå tomt for ingen forvirring",
"path": "Sti",
@@ -65,7 +64,14 @@
"port": "Tjenesteport",
"protocol": "Protokoll",
"relayHost": "Reléadresse",
"relayMode": "Relémodus",
"relayModeOptions": {
"all": "Alle",
"none": "Ingen",
"random": "Tilfeldig"
},
"relayPort": "Reléport",
"relayPrefix": "Reléprefiks",
"remarks": "Merknader",
"security": "Sikkerhet",
"securityConfig": "Sikkerhetskonfigurasjon",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Velg krypteringsmetode",
"selectNodeGroup": "Velg nodegruppe",
"selectProtocol": "Velg protokoll",
"selectRelayMode": "Velg relémodus",
"serverAddr": "Serveradresse",
"serverKey": "Servernøkkel",
"serverName": "Tjenestenavn",
"speedLimit": "Hastighetsbegrensning",
"speedLimitPlaceholder": "Ingen begrensning",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "Time",
"Minute": "Minutt",
"Month": "Måned",
"NoLimit": "Ingen grense",
"Year": "År",
"annualReset": "Årlig Tilbakestilling",
"basic": "Grunnleggende",
"cancel": "Avbryt",
"confirm": "Bekreft",
"deductionRatio": "Automatisk/Manuell Fradragskonfigurasjon",
"deductionRatioDescription": "Brukes for fradrag. Som standard benytter systemet en automatisk beregningsalgoritme. Når en manuell andel er oppgitt, beregner systemet proporsjoner basert på tids- og trafikkforhold, og sikrer at totalen utgjør 100%.",
"description": "Beskrivelse",
"deviceLimit": "Enhetsbegrensning",
"discount": "Rabatt",
@@ -30,17 +35,28 @@
"discountPercent": "Rabattprosent",
"discount_price": "Rabattert pris",
"duration": "Varighet (måneder)",
"groupId": "Abonnementsgruppe",
"inventory": "Lager",
"monthlyReset": "Månedlig Tilbakestilling",
"name": "Navn",
"noLimit": "Ubegrenset",
"noReset": "Ingen Tilbakestilling",
"pricing": "Prissetting",
"purchaseWithDiscount": "Tillat Fradrag",
"purchaseWithDiscountDescription": "Aktiver eller deaktiver funksjonaliteten for avmelding. Etter aktivering vil systemet utføre fradragsbehandling i henhold til de konfigurerte reglene og proporsjonene, og den gjenværende verdien vil bli returnert til saldoen",
"quota": "Kjøpskvote",
"renewalReset": "Fornyelsestilbakestilling",
"renewalResetDescription": "Tilbakestill syklus ved fornyelse",
"replacement": "Erstatningspris (per gang)",
"resetCycle": "Tilbakestill Syklus",
"resetOn1st": "Tilbakestill den 1.",
"selectResetCycle": "Vennligst velg en tilbakestillingssyklus",
"selectSubscribeGroup": "Vennligst velg abonnementsgruppe",
"selectUnitTime": "Vennligst velg enhetstid",
"server": "Tjeneste",
"serverGroup": "Tjenestegruppe",
"speedLimit": "Hastighetsbegrensning (Mbps)",
"subscribeGroup": "Abonnementsgruppe",
"servers": "Servere",
"speedLimit": "Hastighetsbegrensning ",
"traffic": "Trafikk",
"unitPrice": "Enhetspris",
"unitTime": "Enhetstid"
@@ -83,6 +99,6 @@
"subscribeGroup": "Abonner gruppe"
},
"traffic": "trafikk",
"unitPrice": "Pris/måned",
"unitPrice": "Enhetspris",
"updateSuccess": "Oppdatering vellykket"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Lagret vellykket"
},
"node": {
"addTimeSlot": "Legg til tidsluke",
"communicationKey": "Kommunikasjonsnøkkel",
"communicationKeyDescription": "Nøkkelen for kommunikasjon mellom noder, for å sikre at data ikke blir avlyttet av andre",
"delete": "Slett",
"dynamicMultiplier": "Dynamisk Multiplikator",
"dynamicMultiplierDescription": "Dynamisk Multiplikator refererer til behandling av dyttet data med forskjellige multiplikatorer for forskjellige noder i ulike tidsperioder.",
"endTime": "Sluttid",
"inputPlaceholder": "Vennligst skriv inn",
"multiplier": "Multiplikator",
"nodePullInterval": "Node hentingsintervall",
"nodePullIntervalDescription": "Frekvensen (i sekunder) som noden henter data fra panelet",
"nodePushInterval": "Node push-intervall",
"nodePushIntervalDescription": "Frekvensen som noden sender data til panelet",
"saveSuccess": "Lagring vellykket"
"reset": "Tilbakestill",
"save": "Lagre",
"saveSuccess": "Lagring vellykket",
"startTime": "Starttid",
"timeSlot": "Tidsluke"
},
"register": {
"emailSuffixWhitelist": "E-post suffiks hviteliste",
+7
View File
@@ -2,6 +2,7 @@
"actions": "handlinger",
"balance": "Balanse",
"cancel": "Avbryt",
"commission": "Kommisjon",
"confirm": "bekreft",
"confirmDelete": "Er du sikker på at du vil slette?",
"create": "opprett",
@@ -19,7 +20,11 @@
"balance": "Balanse",
"balancePlaceholder": "Balanse",
"cancel": "Avbryt",
"commission": "Provisjon",
"commissionPlaceholder": "Skriv inn provisjon",
"confirm": "Bekreft",
"giftAmount": "Gavebeløp",
"giftAmountPlaceholder": "Skriv inn gavebeløp",
"invalidEmailFormat": "Ugyldig e-postformat",
"inviteCode": "Invitasjonskode",
"inviteCodePlaceholder": "Vennligst skriv inn invitasjonskode (la stå tom for automatisk generering)",
@@ -31,6 +36,8 @@
"userEmail": "Brukerens e-post",
"userEmailPlaceholder": "Vennligst skriv inn brukerens e-post"
},
"giftAmount": "Gavebeløp",
"inviteCode": "Invitasjonskode",
"referer": "Henviser",
"updateSuccess": "Oppdatering vellykket",
"userList": "Brukerliste",
+2
View File
@@ -42,6 +42,8 @@
"50002": "Kupon został już użyty, nie można go użyć ponownie.",
"60001": "Subskrypcja wygasła, odnow ją i użyj ponownie.",
"60002": "Nie można tymczasowo użyć tej subskrypcji, spróbuj ponownie później.",
"60003": "Wykryto istniejącą subskrypcję. Proszę ją anulować przed kontynuacją.",
"60004": "Nie można usunąć w tej chwili, ponieważ subskrypcja ma aktywnych użytkowników.",
"70001": "Kod weryfikacyjny jest nieprawidłowy, wprowadź ponownie.",
"80001": "Zadanie nie zostało pomyślnie dodane do kolejki, spróbuj ponownie później.",
"90001": "Wyłącz tryb DEBUG i spróbuj ponownie.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Potwierdź",
"edit": "Edytuj",
"editSecurity": "Edytuj konfigurację bezpieczeństwa",
"enableRelay": "Włącz przekaźnik",
"enableTLS": "Włącz TLS",
"encryptionMethod": "Metoda szyfrowania",
"flow": "Algorytm kontroli przepływu",
"groupId": "Grupa węzłów",
"hopInterval": "Interwał skoku",
"hopPorts": "Porty skoku",
"hopPortsPlaceholder": "Wiele portów oddziel przecinkami",
"name": "Nazwa",
"nodeGroupId": "ID grupy węzłów",
"obfsPassword": "Hasło zaciemnienia",
"obfsPasswordPlaceholder": "Pozostaw puste, aby nie zaciemniać",
"path": "Ścieżka",
@@ -65,7 +64,14 @@
"port": "Port serwera",
"protocol": "Protokół",
"relayHost": "Adres przekaźnika",
"relayMode": "Tryb przekaźnika",
"relayModeOptions": {
"all": "Wszystkie",
"none": "Brak",
"random": "Losowy"
},
"relayPort": "Port przekaźnika",
"relayPrefix": "Prefiks przekaźnika",
"remarks": "Uwagi",
"security": "Bezpieczeństwo",
"securityConfig": "Konfiguracja bezpieczeństwa",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Wybierz metodę szyfrowania",
"selectNodeGroup": "Wybierz grupę węzłów",
"selectProtocol": "Wybierz protokół",
"selectRelayMode": "Wybierz tryb przekaźnika",
"serverAddr": "Adres serwera",
"serverKey": "Klucz serwera",
"serverName": "Nazwa usługi",
"speedLimit": "Ograniczenie prędkości",
"speedLimitPlaceholder": "Bez ograniczeń",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "Godzina",
"Minute": "Minuta",
"Month": "Miesiąc",
"NoLimit": "Bez ograniczeń",
"Year": "Rok",
"annualReset": "Roczny Reset",
"basic": "Podstawowy",
"cancel": "Anuluj",
"confirm": "Potwierdź",
"deductionRatio": "Automatyczna/Ręczna Konfiguracja Potrąceń",
"deductionRatioDescription": "Używane do potrąceń. Domyślnie system stosuje automatyczny algorytm obliczeniowy. Gdy podany jest ręczny współczynnik, system oblicza proporcje na podstawie czasu i ruchu, zapewniając, że suma wynosi 100%.",
"description": "Opis",
"deviceLimit": "Limit urządzeń",
"discount": "Zniżka",
@@ -30,17 +35,28 @@
"discountPercent": "Procent zniżki",
"discount_price": "Cena po zniżce",
"duration": "Czas trwania (miesiące)",
"groupId": "Grupa subskrypcyjna",
"inventory": "Zapas",
"monthlyReset": "Miesięczny Reset",
"name": "Nazwa",
"noLimit": "Bez ograniczeń",
"noReset": "Brak Resetu",
"pricing": "Cennik",
"purchaseWithDiscount": "Zezwól na Potrącenie",
"purchaseWithDiscountDescription": "Włącz lub wyłącz funkcję rezygnacji z subskrypcji. Po aktywacji system przeprowadzi proces odliczenia zgodnie z skonfigurowanymi zasadami i proporcjami, a pozostała wartość zostanie zwrócona na saldo",
"quota": "Limit zakupu",
"renewalReset": "Reset przy Odnowieniu",
"renewalResetDescription": "Reset cyklu przy odnowieniu",
"replacement": "Cena wymiany (za każdym razem)",
"resetCycle": "Cykl Resetowania",
"resetOn1st": "Reset 1-go",
"selectResetCycle": "Proszę wybrać cykl resetowania",
"selectSubscribeGroup": "Wybierz grupę subskrypcji",
"selectUnitTime": "Proszę wybrać jednostkę czasu",
"server": "Serwer",
"serverGroup": "Grupa serwerów",
"speedLimit": "Limit prędkości (Mbps)",
"subscribeGroup": "Grupa subskrypcji",
"servers": "Serwery",
"speedLimit": "Limit prędkości ",
"traffic": "Ruch",
"unitPrice": "Cena jednostkowa",
"unitTime": "Jednostka czasu"
@@ -83,6 +99,6 @@
"subscribeGroup": "Grupa subskrypcji"
},
"traffic": "ruch",
"unitPrice": "Cena/miesiąc",
"unitPrice": "Cena jednostkowa",
"updateSuccess": "Aktualizacja zakończona pomyślnie"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Zapisano pomyślnie"
},
"node": {
"addTimeSlot": "Dodaj przedział czasowy",
"communicationKey": "Klucz komunikacyjny",
"communicationKeyDescription": "Klucz do komunikacji węzła, aby zapewnić, że dane nie zostaną przechwycone przez inne osoby",
"delete": "Usuń",
"dynamicMultiplier": "Mnożnik dynamiczny",
"dynamicMultiplierDescription": "Mnożnik dynamiczny odnosi się do przetwarzania przesyłanych danych z różnymi mnożnikami dla różnych węzłów w różnych okresach czasu.",
"endTime": "Czas zakończenia",
"inputPlaceholder": "Proszę wprowadzić",
"multiplier": "Mnożnik",
"nodePullInterval": "Interwał pobierania węzła",
"nodePullIntervalDescription": "Częstotliwość, z jaką węzeł pobiera dane z panelu (w sekundach)",
"nodePushInterval": "Interwał wysyłania węzła",
"nodePushIntervalDescription": "Częstotliwość, z jaką węzeł wysyła dane do panelu",
"saveSuccess": "Zapisano pomyślnie"
"reset": "Resetuj",
"save": "Zapisz",
"saveSuccess": "Zapisano pomyślnie",
"startTime": "Czas rozpoczęcia",
"timeSlot": "Przedział czasowy"
},
"register": {
"emailSuffixWhitelist": "Biała lista sufiksów e-mail",
+7
View File
@@ -2,6 +2,7 @@
"actions": "działania",
"balance": "saldo",
"cancel": "Anuluj",
"commission": "Prowizja",
"confirm": "Potwierdź",
"confirmDelete": "Czy na pewno chcesz usunąć?",
"create": "Utwórz",
@@ -19,7 +20,11 @@
"balance": "Saldo",
"balancePlaceholder": "Saldo",
"cancel": "Anuluj",
"commission": "Prowizja",
"commissionPlaceholder": "Wprowadź prowizję",
"confirm": "Potwierdź",
"giftAmount": "Kwota prezentu",
"giftAmountPlaceholder": "Wprowadź kwotę prezentu",
"invalidEmailFormat": "Nieprawidłowy format e-maila",
"inviteCode": "Kod zaproszenia",
"inviteCodePlaceholder": "Wprowadź kod zaproszenia (pozostaw puste, aby wygenerować automatycznie)",
@@ -31,6 +36,8 @@
"userEmail": "E-mail użytkownika",
"userEmailPlaceholder": "Wprowadź e-mail użytkownika"
},
"giftAmount": "Kwota Prezentu",
"inviteCode": "Kod zaproszenia",
"referer": "Polecający",
"updateSuccess": "Aktualizacja zakończona pomyślnie",
"userList": "Lista użytkowników",
+2
View File
@@ -42,6 +42,8 @@
"50002": "O cupom já foi usado, não pode ser reutilizado.",
"60001": "A assinatura expirou, por favor, renove para continuar usando.",
"60002": "Não é possível usar a assinatura no momento, por favor, tente novamente mais tarde.",
"60003": "Uma assinatura existente foi detectada. Cancele-a antes de prosseguir.",
"60004": "Não é possível excluir no momento, pois a assinatura possui usuários ativos.",
"70001": "Código de verificação incorreto, por favor, digite novamente.",
"80001": "A tarefa não foi adicionada à fila com sucesso, por favor, tente novamente mais tarde.",
"90001": "Por favor, desative o modo DEBUG e tente novamente.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Confirmar",
"edit": "Editar",
"editSecurity": "Editar Configuração de Segurança",
"enableRelay": "Habilitar Relay",
"enableTLS": "Habilitar TLS",
"encryptionMethod": "Método de Criptografia",
"flow": "Algoritmo de Controle de Fluxo",
"groupId": "Grupo de Nós",
"hopInterval": "Intervalo de Salto",
"hopPorts": "Portas de Salto",
"hopPortsPlaceholder": "Várias portas separadas por vírgula",
"name": "Nome",
"nodeGroupId": "ID do Grupo de Nós",
"obfsPassword": "Senha de Ofuscação",
"obfsPasswordPlaceholder": "Deixe em branco para não ofuscar",
"path": "Caminho",
@@ -65,7 +64,14 @@
"port": "Porta do Servidor",
"protocol": "Protocolo",
"relayHost": "Endereço de Relay",
"relayMode": "Modo de Retransmissão",
"relayModeOptions": {
"all": "Todos",
"none": "Nenhum",
"random": "Aleatório"
},
"relayPort": "Porta de Relay",
"relayPrefix": "Prefixo de Retransmissão",
"remarks": "Observações",
"security": "Segurança",
"securityConfig": "Configuração de Segurança",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Selecione o Método de Criptografia",
"selectNodeGroup": "Selecione o Grupo de Nós",
"selectProtocol": "Selecione o Protocolo",
"selectRelayMode": "Selecionar Modo de Retransmissão",
"serverAddr": "Endereço do Servidor",
"serverKey": "Chave do Servidor",
"serverName": "Nome do Serviço",
"speedLimit": "Limite de Velocidade",
"speedLimitPlaceholder": "Sem Limite",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "Hora",
"Minute": "Minuto",
"Month": "Mês",
"NoLimit": "Sem Limite",
"Year": "Ano",
"annualReset": "Reinicialização Anual",
"basic": "Básico",
"cancel": "Cancelar",
"confirm": "Confirmar",
"deductionRatio": "Configuração de Dedução Automática/Manual",
"deductionRatioDescription": "Usado para dedução. Por padrão, o sistema adota um algoritmo de cálculo automático. Quando uma proporção manual é fornecida, o sistema calcula proporções com base no tempo e na proporção de tráfego, garantindo que o total seja igual a 100%.",
"description": "Descrição",
"deviceLimit": "Limite de dispositivos",
"discount": "Desconto",
@@ -30,17 +35,28 @@
"discountPercent": "Percentual de desconto",
"discount_price": "Preço com desconto",
"duration": "Duração (meses)",
"groupId": "Grupo de Assinatura",
"inventory": "Estoque",
"monthlyReset": "Reinicialização Mensal",
"name": "Nome",
"noLimit": "Sem limite",
"noReset": "Sem Reinicialização",
"pricing": "Preços",
"purchaseWithDiscount": "Permitir Dedução",
"purchaseWithDiscountDescription": "Ative ou desative a funcionalidade de cancelamento de inscrição. Após a ativação, o sistema realizará o processamento de dedução de acordo com as regras e proporções configuradas, e o valor restante será retornado ao saldo",
"quota": "Quantidade limitada",
"renewalReset": "Reinicialização na Renovação",
"renewalResetDescription": "Reiniciar ciclo ao renovar",
"replacement": "Preço de reposição (cada vez)",
"resetCycle": "Ciclo de Reinicialização",
"resetOn1st": "Reiniciar no dia 1",
"selectResetCycle": "Por favor, selecione um ciclo de reinicialização",
"selectSubscribeGroup": "Por favor, selecione o grupo de assinatura",
"selectUnitTime": "Por favor, selecione a unidade de tempo",
"server": "Servidor",
"serverGroup": "Grupo de servidores",
"speedLimit": "Limite de velocidade (Mbps)",
"subscribeGroup": "Grupo de assinatura",
"servers": "Servidores",
"speedLimit": "Limite de velocidade ",
"traffic": "Tráfego",
"unitPrice": "Preço unitário",
"unitTime": "Unidade de tempo"
@@ -83,6 +99,6 @@
"subscribeGroup": "Grupo de Inscrição"
},
"traffic": "tráfego",
"unitPrice": "Preço/mês",
"unitPrice": "Preço Unitário",
"updateSuccess": "Atualização bem-sucedida"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Salvo com sucesso"
},
"node": {
"addTimeSlot": "Adicionar Faixa de Horário",
"communicationKey": "Chave de Comunicação",
"communicationKeyDescription": "Chave para comunicação do nó, garantindo que os dados não sejam interceptados por terceiros",
"delete": "Excluir",
"dynamicMultiplier": "Multiplicador Dinâmico",
"dynamicMultiplierDescription": "Multiplicador Dinâmico refere-se ao processamento de dados enviados com diferentes multiplicadores para diferentes nós durante diferentes períodos de tempo.",
"endTime": "Hora de Término",
"inputPlaceholder": "Por favor, insira",
"multiplier": "Multiplicador",
"nodePullInterval": "Intervalo de Extração do Nó",
"nodePullIntervalDescription": "Frequência com que o nó obtém dados do painel (segundos)",
"nodePushInterval": "Intervalo de Envio do Nó",
"nodePushIntervalDescription": "Frequência com que o nó envia dados para o painel",
"saveSuccess": "Salvo com sucesso"
"reset": "Redefinir",
"save": "Salvar",
"saveSuccess": "Salvo com sucesso",
"startTime": "Hora de Início",
"timeSlot": "Horário"
},
"register": {
"emailSuffixWhitelist": "Lista branca de sufixos de e-mail",
+7
View File
@@ -2,6 +2,7 @@
"actions": "ações",
"balance": "Saldo",
"cancel": "Cancelar",
"commission": "Comissão",
"confirm": "confirmar",
"confirmDelete": "Você tem certeza de que deseja excluir?",
"create": "Criar",
@@ -19,7 +20,11 @@
"balance": "Saldo",
"balancePlaceholder": "Saldo",
"cancel": "Cancelar",
"commission": "Comissão",
"commissionPlaceholder": "Insira a comissão",
"confirm": "Confirmar",
"giftAmount": "Valor do Presente",
"giftAmountPlaceholder": "Insira o valor do presente",
"invalidEmailFormat": "Formato de e-mail inválido",
"inviteCode": "Código de Convite",
"inviteCodePlaceholder": "Insira o código de convite (deixe em branco para gerar automaticamente)",
@@ -31,6 +36,8 @@
"userEmail": "E-mail do Usuário",
"userEmailPlaceholder": "Insira o e-mail do usuário"
},
"giftAmount": "Valor do Presente",
"inviteCode": "Código de Convite",
"referer": "Referente",
"updateSuccess": "Atualização bem-sucedida",
"userList": "Lista de Usuários",
+2
View File
@@ -42,6 +42,8 @@
"50002": "Acest cupon a fost deja utilizat, nu poate fi folosit din nou.",
"60001": "Abonamentul a expirat, vă rugăm să reînnoiți pentru a continua utilizarea.",
"60002": "Nu se poate utiliza momentan acest abonament, vă rugăm să încercați din nou mai târziu.",
"60003": "A fost detectat un abonament existent. Vă rugăm să-l anulați înainte de a continua.",
"60004": "Nu se poate șterge în acest moment, deoarece abonamentul are utilizatori activi.",
"70001": "Codul de verificare este incorect, vă rugăm să îl introduceți din nou.",
"80001": "Sarcina nu a fost adăugată cu succes în coadă, vă rugăm să încercați din nou mai târziu.",
"90001": "Vă rugăm să dezactivați modul DEBUG și să încercați din nou.",
+10 -2
View File
@@ -49,15 +49,14 @@
"confirm": "Confirmă",
"edit": "Editează",
"editSecurity": "Editează configurația de securitate",
"enableRelay": "Activează retransmisia",
"enableTLS": "Activează TLS",
"encryptionMethod": "Metodă de criptare",
"flow": "Algoritm de control al fluxului",
"groupId": "Grup Nod",
"hopInterval": "Interval de salt",
"hopPorts": "Porturi de salt",
"hopPortsPlaceholder": "Mai multe porturi separate prin virgulă",
"name": "Nume",
"nodeGroupId": "ID grup nod",
"obfsPassword": "Parolă de obfuscare",
"obfsPasswordPlaceholder": "Lasă gol pentru a nu obfusca",
"path": "Cale",
@@ -65,7 +64,14 @@
"port": "Port server",
"protocol": "Protocol",
"relayHost": "Adresă retransmisie",
"relayMode": "Modul de Releu",
"relayModeOptions": {
"all": "Toate",
"none": "Niciunul",
"random": "Aleatoriu"
},
"relayPort": "Port retransmisie",
"relayPrefix": "Prefix de Releu",
"remarks": "Observații",
"security": "Securitate",
"securityConfig": "Configurație de securitate",
@@ -88,7 +94,9 @@
"selectEncryptionMethod": "Selectați metoda de criptare",
"selectNodeGroup": "Selectați grupul de noduri",
"selectProtocol": "Selectați protocolul",
"selectRelayMode": "Selectați Modul de Releu",
"serverAddr": "Adresă server",
"serverKey": "Cheie Server",
"serverName": "Nume serviciu",
"speedLimit": "Limită de viteză",
"speedLimitPlaceholder": "Nelimitat",
+19 -3
View File
@@ -19,9 +19,14 @@
"Hour": "Oră",
"Minute": "Minut",
"Month": "Lună",
"NoLimit": "Fără limită",
"Year": "An",
"annualReset": "Resetare Anuală",
"basic": "De Bază",
"cancel": "Anulează",
"confirm": "Confirmă",
"deductionRatio": "Configurare Deducere Automată/Manuală",
"deductionRatioDescription": "Utilizat pentru deducere. În mod implicit, sistemul adoptă un algoritm de calcul automat. Când se furnizează un raport manual, sistemul calculează proporțiile pe baza timpului și a raportului de trafic, asigurându-se că totalul este egal cu 100%.",
"description": "Descriere",
"deviceLimit": "Limită dispozitive",
"discount": "Reducere",
@@ -30,17 +35,28 @@
"discountPercent": "Procent reducere",
"discount_price": "Preț redus",
"duration": "Durată (luni)",
"groupId": "Grup de Abonament",
"inventory": "Stoc",
"monthlyReset": "Resetare Lunară",
"name": "Nume",
"noLimit": "Fără limită",
"noReset": "Fără Resetare",
"pricing": "Prețuri",
"purchaseWithDiscount": "Permite Deducerea",
"purchaseWithDiscountDescription": "Activează sau dezactivează funcționalitatea de dezabonare. După activare, sistemul va efectua procesarea deducerilor conform regulilor și proporțiilor configurate, iar valoarea rămasă va fi returnată în sold.",
"quota": "Limită de achiziție",
"renewalReset": "Resetare la Reînnoire",
"renewalResetDescription": "Resetează ciclul la reînnoire",
"replacement": "Preț de înlocuire (per dată)",
"resetCycle": "Ciclu de Resetare",
"resetOn1st": "Resetare pe 1",
"selectResetCycle": "Vă rugăm să selectați un ciclu de resetare",
"selectSubscribeGroup": "Vă rugăm să selectați grupul de abonament",
"selectUnitTime": "Vă rugăm să selectați unitatea de timp",
"server": "Server",
"serverGroup": "Grup server",
"speedLimit": "Limită de viteză (Mbps)",
"subscribeGroup": "Grup de abonament",
"servers": "Servere",
"speedLimit": "Limită de viteză ",
"traffic": "Trafic",
"unitPrice": "Preț unitar",
"unitTime": "Unitate de timp"
@@ -83,6 +99,6 @@
"subscribeGroup": "Grup de abonare"
},
"traffic": "trafic",
"unitPrice": "Preț/lună",
"unitPrice": "Preț unitar",
"updateSuccess": "Actualizare reușită"
}
+11 -1
View File
@@ -45,14 +45,24 @@
"saveSuccess": "Salvare reușită"
},
"node": {
"addTimeSlot": "Adaugă Interval Orar",
"communicationKey": "Cheie de comunicare",
"communicationKeyDescription": "Cheia de comunicare a nodului, pentru a asigura că datele nu sunt interceptate de alții",
"delete": "Ștergere",
"dynamicMultiplier": "Multiplicator Dinamic",
"dynamicMultiplierDescription": "Multiplicatorul Dinamic se referă la procesarea datelor transmise cu multiplicatori diferiți pentru noduri diferite în perioade de timp diferite.",
"endTime": "Ora de Sfârșit",
"inputPlaceholder": "Vă rugăm să introduceți",
"multiplier": "Multiplicator",
"nodePullInterval": "Interval de extragere a nodului",
"nodePullIntervalDescription": "Frecvența cu care nodul obține date de la panou (secunde)",
"nodePushInterval": "Interval de împingere a nodului",
"nodePushIntervalDescription": "Frecvența cu care nodul trimite date către panou",
"saveSuccess": "Salvare reușită"
"reset": "Resetare",
"save": "Salvare",
"saveSuccess": "Salvare reușită",
"startTime": "Ora de Începere",
"timeSlot": "Interval de timp"
},
"register": {
"emailSuffixWhitelist": "Lista albă a sufixelor de e-mail",
+7
View File
@@ -2,6 +2,7 @@
"actions": "acțiuni",
"balance": "Sold",
"cancel": "Anulare",
"commission": "Comision",
"confirm": "Confirmare",
"confirmDelete": "Sunteți sigur că doriți să ștergeți?",
"create": "crea",
@@ -19,7 +20,11 @@
"balance": "Sold",
"balancePlaceholder": "Sold",
"cancel": "Anulează",
"commission": "Comision",
"commissionPlaceholder": "Introduceți comisionul",
"confirm": "Confirmă",
"giftAmount": "Sumă Cadou",
"giftAmountPlaceholder": "Introduceți suma cadou",
"invalidEmailFormat": "Format de e-mail invalid",
"inviteCode": "Cod de invitație",
"inviteCodePlaceholder": "Introduceți codul de invitație (lăsați gol pentru generare automată)",
@@ -31,6 +36,8 @@
"userEmail": "E-mail utilizator",
"userEmailPlaceholder": "Introduceți e-mailul utilizatorului"
},
"giftAmount": "Sumă Cadou",
"inviteCode": "Cod de invitație",
"referer": "Referent",
"updateSuccess": "Actualizare reușită",
"userList": "Lista utilizatorilor",

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