dev #3

Merged
jingrow merged 96 commits from dev into main 2026-01-13 22:47:33 +08:00
9 changed files with 139 additions and 77 deletions
Showing only changes of commit e824630632 - Show all commits

View File

@ -19,7 +19,7 @@
variant="outline"
@click="copyTextContentToClipboard"
>
{{ copied ? '已复制' : '复制' }}
{{ copied ? $t('Copied') : $t('Copy') }}
</button>
</div>
</template>
@ -51,7 +51,7 @@ export default {
setTimeout(() => {
this.copied = false;
}, 4000);
toast.success('已复制到剪贴板!');
toast.success(this.$t('Copied to clipboard!'));
});
}
}

View File

@ -11,21 +11,21 @@
class="space-y-4"
>
<AlertBanner
title="如果禁用双重认证,您的账户将变得不安全"
:title="$t('If you disable two-factor authentication, your account will become insecure')"
type="error"
/>
<!-- 用户需要遵循的步骤 -->
<div class="rounded border border-gray-200 bg-gray-50 p-4">
<h3 class="text-lg font-semibold">禁用双重认证的步骤</h3>
<h3 class="text-lg font-semibold">{{ $t('Steps to Disable Two-Factor Authentication') }}</h3>
<ol class="mt-2 list-disc pl-2 text-sm">
<li>打开认证器应用</li>
<li>在下方输入应用中的代码</li>
<li>{{ $t('Open the authenticator app') }}</li>
<li>{{ $t('Enter the code from the app below') }}</li>
</ol>
</div>
<FormControl
label="验证应用中的代码以禁用双重认证"
:label="$t('Verify the code in the app to disable two-factor authentication')"
v-model="totpCode"
/>
</div>
@ -43,14 +43,14 @@
<!-- 用户需要遵循的步骤 -->
<div class="rounded border border-gray-200 bg-gray-50 p-4">
<h3 class="text-lg font-semibold">启用双重认证的步骤</h3>
<h3 class="text-lg font-semibold">{{ $t('Steps to Enable Two-Factor Authentication') }}</h3>
<ol class="ml-1 mt-2 list-disc pl-2 text-sm text-gray-700">
<li>在手机上下载认证器应用例如阿里云APP等</li>
<li>扫描二维码</li>
<li>在下方输入认证器应用中的代码</li>
<li>{{ $t('Download an authenticator app on your phone, such as Alibaba Cloud APP, etc.') }}</li>
<li>{{ $t('Scan the QR code') }}</li>
<li>{{ $t('Enter the code from the authenticator app below') }}</li>
</ol>
<p class="mt-4 text-sm text-gray-700">
<strong>注意</strong> 如果您无法访问认证器应用您的账户将被锁定请确保备份您的保险库/密钥
<strong>{{ $t('Note') }}:</strong> {{ $t('If you cannot access the authenticator app, your account will be locked. Please ensure you back up your vault/key.') }}
</p>
</div>
@ -58,14 +58,14 @@
v-if="showSetupKey"
class="rounded border border-gray-200 bg-gray-50 p-4"
>
<h3 class="text-lg font-semibold">设置密钥</h3>
<h3 class="text-lg font-semibold">{{ $t('Setup Key') }}</h3>
<p class="mt-2 text-sm">
{{ setupKey }}
</p>
</div>
<FormControl
label="验证应用中的代码以启用双重认证"
:label="$t('Verify the code in the app to enable two-factor authentication')"
v-model="totpCode"
/>
</div>
@ -75,7 +75,7 @@
v-if="!is2FAEnabled"
class="w-full"
variant="solid"
label="启用双重认证"
:label="$t('Enable Two-Factor Authentication')"
:disabled="!totpCode"
:loading="$resources.enable2FA.loading"
@click="enable2FA"
@ -84,7 +84,7 @@
v-else
class="w-full"
variant="solid"
label="禁用双重认证"
:label="$t('Disable Two-Factor Authentication')"
:disabled="!totpCode"
:loading="$resources.disable2FA.loading"
@click="disable2FA"
@ -118,7 +118,7 @@ qrUrl: '', // not storing as computed property to avoid re-fetching on dialog cl
totp_code: this.totpCode
}),
{
loading: '正在启用双因素认证...',
loading: this.$t('Enabling two-factor authentication...'),
success: () => {
this.totpCode = '';
@ -128,17 +128,17 @@ qrUrl: '', // not storing as computed property to avoid re-fetching on dialog cl
}, 500);
this.$emit('enabled');
return '双因素认证已成功启用';
return this.$t('Two-factor authentication enabled successfully');
},
error(err) {
if (err.messages) {
if (err.messages.includes('Invalid TOTP code')) {
return '无效的TOTP验证码请重试';
return this.$t('Invalid TOTP code, please try again');
} else {
return err.messages.join('.');
}
} else {
return '启用双因素认证失败';
return this.$t('Failed to enable two-factor authentication');
}
}
}
@ -150,7 +150,7 @@ qrUrl: '', // not storing as computed property to avoid re-fetching on dialog cl
totp_code: this.totpCode
}),
{
loading: '正在禁用双因素认证...',
loading: this.$t('Disabling two-factor authentication...'),
success: () => {
this.totpCode = '';
@ -161,17 +161,17 @@ qrUrl: '', // not storing as computed property to avoid re-fetching on dialog cl
this.$emit('disabled');
return '双因素认证已成功禁用';
return this.$t('Two-factor authentication disabled successfully');
},
error(err) {
if (err.messages) {
if (err.messages.includes('Invalid TOTP code')) {
return '无效的TOTP验证码请重试';
return this.$t('Invalid TOTP code, please try again');
} else {
return err.messages.join('.');
}
} else {
return '禁用双因素认证失败';
return this.$t('Failed to disable two-factor authentication');
}
}
}

View File

@ -1,10 +1,10 @@
<template>
<Dialog
:options="{
title: '添加新Webhook',
title: $t('Add New Webhook'),
actions: [
{
label: '添加Webhook',
label: $t('Add Webhook'),
variant: 'solid',
onClick: addWebhook,
loading: $resources?.addWebhook?.loading
@ -14,9 +14,9 @@
>
<template #body-content>
<div class="space-y-4">
<FormControl label="端点" v-model="endpoint" />
<FormControl :label="$t('Endpoint')" v-model="endpoint" />
<div>
<FormControl label="密钥" v-model="secret">
<FormControl :label="$t('Secret Key')" v-model="secret">
<template #suffix>
<FeatherIcon
class="w-4 cursor-pointer"
@ -26,21 +26,21 @@
</template>
</FormControl>
<p class="mt-2 text-sm text-gray-700">
<strong>注意</strong> 密钥是可选的查看
<strong>{{ $t('Note') }}:</strong> {{ $t('The secret key is optional. View') }}
<a href="https://jingrow.com/docs/webhook-introduction" class="underline" target="_blank"
>文档</a
>{{ $t('documentation') }}</a
>
了解更多
{{ $t('to learn more') }}
</p>
</div>
<p class="text-base font-medium text-gray-900">
选择Webhook事件
{{ $t('Select Webhook Events') }}
</p>
<div
class="text-center text-sm leading-10 text-gray-500"
v-if="$resources.events.loading"
>
加载中...
{{ $t('Loading...') }}
</div>
<div class="mt-6 flex flex-col gap-4" v-else>
<Switch
@ -94,7 +94,7 @@ export default {
events: this.selectedEvents
},
onSuccess() {
toast.success('Webhook添加成功');
toast.success(this.$t('Webhook added successfully'));
this.$emit('success');
}
};
@ -105,25 +105,27 @@ export default {
if (!this.$resources.events.data) return [];
return this.$resources.events.data.map(event => {
// titledescription使
//
if (!event.title) {
if (event.name === 'Site Status Update') {
event.title = '站点状态更新';
} else if (event.name === 'Site Plan Change') {
event.title = '站点套餐变更';
//
const localizedEvent = { ...event };
//
if (localizedEvent.name === 'Site Status Update') {
localizedEvent.title = this.$t('Site Status Update');
localizedEvent.description = this.$t('Pending, Installing, Updating, Active, Inactive, Abnormal, Archived, Paused');
} else if (localizedEvent.name === 'Site Plan Change') {
localizedEvent.title = this.$t('Site Plan Change');
localizedEvent.description = this.$t('Get notifications for site subscription plan changes');
} else {
// title使namedescription使
if (!localizedEvent.title) {
localizedEvent.title = localizedEvent.name;
}
if (!localizedEvent.description) {
localizedEvent.description = '';
}
}
if (!event.description || event.description.includes('Pending') || event.description.includes('Get notified')) {
if (event.name === 'Site Status Update') {
event.description = '等待中、安装中、更新中、活跃、不活跃、异常、已归档、已暂停';
} else if (event.name === 'Site Plan Change') {
event.description = '获取站点套餐变更的通知';
}
}
return event;
return localizedEvent;
});
}
},
@ -151,11 +153,11 @@ export default {
},
addWebhook() {
if (!this.endpoint) {
this.errorMessage = '请提供有效的Webhook端点';
this.errorMessage = this.$t('Please provide a valid webhook endpoint');
return;
}
if (!this.selectedEvents.length) {
this.errorMessage = '请启用至少一个事件';
this.errorMessage = this.$t('Please enable at least one event');
return;
}
this.errorMessage = '';

View File

@ -118,6 +118,10 @@ const listOptions = ref({
autocomplete: 'off',
},
],
primaryAction: {
label: $t('Confirm'),
variant: 'solid'
},
onSuccess({ hide, values }) {
if (values.title) {
return groups.insert.submit(

View File

@ -411,6 +411,10 @@ url: 'jcloud.api.billing.get_unpaid_invoices',
confirmDialog({
title: this.$t('Become a Marketplace Developer?'),
message: this.$t('After confirmation, you will be able to publish apps to our marketplace.'),
primaryAction: {
label: this.$t('Confirm'),
variant: 'solid'
},
onSuccess: ({ hide }) => {
toast.promise(
this.$team.setValue.submit(

View File

@ -1,5 +1,5 @@
<template>
<Dialog v-model="showDialog" :options="{ title: '重置密码' }">
<Dialog v-model="showDialog" :options="{ title: $t('Reset Password') }">
<template #body-content>
<div class="space-y-4">
<div v-if="!isResetMode" class="space-y-4">
@ -7,10 +7,10 @@
v-model="oldPassword"
type="password"
:fieldtype="'Password'"
:label="'当前密码'"
:label="$t('Current Password')"
:fieldname="'old_password'"
:reqd="1"
:placeholder="'请输入当前密码'"
:placeholder="$t('Please enter current password')"
/>
</div>
<div class="space-y-4">
@ -18,10 +18,10 @@
v-model="newPassword"
type="password"
:fieldtype="'Password'"
:label="'新密码'"
:label="$t('New Password')"
:fieldname="'new_password'"
:reqd="1"
:placeholder="'请输入新密码'"
:placeholder="$t('Please enter new password')"
/>
<div v-if="passwordStrengthMessage" class="text-sm" :class="passwordStrengthClass">
{{ passwordStrengthMessage }}
@ -30,10 +30,10 @@
v-model="confirmPassword"
type="password"
:fieldtype="'Password'"
:label="'确认密码'"
:label="$t('Confirm Password')"
:fieldname="'confirm_password'"
:reqd="1"
:placeholder="'请再次输入新密码'"
:placeholder="$t('Please re-enter new password')"
/>
<div v-if="passwordMismatchMessage" class="text-sm text-red-600">
{{ passwordMismatchMessage }}
@ -49,7 +49,7 @@
class="flex-1"
@click="hide"
>
取消
{{ $t('Cancel') }}
</Button>
<Button
variant="solid"
@ -58,7 +58,7 @@
:disabled="!isFormValid"
@click="onConfirm"
>
确认
{{ $t('Confirm') }}
</Button>
</div>
</template>
@ -152,10 +152,10 @@ export default {
checkPasswordMismatch() {
if (this.oldPassword && this.newPassword && this.oldPassword === this.newPassword) {
this.passwordMismatchMessage = '新密码不能与当前密码相同';
this.passwordMismatchMessage = this.$t('New password cannot be the same as current password');
this.passwordStrengthMessage = '';
} else if (this.confirmPassword && this.newPassword !== this.confirmPassword) {
this.passwordMismatchMessage = '两次输入的密码不一致';
this.passwordMismatchMessage = this.$t('Passwords do not match');
this.passwordStrengthMessage = '';
} else {
this.passwordMismatchMessage = '';
@ -178,7 +178,7 @@ export default {
logout_all_sessions: 1
});
} catch (error) {
this.error = error.message || '密码更新失败';
this.error = error.message || this.$t('Failed to update password');
} finally {
this.isLoading = false;
}
@ -186,22 +186,22 @@ export default {
validateForm() {
if (!this.isResetMode && !this.oldPassword) {
this.error = '请输入当前密码';
this.error = this.$t('Please enter current password');
return false;
}
if (!this.newPassword) {
this.error = '请输入新密码';
this.error = this.$t('Please enter new password');
return false;
}
if (this.newPassword !== this.confirmPassword) {
this.error = '两次输入的密码不一致';
this.error = this.$t('Passwords do not match');
return false;
}
if (!this.isResetMode && this.oldPassword === this.newPassword) {
this.error = '新密码不能与当前密码相同';
this.error = this.$t('New password cannot be the same as current password');
return false;
}
@ -247,7 +247,7 @@ export default {
const feedback = data.message.feedback;
if (feedback.password_policy_validation_passed) {
this.passwordStrengthMessage = '密码强度良好 👍';
this.passwordStrengthMessage = this.$t('Password strength is good 👍');
this.passwordStrengthClass = 'text-green-600';
} else {
let message = [];
@ -256,7 +256,7 @@ export default {
} else if (feedback.warning) {
message.push(feedback.warning);
}
message.push('提示:密码应包含符号、数字和大写字母');
message.push(this.$t('Tip: Password should contain symbols, numbers and uppercase letters'));
this.passwordStrengthMessage = message.join(' ');
this.passwordStrengthClass = 'text-red-600';
}
@ -273,9 +273,9 @@ export default {
url: 'jingrow.core.pagetype.user.user.update_password',
onSuccess(data) {
// 5
toast.success('密码更新成功', {
toast.success(this.$t('Password updated successfully'), {
duration: 3000,
description: '您的密码已更新'
description: this.$t('Your password has been updated')
});
//
@ -290,9 +290,9 @@ export default {
},
onError(error) {
if (error.status === 401) {
this.error = '当前密码不正确';
this.error = this.$t('Current password is incorrect');
} else {
this.error = error.message || '密码更新失败';
this.error = error.message || this.$t('Failed to update password');
}
}
};

View File

@ -3,8 +3,8 @@
v-model="show"
:options="{
title: is2FAEnabled
? '禁用双因素认证'
: '启用双因素认证'
? $t('Disable Two-Factor Authentication')
: $t('Enable Two-Factor Authentication')
}"
>
<template #body-content>

View File

@ -81,7 +81,7 @@ export default {
computed: {
primaryActionProps() {
return {
label: '确认',
label: this.$t('Confirm'),
variant: 'solid',
...this.primaryAction,
loading: this.isLoading,

View File

@ -978,3 +978,55 @@ Default,默认,
Release Group,发布组,
Note,注意,
Submit,提交,
Copy,复制,
Copied,已复制,
Copied to clipboard!,已复制到剪贴板!,
Confirm,确认,
Current Password,当前密码,
Please enter current password,请输入当前密码,
New Password,新密码,
Please enter new password,请输入新密码,
Confirm Password,确认密码,
Please re-enter new password,请再次输入新密码,
New password cannot be the same as current password,新密码不能与当前密码相同,
Passwords do not match,两次输入的密码不一致,
Failed to update password,密码更新失败,
Password strength is good 👍,密码强度良好 👍,
Tip: Password should contain symbols, numbers and uppercase letters,提示:密码应包含符号、数字和大写字母,
Password updated successfully,密码更新成功,
Your password has been updated,您的密码已更新,
Current password is incorrect,当前密码不正确,
Cancel,取消,
Add New Webhook,添加新Webhook,
Secret Key,密钥,
The secret key is optional. View,密钥是可选的。查看,
documentation,文档,
to learn more,了解更多,
Select Webhook Events,选择Webhook事件,
Loading...,加载中...,
Webhook added successfully,Webhook添加成功,
Site Status Update,站点状态更新,
Site Plan Change,站点套餐变更,
Pending, Installing, Updating, Active, Inactive, Abnormal, Archived, Paused,等待中、安装中、更新中、活跃、不活跃、异常、已归档、已暂停,
Get notifications for site subscription plan changes,获取站点套餐变更的通知,
Please provide a valid webhook endpoint,请提供有效的Webhook端点,
Please enable at least one event,请启用至少一个事件,
If you disable two-factor authentication, your account will become insecure,如果禁用双重认证,您的账户将变得不安全,
Steps to Disable Two-Factor Authentication,禁用双重认证的步骤,
Open the authenticator app,打开认证器应用,
Enter the code from the app below,在下方输入应用中的代码,
Verify the code in the app to disable two-factor authentication,验证应用中的代码以禁用双重认证,
Steps to Enable Two-Factor Authentication,启用双重认证的步骤,
Download an authenticator app on your phone, such as Alibaba Cloud APP, etc.,在手机上下载认证器应用例如阿里云APP等。,
Scan the QR code,扫描二维码,
Enter the code from the authenticator app below,在下方输入认证器应用中的代码,
If you cannot access the authenticator app, your account will be locked. Please ensure you back up your vault/key.,如果您无法访问认证器应用,您的账户将被锁定。请确保备份您的保险库/密钥。,
Setup Key,设置密钥,
Verify the code in the app to enable two-factor authentication,验证应用中的代码以启用双重认证,
Enabling two-factor authentication...,正在启用双因素认证...,
Two-factor authentication enabled successfully,双因素认证已成功启用,
Invalid TOTP code, please try again,无效的TOTP验证码请重试,
Failed to enable two-factor authentication,启用双因素认证失败,
Disabling two-factor authentication...,正在禁用双因素认证...,
Two-factor authentication disabled successfully,双因素认证已成功禁用,
Failed to disable two-factor authentication,禁用双因素认证失败,

Can't render this file because it has a wrong number of fields in line 390.