diff --git a/dashboard/.eslintrc.js b/dashboard/.eslintrc.cjs
similarity index 100%
rename from dashboard/.eslintrc.js
rename to dashboard/.eslintrc.cjs
diff --git a/dashboard/README.md b/dashboard/README.md
index 8713190..782e1f8 100644
--- a/dashboard/README.md
+++ b/dashboard/README.md
@@ -1,6 +1,6 @@
# Dashboard
-Dashboard is a VueJS application that is the face of 今果 Jingrow. This is what the end users (tenants) see and manage their FC stuff in. The tenants does not have access to the desk, so, this is their dashboard for managing sites, apps, updates etc.
+Dashboard is a VueJS application that is the face of Jingrow. This is what the end users (tenants) see and manage their FC stuff in. The tenants does not have access to the desk, so, this is their dashboard for managing sites, apps, updates etc.
Technologies at the heart of dashboard:
diff --git a/dashboard/index.html b/dashboard/index.html
index a95bde5..d1ab8e5 100644
--- a/dashboard/index.html
+++ b/dashboard/index.html
@@ -1,17 +1,17 @@
-
+
+ {{ $t('You are not logged in.') }}
+ {{ $t('Login') }} {{ $t('to access dashboard.') }}
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
-
+
+
+
diff --git a/dashboard/src2/components/ActionButton.vue b/dashboard/src/components/ActionButton.vue
similarity index 100%
rename from dashboard/src2/components/ActionButton.vue
rename to dashboard/src/components/ActionButton.vue
diff --git a/dashboard/src2/components/ActiveServersDialog.vue b/dashboard/src/components/ActiveServersDialog.vue
similarity index 100%
rename from dashboard/src2/components/ActiveServersDialog.vue
rename to dashboard/src/components/ActiveServersDialog.vue
diff --git a/dashboard/src2/components/AddDomainDialog.vue b/dashboard/src/components/AddDomainDialog.vue
similarity index 100%
rename from dashboard/src2/components/AddDomainDialog.vue
rename to dashboard/src/components/AddDomainDialog.vue
diff --git a/dashboard/src2/components/AddTagDialog.vue b/dashboard/src/components/AddTagDialog.vue
similarity index 100%
rename from dashboard/src2/components/AddTagDialog.vue
rename to dashboard/src/components/AddTagDialog.vue
diff --git a/dashboard/src2/components/AddressForm.vue b/dashboard/src/components/AddressForm.vue
similarity index 100%
rename from dashboard/src2/components/AddressForm.vue
rename to dashboard/src/components/AddressForm.vue
diff --git a/dashboard/src2/components/AddressableErrorDialog.vue b/dashboard/src/components/AddressableErrorDialog.vue
similarity index 100%
rename from dashboard/src2/components/AddressableErrorDialog.vue
rename to dashboard/src/components/AddressableErrorDialog.vue
diff --git a/dashboard/src2/components/AlertAddPaymentMode.vue b/dashboard/src/components/AlertAddPaymentMode.vue
similarity index 100%
rename from dashboard/src2/components/AlertAddPaymentMode.vue
rename to dashboard/src/components/AlertAddPaymentMode.vue
diff --git a/dashboard/src2/components/AlertAddressDetails.vue b/dashboard/src/components/AlertAddressDetails.vue
similarity index 84%
rename from dashboard/src2/components/AlertAddressDetails.vue
rename to dashboard/src/components/AlertAddressDetails.vue
index ff039d9..119f493 100644
--- a/dashboard/src2/components/AlertAddressDetails.vue
+++ b/dashboard/src/components/AlertAddressDetails.vue
@@ -1,7 +1,7 @@
- 您的订阅已确认。
- 如果您的任何站点已被禁用,它很快就会重新启用。
+ {{ $t('Your subscription has been confirmed.') }}
+ {{ $t('If any of your sites have been disabled, they will be re-enabled soon.') }}
@@ -258,7 +258,7 @@ SitePlansCards: defineAsyncComponent(() => import('./SitePlansCards.vue')),
import('./UpdateBillingDetailsForm.vue')
),
CardWithDetails: defineAsyncComponent(() =>
- import('../../src/components/CardWithDetails.vue')
+ import('@/components/CardWithDetails.vue')
),
BuyPrepaidCreditsForm: defineAsyncComponent(() =>
import('./BuyPrepaidCreditsForm.vue')
@@ -293,7 +293,7 @@ SitePlansCards: defineAsyncComponent(() => import('./SitePlansCards.vue')),
methods: {
confirmPlan() {
if (!this.selectedPlan) {
- toast.error('请选择一个计划');
+ toast.error(this.$t('Please select a plan'));
return;
}
this.step = 2;
@@ -338,7 +338,7 @@ SitePlansCards: defineAsyncComponent(() => import('./SitePlansCards.vue')),
},
onError: () => {
this.isChangingPlan = false;
- toast.error('更改计划失败,请稍后重试。');
+ toast.error(this.$t('Failed to change plan, please try again later.'));
this.showDialog = false;
}
});
diff --git a/dashboard/src2/components/Autocomplete.vue b/dashboard/src/components/Autocomplete.vue
similarity index 100%
rename from dashboard/src2/components/Autocomplete.vue
rename to dashboard/src/components/Autocomplete.vue
diff --git a/dashboard/src2/components/AvatarGroup.vue b/dashboard/src/components/AvatarGroup.vue
similarity index 100%
rename from dashboard/src2/components/AvatarGroup.vue
rename to dashboard/src/components/AvatarGroup.vue
diff --git a/dashboard/src/components/BackupFilesUploader.vue b/dashboard/src/components/BackupFilesUploader.vue
index c403b58..0130ab8 100644
--- a/dashboard/src/components/BackupFilesUploader.vue
+++ b/dashboard/src/components/BackupFilesUploader.vue
@@ -29,26 +29,26 @@
class="text-base"
:class="error ? 'text-red-500' : 'text-gray-600'"
>
- {{
- uploading
- ? `上传中 ${progress}%`
- : success
- ? formatBytes(fileObj.size)
- : error
- ? error
- : file.description
- }}
+ {{
+ uploading
+ ? $t('Uploading {progress}%', { progress })
+ : success
+ ? formatBytes(fileObj.size)
+ : error
+ ? error
+ : file.description
+ }}
-
- 上传
-
+
+ {{ $t('Upload') }}
+
@@ -72,36 +72,32 @@ export default {
icon: '',
type: 'database',
ext: 'application/x-gzip,application/sql,.sql',
- title: '数据库备份',
- description:
- '上传数据库备份文件。通常文件名以 .sql.gz 或 .sql 结尾',
+ title: this.$t('Database Backup'),
+ description: this.$t('Upload database backup file. Usually the filename ends with .sql.gz or .sql'),
file: null
},
{
icon: '',
type: 'public',
ext: 'application/x-tar',
- title: '公共文件',
- description:
- '上传公共文件备份。通常文件名以 -files.tar 结尾',
+ title: this.$t('Public Files'),
+ description: this.$t('Upload public files backup. Usually the filename ends with -files.tar'),
file: null
},
{
icon: '',
type: 'private',
ext: 'application/x-tar',
- title: '私有文件',
- description:
- '上传私有文件备份。通常文件名以 -private-files.tar 结尾',
+ title: this.$t('Private Files'),
+ description: this.$t('Upload private files backup. Usually the filename ends with -private-files.tar'),
file: null
},
{
icon: '',
type: 'config',
ext: 'application/json',
- title: '站点配置(如备份已加密则必需)',
- description:
- '上传站点配置文件。通常文件名以 -site_config_backup.json 结尾',
+ title: this.$t('Site Config (required if backup is encrypted)'),
+ description: this.$t('Upload site config file. Usually the filename ends with -site_config_backup.json'),
file: null
}
]
@@ -118,7 +114,7 @@ export default {
// valid strings are "database.sql.gz", "database.sql", "database.sql (1).gz", "database.sql (2).gz"
if (!/\.sql( \(\d\))?\.gz$|\.sql$/.test(file.name)) {
throw new Error(
- '数据库备份文件应以"database.sql.gz"或"database.sql"结尾'
+ this.$t('Database backup file should end with "database.sql.gz" or "database.sql"')
);
}
if (
@@ -128,17 +124,18 @@ export default {
'application/sql'
].includes(file.type)
) {
- throw new Error('无效的数据库备份文件');
+ throw new Error(this.$t('Invalid database backup file'));
}
}
if (['public', 'private'].includes(type)) {
if (file.type != 'application/x-tar') {
- throw new Error(`无效的${type === 'public' ? '公共' : '私有'}文件备份文件`);
+ const fileType = type === 'public' ? this.$t('public') : this.$t('private');
+ throw new Error(this.$t('Invalid {fileType} files backup file', { fileType }));
}
}
if (type === 'config') {
if (file.type != 'application/json') {
- throw new Error(`无效的站点配置文件`);
+ throw new Error(this.$t('Invalid site config file'));
}
}
}
diff --git a/dashboard/src2/components/BuyPrepaidCreditsAlipay.vue b/dashboard/src/components/BuyPrepaidCreditsAlipay.vue
similarity index 79%
rename from dashboard/src2/components/BuyPrepaidCreditsAlipay.vue
rename to dashboard/src/components/BuyPrepaidCreditsAlipay.vue
index 37ea8e0..8ad43ed 100644
--- a/dashboard/src2/components/BuyPrepaidCreditsAlipay.vue
+++ b/dashboard/src/components/BuyPrepaidCreditsAlipay.vue
@@ -11,7 +11,7 @@
:loading="$resources.createAlipayOrder.loading || loading"
@click="processAlipayPayment"
>
- 使用支付宝支付
+ {{ $t('Pay with Alipay') }}
@@ -49,18 +49,18 @@ export default {
},
validate() {
if (this.amount <= 0) {
- throw new DashboardError('支付金额必须大于0');
+ throw new DashboardError(this.$t('Payment amount must be greater than 0'));
}
if (this.amount < this.minimumAmount) {
- throw new DashboardError('金额低于最低要求金额');
+ throw new DashboardError(this.$t('Amount is below the minimum required amount'));
}
},
onSuccess(response) {
window.open(response.payment_url, '_blank');
- toast.success('支付页面已在新窗口打开');
+ toast.success(this.$t('Payment page opened in new window'));
- // 如果需要检查支付状态
+ // Optional: check payment status
// this.checkPaymentStatus(response.order_id);
}
};
@@ -71,7 +71,7 @@ export default {
this.$resources.createAlipayOrder.submit();
},
- // 可选:检查支付状态的方法
+ // Optional: method to check payment status
checkPaymentStatus(orderId) {
const checkInterval = setInterval(() => {
this.$call('jcloud.api.billing.check_payment_status', {
@@ -80,15 +80,15 @@ export default {
}).then(result => {
if (result && result.status === 'Success') {
clearInterval(checkInterval);
- toast.success('支付成功!账户已充值');
+ toast.success(this.$t('Payment successful! Account has been recharged'));
this.$emit('payment-success');
}
}).catch(err => {
- console.error('检查支付状态出错:', err);
+ console.error('Error checking payment status:', err);
});
}, 3000);
- // 5分钟后停止检查
+ // Stop checking after 5 minutes
setTimeout(() => {
clearInterval(checkInterval);
}, 300000);
diff --git a/dashboard/src/components/BuyPrepaidCreditsForm.vue b/dashboard/src/components/BuyPrepaidCreditsForm.vue
new file mode 100644
index 0000000..6a19eac
--- /dev/null
+++ b/dashboard/src/components/BuyPrepaidCreditsForm.vue
@@ -0,0 +1,388 @@
+
+
+
+
+
+ {{ $team.pg.currency === 'CNY' ? '¥' : '$' }}
+
+
+
+
+
+
+
{{ $t('Payment Method') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('Pay with {method}, fast and convenient. Balance will be credited immediately after successful payment.', { method: paymentGateway === 'Alipay' ? $t('Alipay') : paymentGateway === 'WeChatPay' ? $t('WeChat Pay') : paymentGateway === 'Stripe' ? $t('Stripe') : $t('PayPal') }) }}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dashboard/src/components/BuyPrepaidCreditsPayPal.vue b/dashboard/src/components/BuyPrepaidCreditsPayPal.vue
new file mode 100644
index 0000000..4041ac0
--- /dev/null
+++ b/dashboard/src/components/BuyPrepaidCreditsPayPal.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+ {{ $t('Pay with PayPal') }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dashboard/src2/components/BuyPrepaidCreditsRazorpay.vue b/dashboard/src/components/BuyPrepaidCreditsRazorpay.vue
similarity index 95%
rename from dashboard/src2/components/BuyPrepaidCreditsRazorpay.vue
rename to dashboard/src/components/BuyPrepaidCreditsRazorpay.vue
index b1b3f10..1796119 100644
--- a/dashboard/src2/components/BuyPrepaidCreditsRazorpay.vue
+++ b/dashboard/src/components/BuyPrepaidCreditsRazorpay.vue
@@ -91,7 +91,7 @@ export default {
const options = {
key: data.key_id,
order_id: data.order_id,
- name: '今果 Jingrow',
+ name: 'Jingrow',
image: '/assets/jcloud/images/jingrow-cloud-logo.png',
prefill: {
email: this.$team.pg.user
diff --git a/dashboard/src2/components/BuyPrepaidCreditsStripe.vue b/dashboard/src/components/BuyPrepaidCreditsStripe.vue
similarity index 100%
rename from dashboard/src2/components/BuyPrepaidCreditsStripe.vue
rename to dashboard/src/components/BuyPrepaidCreditsStripe.vue
diff --git a/dashboard/src2/components/BuyPrepaidCreditsWeChatPay.vue b/dashboard/src/components/BuyPrepaidCreditsWeChatPay.vue
similarity index 83%
rename from dashboard/src2/components/BuyPrepaidCreditsWeChatPay.vue
rename to dashboard/src/components/BuyPrepaidCreditsWeChatPay.vue
index 517b442..ca4d575 100644
--- a/dashboard/src2/components/BuyPrepaidCreditsWeChatPay.vue
+++ b/dashboard/src/components/BuyPrepaidCreditsWeChatPay.vue
@@ -11,11 +11,11 @@
:loading="$resources.createWeChatPayOrder.loading || loading"
@click="processWeChatPayment"
>
- 使用微信支付
+ {{ $t('Pay with WeChat Pay') }}
-
+
@@ -31,20 +31,20 @@
-
扫一扫付款(元)
-
{{ amount }} 元
+
{{ $t('Scan to Pay (CNY)') }}
+
{{ amount }} {{ $t('CNY') }}
-
+
-
请使用微信扫描二维码完成支付
-
二维码有效期 15 分钟
+
{{ $t('Please scan the QR code with WeChat to complete payment') }}
+
{{ $t('QR code valid for 15 minutes') }}
@@ -55,7 +55,7 @@
+
\ No newline at end of file
diff --git a/dashboard/src2/components/ConfigEditorDialog.vue b/dashboard/src/components/ConfigEditorDialog.vue
similarity index 100%
rename from dashboard/src2/components/ConfigEditorDialog.vue
rename to dashboard/src/components/ConfigEditorDialog.vue
diff --git a/dashboard/src2/components/ConfigPreviewDialog.vue b/dashboard/src/components/ConfigPreviewDialog.vue
similarity index 100%
rename from dashboard/src2/components/ConfigPreviewDialog.vue
rename to dashboard/src/components/ConfigPreviewDialog.vue
diff --git a/dashboard/src2/components/DateTimeControl.vue b/dashboard/src/components/DateTimeControl.vue
similarity index 100%
rename from dashboard/src2/components/DateTimeControl.vue
rename to dashboard/src/components/DateTimeControl.vue
diff --git a/dashboard/src2/components/DialogWrapper.vue b/dashboard/src/components/DialogWrapper.vue
similarity index 100%
rename from dashboard/src2/components/DialogWrapper.vue
rename to dashboard/src/components/DialogWrapper.vue
diff --git a/dashboard/src2/components/DismissableBanner.vue b/dashboard/src/components/DismissableBanner.vue
similarity index 100%
rename from dashboard/src2/components/DismissableBanner.vue
rename to dashboard/src/components/DismissableBanner.vue
diff --git a/dashboard/src2/components/DomainOwner.vue b/dashboard/src/components/DomainOwner.vue
similarity index 84%
rename from dashboard/src2/components/DomainOwner.vue
rename to dashboard/src/components/DomainOwner.vue
index 337ad53..ec561c2 100644
--- a/dashboard/src2/components/DomainOwner.vue
+++ b/dashboard/src/components/DomainOwner.vue
@@ -6,7 +6,7 @@
@@ -559,29 +559,29 @@ export default {
// 获取实名认证状态文本
getRealNameStatusText(status) {
if (!status || status === '') {
- return '未实名认证';
+ return this.$t('Not Real-name Verified');
}
// 根据r_status字段判断实名认证状态
// 0: 未实名, 1: 实名成功, 2: 实名中, 3: 实名失败, 4: 认证过期, 5: 待审核
const statusMap = {
- '0': '未实名认证',
- '1': '已实名认证',
- '2': '实名认证中',
- '3': '实名认证失败',
- '4': '实名认证过期',
- '5': '待审核'
+ '0': this.$t('Not Real-name Verified'),
+ '1': this.$t('Real-name Verified'),
+ '2': this.$t('Real-name Verification in Progress'),
+ '3': this.$t('Real-name Verification Failed'),
+ '4': this.$t('Real-name Verification Expired'),
+ '5': this.$t('Pending Review')
};
- return statusMap[status] || '未实名认证';
+ return statusMap[status] || this.$t('Not Real-name Verified');
},
// 获取所有者类型文本
getOwnerTypeText(type) {
- if (!type || type === '') return '未知';
+ if (!type || type === '') return this.$t('Unknown');
const typeMap = {
- 'I': '个人',
- 'E': '企业/组织'
+ 'I': this.$t('Individual'),
+ 'E': this.$t('Enterprise/Organization')
};
- return typeMap[type] || '未知';
+ return typeMap[type] || this.$t('Unknown');
},
// 获取地址信息
@@ -597,25 +597,25 @@ export default {
getCertificateTypeName(type) {
const typeMap = {
// 字符串格式映射
- 'SFZ': '身份证',
- 'HZ': '护照',
- 'GAJMTX': '港澳居民来往内地通行证',
- 'TWJMTX': '台湾居民来往大陆通行证',
- 'WJLSFZ': '外国人永久居留身份证',
- 'GAJZZ': '港澳台居民居住证',
- 'ORG': '组织机构代码证',
- 'YYZZ': '工商营业执照',
- 'TYDM': '统一社会信用代码',
+ 'SFZ': this.$t('ID Card'),
+ 'HZ': this.$t('Passport'),
+ 'GAJMTX': this.$t('Mainland Travel Permit for Hong Kong and Macao Residents'),
+ 'TWJMTX': this.$t('Mainland Travel Permit for Taiwan Residents'),
+ 'WJLSFZ': this.$t('Permanent Residence ID Card for Foreigners'),
+ 'GAJZZ': this.$t('Residence Permit for Hong Kong, Macao and Taiwan Residents'),
+ 'ORG': this.$t('Organization Code Certificate'),
+ 'YYZZ': this.$t('Business License'),
+ 'TYDM': this.$t('Unified Social Credit Code'),
// 数字格式映射
- '1': '身份证',
- '5': '护照',
- '6': '港澳居民来往内地通行证',
- '11': '台湾居民来往大陆通行证',
- '12': '外国人永久居留身份证',
- '30': '港澳台居民居住证',
- '2': '组织机构代码证',
- '3': '工商营业执照',
- '4': '统一社会信用代码'
+ '1': this.$t('ID Card'),
+ '5': this.$t('Passport'),
+ '6': this.$t('Mainland Travel Permit for Hong Kong and Macao Residents'),
+ '11': this.$t('Mainland Travel Permit for Taiwan Residents'),
+ '12': this.$t('Permanent Residence ID Card for Foreigners'),
+ '30': this.$t('Residence Permit for Hong Kong, Macao and Taiwan Residents'),
+ '2': this.$t('Organization Code Certificate'),
+ '3': this.$t('Business License'),
+ '4': this.$t('Unified Social Credit Code')
};
return typeMap[type] || type || '-';
},
diff --git a/dashboard/src2/components/DomainOwnerDialog.vue b/dashboard/src/components/DomainOwnerDialog.vue
similarity index 100%
rename from dashboard/src2/components/DomainOwnerDialog.vue
rename to dashboard/src/components/DomainOwnerDialog.vue
diff --git a/dashboard/src2/components/EnvironmentVariableEditorDialog.vue b/dashboard/src/components/EnvironmentVariableEditorDialog.vue
similarity index 100%
rename from dashboard/src2/components/EnvironmentVariableEditorDialog.vue
rename to dashboard/src/components/EnvironmentVariableEditorDialog.vue
diff --git a/dashboard/src2/components/FilterControl.vue b/dashboard/src/components/FilterControl.vue
similarity index 100%
rename from dashboard/src2/components/FilterControl.vue
rename to dashboard/src/components/FilterControl.vue
diff --git a/dashboard/src2/components/FoldStep.vue b/dashboard/src/components/FoldStep.vue
similarity index 100%
rename from dashboard/src2/components/FoldStep.vue
rename to dashboard/src/components/FoldStep.vue
diff --git a/dashboard/src2/components/GenericDialog.vue b/dashboard/src/components/GenericDialog.vue
similarity index 100%
rename from dashboard/src2/components/GenericDialog.vue
rename to dashboard/src/components/GenericDialog.vue
diff --git a/dashboard/src2/components/GenericDialogField.vue b/dashboard/src/components/GenericDialogField.vue
similarity index 100%
rename from dashboard/src2/components/GenericDialogField.vue
rename to dashboard/src/components/GenericDialogField.vue
diff --git a/dashboard/src2/components/GenericList.vue b/dashboard/src/components/GenericList.vue
similarity index 93%
rename from dashboard/src2/components/GenericList.vue
rename to dashboard/src/components/GenericList.vue
index ca2290f..7bfec53 100644
--- a/dashboard/src2/components/GenericList.vue
+++ b/dashboard/src/components/GenericList.vue
@@ -28,7 +28,7 @@
v-if="rows.length === 0"
class="text-center text-sm leading-10 text-gray-500"
>
- 未找到结果
+ {{ $t('No results found') }}
diff --git a/dashboard/src2/components/GitHubAppSelector.vue b/dashboard/src/components/GitHubAppSelector.vue
similarity index 100%
rename from dashboard/src2/components/GitHubAppSelector.vue
rename to dashboard/src/components/GitHubAppSelector.vue
diff --git a/dashboard/src2/components/Header.vue b/dashboard/src/components/Header.vue
similarity index 100%
rename from dashboard/src2/components/Header.vue
rename to dashboard/src/components/Header.vue
diff --git a/dashboard/src2/components/HomeSummary.vue b/dashboard/src/components/HomeSummary.vue
similarity index 100%
rename from dashboard/src2/components/HomeSummary.vue
rename to dashboard/src/components/HomeSummary.vue
diff --git a/dashboard/src2/components/InvoiceTable.vue b/dashboard/src/components/InvoiceTable.vue
similarity index 100%
rename from dashboard/src2/components/InvoiceTable.vue
rename to dashboard/src/components/InvoiceTable.vue
diff --git a/dashboard/src2/components/JobStep.vue b/dashboard/src/components/JobStep.vue
similarity index 100%
rename from dashboard/src2/components/JobStep.vue
rename to dashboard/src/components/JobStep.vue
diff --git a/dashboard/src2/components/JsiteDomainAddDNSRecordDialog.vue b/dashboard/src/components/JsiteDomainAddDNSRecordDialog.vue
similarity index 100%
rename from dashboard/src2/components/JsiteDomainAddDNSRecordDialog.vue
rename to dashboard/src/components/JsiteDomainAddDNSRecordDialog.vue
diff --git a/dashboard/src2/components/JsiteDomainDNSRecords.vue b/dashboard/src/components/JsiteDomainDNSRecords.vue
similarity index 91%
rename from dashboard/src2/components/JsiteDomainDNSRecords.vue
rename to dashboard/src/components/JsiteDomainDNSRecords.vue
index 0089b14..5e3af56 100644
--- a/dashboard/src2/components/JsiteDomainDNSRecords.vue
+++ b/dashboard/src/components/JsiteDomainDNSRecords.vue
@@ -6,32 +6,32 @@