Sites菜单实现多语言支持

This commit is contained in:
jingrow 2025-12-29 04:29:39 +08:00
parent 0e1bc1e65e
commit bdb0e583aa
8 changed files with 227 additions and 183 deletions

View File

@ -67,7 +67,7 @@ export default {
disabled: enforce2FA, disabled: enforce2FA,
}, },
{ {
name: '站点', name: this.$t('Sites'),
icon: () => h(PanelTopInactive), icon: () => h(PanelTopInactive),
route: '/sites', route: '/sites',
isActive: isActive:

View File

@ -9,18 +9,19 @@ import type {
} from './types'; } from './types';
import { trialDays } from '../../utils/site'; import { trialDays } from '../../utils/site';
import { planTitle } from '../../utils/format'; import { planTitle } from '../../utils/format';
import { t } from '../../utils/i18n';
export const unreachable = Error('unreachable'); // used to indicate that a codepath is unreachable export const unreachable = Error('unreachable'); // used to indicate that a codepath is unreachable
export const clusterOptions = [ export const clusterOptions = [
'', '',
'中国大陆', t('China'),
'中国香港', t('Hong Kong'),
'美国-洛杉矶', t('US - Los Angeles'),
'新加坡', t('Singapore'),
'英国-伦敦', t('UK - London'),
'德国-法兰克福', t('Germany - Frankfurt'),
'阿联酋-迪拜', t('UAE - Dubai'),
]; ];
export function getUpsellBanner(site: DocumentResource, title: string) { export function getUpsellBanner(site: DocumentResource, title: string) {
@ -38,7 +39,7 @@ export function getUpsellBanner(site: DocumentResource, title: string) {
id: site.name, id: site.name,
type: 'gray', type: 'gray',
button: { button: {
label: '升级计划', label: t('Upgrade Plan'),
variant: 'outline', variant: 'outline',
onClick() { onClick() {
let SitePlansDialog = defineAsyncComponent( let SitePlansDialog = defineAsyncComponent(
@ -53,7 +54,7 @@ export function getUpsellBanner(site: DocumentResource, title: string) {
export function getSitesTabColumns(forBenchTab: boolean) { export function getSitesTabColumns(forBenchTab: boolean) {
return [ return [
{ {
label: '站点', label: t('Sites'),
fieldname: 'host_name', fieldname: 'host_name',
format(value, row) { format(value, row) {
return value || row.name; return value || row.name;
@ -64,13 +65,13 @@ export function getSitesTabColumns(forBenchTab: boolean) {
}, },
}, },
{ {
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
type: 'Badge', type: 'Badge',
width: 0.5, width: 0.5,
}, },
{ {
label: '区域', label: t('Region'),
fieldname: 'cluster_title', fieldname: 'cluster_title',
width: 0.5, width: 0.5,
prefix(row) { prefix(row) {
@ -83,7 +84,7 @@ export function getSitesTabColumns(forBenchTab: boolean) {
}, },
}, },
{ {
label: '计划', label: t('Plan Type'),
width: 0.5, width: 0.5,
format(value, row) { format(value, row) {
if (row.trial_end_date) { if (row.trial_end_date) {
@ -99,29 +100,29 @@ export function siteTabFilterControls() {
return [ return [
{ {
type: 'select', type: 'select',
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
options: [ options: [
{ label: '', value: '' }, { label: '', value: '' },
{ label: '激活', value: 'Active' }, { label: t('Active'), value: 'Active' },
{ label: '未激活', value: 'Inactive' }, { label: t('Inactive'), value: 'Inactive' },
{ label: '已暂停', value: 'Suspended' }, { label: t('Suspended'), value: 'Suspended' },
{ label: '已损坏', value: 'Broken' } { label: t('Broken'), value: 'Broken' }
], ],
}, },
{ {
type: 'select', type: 'select',
label: '区域', label: t('Region'),
fieldname: 'cluster', fieldname: 'cluster',
options: [ options: [
'', '',
'中国大陆', t('China'),
'中国香港', t('Hong Kong'),
'美国-洛杉矶', t('US - Los Angeles'),
'新加坡', t('Singapore'),
'英国-伦敦', t('UK - London'),
'德国-法兰克福', t('Germany - Frankfurt'),
'阿联酋-迪拜', t('UAE - Dubai'),
], ],
}, },
]; ];
@ -129,7 +130,7 @@ export function siteTabFilterControls() {
export function sitesTabRoute(r: Row) { export function sitesTabRoute(r: Row) {
return { return {
name: '站点详情', name: 'Site Detail',
params: { name: r.name }, params: { name: r.name },
} satisfies Route as Route; } satisfies Route as Route;
} }

View File

@ -8,6 +8,7 @@ import { duration, planTitle, userCurrency } from '../utils/format';
import { trialDays } from '../utils/site'; import { trialDays } from '../utils/site';
import { getJobsTab } from './common/jobs'; import { getJobsTab } from './common/jobs';
import { tagTab } from './common/tags'; import { tagTab } from './common/tags';
import { t } from '../utils/i18n';
export default { export default {
pagetype: 'Server', pagetype: 'Server',
@ -23,7 +24,7 @@ export default {
}, },
list: { list: {
route: '/servers', route: '/servers',
title: '服务器', title: t('Servers'),
fields: [ fields: [
'title', 'title',
'database_server', 'database_server',
@ -37,27 +38,27 @@ export default {
return [ return [
{ {
type: 'select', type: 'select',
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
options: [ options: [
{ label: '', value: '' }, { label: '', value: '' },
{ label: '激活', value: 'Active' }, { label: t('Active'), value: 'Active' },
{ label: '待定', value: 'Pending' } { label: t('Pending'), value: 'Pending' }
] ]
}, },
{ {
type: 'select', type: 'select',
label: '区域', label: t('Region'),
fieldname: 'cluster', fieldname: 'cluster',
options: [ options: [
'', '',
'中国大陆', t('China'),
'中国香港', t('Hong Kong'),
'美国-洛杉矶', t('US - Los Angeles'),
'新加坡', t('Singapore'),
'英国-伦敦', t('UK - London'),
'德国-法兰克福', t('Germany - Frankfurt'),
'阿联酋-迪拜', t('UAE - Dubai'),
] ]
} }
]; ];
@ -65,7 +66,7 @@ export default {
orderBy: 'creation desc', orderBy: 'creation desc',
columns: [ columns: [
{ {
label: '服务器', label: t('Servers'),
fieldname: 'name', fieldname: 'name',
width: 1.5, width: 1.5,
class: 'font-medium', class: 'font-medium',
@ -73,15 +74,15 @@ export default {
return row.title || value; return row.title || value;
} }
}, },
{ label: '状态', fieldname: 'status', type: 'Badge', width: 0.8 }, { label: t('Status'), fieldname: 'status', type: 'Badge', width: 0.8 },
{ {
label: '应用服务器计划', label: t('Application Server Plan'),
format(value, row) { format(value, row) {
return planTitle(row); return planTitle(row);
} }
}, },
{ {
label: '数据库服务器计划', label: t('Database Server Plan'),
fieldname: 'db_plan', fieldname: 'db_plan',
format(value) { format(value) {
if (!value) return ''; if (!value) return '';
@ -89,7 +90,7 @@ export default {
} }
}, },
{ {
label: '区域', label: t('Region'),
fieldname: 'cluster', fieldname: 'cluster',
format(value, row) { format(value, row) {
return row.cluster_title || value; return row.cluster_title || value;
@ -105,7 +106,7 @@ export default {
], ],
primaryAction({ listResource: servers }) { primaryAction({ listResource: servers }) {
return { return {
label: '新建服务器', label: t('New Server'),
variant: 'solid', variant: 'solid',
slots: { slots: {
prefix: icon('plus') prefix: icon('plus')
@ -127,7 +128,7 @@ export default {
breadcrumbs({ documentResource: server }) { breadcrumbs({ documentResource: server }) {
return [ return [
{ {
label: '服务器', label: t('Servers'),
route: '/servers' route: '/servers'
}, },
{ {
@ -141,8 +142,8 @@ export default {
return [ return [
{ {
label: '模拟服务器所有者', label: t('Impersonate Server Owner'),
title: '模拟服务器所有者', // for label to pop-up on hover title: t('Impersonate Server Owner'), // for label to pop-up on hover
slots: { slots: {
icon: defineAsyncComponent(() => icon: defineAsyncComponent(() =>
import('~icons/lucide/venetian-mask') import('~icons/lucide/venetian-mask')
@ -155,16 +156,16 @@ export default {
} }
}, },
{ {
label: '选项', label: t('Options'),
button: { button: {
label: '选项', label: t('Options'),
slots: { slots: {
icon: icon('more-horizontal') icon: icon('more-horizontal')
} }
}, },
options: [ options: [
{ {
label: '在 Desk 中查看', label: t('View in Desk'),
icon: icon('external-link'), icon: icon('external-link'),
condition: () => $team.pg?.is_desk_user, condition: () => $team.pg?.is_desk_user,
onClick() { onClick() {
@ -179,7 +180,7 @@ export default {
} }
}, },
{ {
label: '访问服务器', label: t('Access Server'),
icon: icon('external-link'), icon: icon('external-link'),
condition: () => condition: () =>
server.pg.status === 'Active' && $team.pg?.is_desk_user, server.pg.status === 'Active' && $team.pg?.is_desk_user,
@ -193,7 +194,7 @@ export default {
}, },
tabs: [ tabs: [
{ {
label: '概览', label: t('Overview'),
icon: icon('home'), icon: icon('home'),
route: 'overview', route: 'overview',
type: 'Component', type: 'Component',
@ -205,7 +206,7 @@ export default {
} }
}, },
{ {
label: '分析', label: t('Analytics'),
icon: icon('bar-chart-2'), icon: icon('bar-chart-2'),
route: 'analytics', route: 'analytics',
type: 'Component', type: 'Component',
@ -219,7 +220,7 @@ export default {
} }
}, },
{ {
label: '站点', label: t('Sites'),
icon: icon(LucideAppWindow), icon: icon(LucideAppWindow),
route: 'sites', route: 'sites',
type: 'list', type: 'list',
@ -247,19 +248,19 @@ export default {
return [ return [
{ {
type: 'select', type: 'select',
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
options: [ options: [
{ label: '', value: '' }, { label: '', value: '' },
{ label: '激活', value: 'Active' }, { label: t('Active'), value: 'Active' },
{ label: '未激活', value: 'Inactive' }, { label: t('Inactive'), value: 'Inactive' },
{ label: '已暂停', value: 'Suspended' }, { label: t('Suspended'), value: 'Suspended' },
{ label: '损坏', value: 'Broken' } { label: t('Broken'), value: 'Broken' }
] ]
}, },
{ {
type: 'link', type: 'link',
label: '版本', label: t('Version'),
fieldname: 'group.version', fieldname: 'group.version',
options: { options: {
pagetype: 'Jingrow Version' pagetype: 'Jingrow Version'
@ -267,7 +268,7 @@ export default {
}, },
{ {
type: 'link', type: 'link',
label: '站点分组', label: t('Release Group'),
fieldname: 'group', fieldname: 'group',
options: { options: {
pagetype: 'Release Group' pagetype: 'Release Group'
@ -275,7 +276,7 @@ export default {
}, },
{ {
type: 'link', type: 'link',
label: '标签', label: t('Tag'),
fieldname: 'tags.tag', fieldname: 'tags.tag',
options: { options: {
pagetype: 'Jcloud Tag', pagetype: 'Jcloud Tag',
@ -288,7 +289,7 @@ export default {
}, },
columns: [ columns: [
{ {
label: '站点', label: t('Sites'),
fieldname: 'host_name', fieldname: 'host_name',
width: 1.5, width: 1.5,
class: 'font-medium', class: 'font-medium',
@ -296,9 +297,9 @@ export default {
return value || row.name; return value || row.name;
} }
}, },
{ label: '状态', fieldname: 'status', type: 'Badge', width: 0.6 }, { label: t('Status'), fieldname: 'status', type: 'Badge', width: 0.6 },
{ {
label: '计划', label: t('Plan Type'),
fieldname: 'plan', fieldname: 'plan',
width: 0.85, width: 0.85,
format(value, row) { format(value, row) {
@ -312,18 +313,18 @@ export default {
china ? row.price_cny : row.price_usd, china ? row.price_cny : row.price_usd,
0 0
); );
return `${formattedValue}/`; return `${formattedValue}/${t('Monthly')}`;
} }
return row.plan_title; return row.plan_title;
} }
}, },
{ {
label: '站点分组', label: t('Release Group'),
fieldname: 'group_title', fieldname: 'group_title',
width: '15rem' width: '15rem'
}, },
{ {
label: '版本', label: t('Version'),
fieldname: 'version', fieldname: 'version',
width: 0.5 width: 0.5
} }
@ -331,7 +332,7 @@ export default {
} }
}, },
{ {
label: '站点分组', label: t('Release Group'),
icon: icon('package'), icon: icon('package'),
route: 'groups', route: 'groups',
type: 'list', type: 'list',
@ -342,24 +343,24 @@ export default {
}, },
fields: [{ apps: ['app'] }, { servers: ['server'] }], fields: [{ apps: ['app'] }, { servers: ['server'] }],
columns: [ columns: [
{ label: '标题', fieldname: 'title' }, { label: t('Title'), fieldname: 'title' },
{ {
label: '状态', label: t('Status'),
fieldname: 'active_benches', fieldname: 'active_benches',
type: 'Badge', type: 'Badge',
width: 0.5, width: 0.5,
format: (value, row) => { format: (value, row) => {
if (!value) return '等待部署'; if (!value) return t('Waiting for Deployment');
else return '激活'; else return t('Active');
} }
}, },
{ {
label: '版本', label: t('Version'),
fieldname: 'version', fieldname: 'version',
width: 0.5 width: 0.5
}, },
{ {
label: '应用', label: t('App'),
fieldname: 'app', fieldname: 'app',
format: (value, row) => { format: (value, row) => {
return (row.apps || []).map(d => d.app).join(', '); return (row.apps || []).map(d => d.app).join(', ');
@ -367,7 +368,7 @@ export default {
width: '25rem' width: '25rem'
}, },
{ {
label: '站点', label: t('Sites'),
fieldname: 'site_count', fieldname: 'site_count',
width: 0.25 width: 0.25
} }
@ -376,7 +377,7 @@ export default {
return [ return [
{ {
type: 'link', type: 'link',
label: '版本', label: t('Version'),
fieldname: 'version', fieldname: 'version',
options: { options: {
pagetype: 'Jingrow Version' pagetype: 'Jingrow Version'
@ -384,7 +385,7 @@ export default {
}, },
{ {
type: 'link', type: 'link',
label: '标签', label: t('Tag'),
fieldname: 'tags.tag', fieldname: 'tags.tag',
options: { options: {
pagetype: 'Jcloud Tag', pagetype: 'Jcloud Tag',
@ -403,7 +404,7 @@ export default {
}, },
primaryAction({ listResource: benches, documentResource: server }) { primaryAction({ listResource: benches, documentResource: server }) {
return { return {
label: '新建站点分组', label: t('New Release Group'),
slots: { slots: {
prefix: icon('plus') prefix: icon('plus')
}, },
@ -419,7 +420,7 @@ export default {
}, },
getJobsTab('Server'), getJobsTab('Server'),
{ {
label: '执行', label: t('Execute'),
icon: icon('play'), icon: icon('play'),
childrenRoutes: ['Server Play'], childrenRoutes: ['Server Play'],
route: 'plays', route: 'plays',
@ -430,7 +431,7 @@ export default {
return [ return [
{ {
type: 'select', type: 'select',
label: '服务器', label: t('Servers'),
fieldname: 'server', fieldname: 'server',
options: [ options: [
server.pg.name, server.pg.name,
@ -462,23 +463,23 @@ export default {
fields: ['server', 'end'], fields: ['server', 'end'],
columns: [ columns: [
{ {
label: '执行', label: t('Execute'),
fieldname: 'play', fieldname: 'play',
width: 2 width: 2
}, },
{ {
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
type: 'Badge', type: 'Badge',
width: 0.5 width: 0.5
}, },
{ {
label: '服务器', label: t('Servers'),
fieldname: 'server', fieldname: 'server',
width: 2 width: 2
}, },
{ {
label: '持续时间', label: t('Duration'),
fieldname: 'duration', fieldname: 'duration',
width: 0.5, width: 0.5,
format(value, row) { format(value, row) {
@ -496,7 +497,7 @@ export default {
} }
}, },
{ {
label: '操作', label: t('Actions'),
icon: icon('sliders'), icon: icon('sliders'),
route: 'actions', route: 'actions',
type: 'Component', type: 'Component',

View File

@ -23,6 +23,7 @@ import { clusterOptions, getUpsellBanner } from './common';
import { getAppsTab } from './common/apps'; import { getAppsTab } from './common/apps';
import { isMobile } from '../utils/device'; import { isMobile } from '../utils/device';
import { getJobsTab } from './common/jobs'; import { getJobsTab } from './common/jobs';
import { t } from '../utils/i18n';
export default { export default {
pagetype: 'Site', pagetype: 'Site',
@ -64,7 +65,7 @@ export default {
}, },
list: { list: {
route: '/sites', route: '/sites',
title: '站点', title: t('Sites'),
fields: [ fields: [
'plan.plan_title as plan_title', 'plan.plan_title as plan_title',
'plan.price_usd as price_usd', 'plan.price_usd as price_usd',
@ -84,20 +85,20 @@ export default {
return [ return [
{ {
type: 'select', type: 'select',
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
options: [ options: [
{ label: '', value: '' }, { label: '', value: '' },
{ label: '激活', value: 'Active' }, { label: t('Active'), value: 'Active' },
{ label: '未激活', value: 'Inactive' }, { label: t('Inactive'), value: 'Inactive' },
{ label: '已暂停', value: 'Suspended' }, { label: t('Suspended'), value: 'Suspended' },
{ label: '损坏', value: 'Broken' }, { label: t('Broken'), value: 'Broken' },
{ label: '已归档', value: 'Archived' }, { label: t('Archived'), value: 'Archived' },
], ],
}, },
{ {
type: 'link', type: 'link',
label: '版本', label: t('Version'),
fieldname: 'group.version', fieldname: 'group.version',
options: { options: {
pagetype: 'Jingrow Version', pagetype: 'Jingrow Version',
@ -105,7 +106,7 @@ export default {
}, },
{ {
type: 'link', type: 'link',
label: '站点分组', label: t('Release Group'),
fieldname: 'group', fieldname: 'group',
options: { options: {
pagetype: 'Release Group', pagetype: 'Release Group',
@ -113,13 +114,13 @@ export default {
}, },
{ {
type: 'select', type: 'select',
label: '区域', label: t('Region'),
fieldname: 'cluster', fieldname: 'cluster',
options: clusterOptions, options: clusterOptions,
}, },
{ {
type: 'link', type: 'link',
label: '标签', label: t('Tag'),
fieldname: 'tags.tag', fieldname: 'tags.tag',
options: { options: {
pagetype: 'Jcloud Tag', pagetype: 'Jcloud Tag',
@ -132,7 +133,7 @@ export default {
}, },
columns: [ columns: [
{ {
label: '站点', label: t('Sites'),
fieldname: 'host_name', fieldname: 'host_name',
width: 1.5, width: 1.5,
class: 'font-medium', class: 'font-medium',
@ -141,29 +142,29 @@ export default {
}, },
}, },
{ {
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
type: 'Badge', type: 'Badge',
width: '140px', width: '140px',
format(value) { format(value) {
const statusMap = { const statusMap = {
'Active': '激活', 'Active': t('Active'),
'Inactive': '未激活', 'Inactive': t('Inactive'),
'Suspended': '已暂停', 'Suspended': t('Suspended'),
'Broken': '损坏', 'Broken': t('Broken'),
'Archived': '已归档', 'Archived': t('Archived'),
'Pending': '待处理', 'Pending': t('Pending'),
'Installing': '安装中', 'Installing': t('Installing'),
'Update Available': '可更新', 'Update Available': t('Update Available'),
'Running': '运行中', 'Running': t('Running'),
'Success': '成功', 'Success': t('Success'),
'Failure': '失败' 'Failure': t('Failure')
}; };
return statusMap[value] || value; return statusMap[value] || value;
} }
}, },
{ {
label: '计划', label: t('Plan Type'),
fieldname: 'plan', fieldname: 'plan',
width: 0.85, width: 0.85,
format(value, row) { format(value, row) {
@ -177,13 +178,13 @@ export default {
china ? row.price_cny : row.price_usd, china ? row.price_cny : row.price_usd,
0, 0,
); );
return `${formattedValue}/`; return `${formattedValue}/${t('Monthly')}`;
} }
return row.plan_title; return row.plan_title;
}, },
}, },
{ {
label: '区域', label: t('Region'),
fieldname: 'cluster', fieldname: 'cluster',
width: 1, width: 1,
format(value, row) { format(value, row) {
@ -198,20 +199,20 @@ export default {
}, },
}, },
{ {
label: '站点分组', label: t('Release Group'),
fieldname: 'group', fieldname: 'group',
width: '15rem', width: '15rem',
format(value, row) { format(value, row) {
return row.group_public ? '公域' : row.group_title || value; return row.group_public ? t('Public') : row.group_title || value;
}, },
}, },
{ {
label: '版本', label: t('Version'),
fieldname: 'version', fieldname: 'version',
width: 0.5, width: 0.5,
}, },
{ {
label: '到期时间', label: t('Due Date'),
fieldname: 'site_end_date', fieldname: 'site_end_date',
width: 1, width: 1,
format(value) { format(value) {
@ -221,7 +222,7 @@ export default {
], ],
primaryAction({ listResource: sites }) { primaryAction({ listResource: sites }) {
return { return {
label: '新建站点', label: t('New Site'),
variant: 'solid', variant: 'solid',
slots: { slots: {
prefix: icon('plus'), prefix: icon('plus'),
@ -234,7 +235,7 @@ export default {
moreActions({ listResource: sites }) { moreActions({ listResource: sites }) {
return [ return [
{ {
label: '导出为CSV', label: t('Export as CSV'),
icon: 'download', icon: 'download',
onClick() { onClick() {
const fields = [ const fields = [
@ -278,16 +279,16 @@ export default {
route: '/sites/:name', route: '/sites/:name',
statusBadge({ documentResource: site }) { statusBadge({ documentResource: site }) {
const statusMap = { const statusMap = {
'Active': '激活', 'Active': t('Active'),
'Inactive': '未激活', 'Inactive': t('Inactive'),
'Suspended': '已暂停', 'Suspended': t('Suspended'),
'Broken': '损坏', 'Broken': t('Broken'),
'Archived': '已归档', 'Archived': t('Archived'),
'Pending': '待处理', 'Pending': t('Pending'),
'Installing': '安装中', 'Installing': t('Installing'),
'Running': '运行中', 'Running': t('Running'),
'Success': '成功', 'Success': t('Success'),
'Failure': '失败' 'Failure': t('Failure')
}; };
return { label: statusMap[site.pg.status] || site.pg.status }; return { label: statusMap[site.pg.status] || site.pg.status };
}, },
@ -328,7 +329,7 @@ export default {
}, },
tabs: [ tabs: [
{ {
label: '概览', label: t('Overview'),
icon: icon('home'), icon: icon('home'),
route: 'overview', route: 'overview',
type: 'Component', type: 'Component',
@ -342,7 +343,7 @@ export default {
}, },
getAppsTab(true), getAppsTab(true),
{ {
label: '域名', label: t('Domain'),
icon: icon('external-link'), icon: icon('external-link'),
route: 'domains', route: 'domains',
type: 'list', type: 'list',
@ -355,22 +356,22 @@ export default {
}, },
columns: [ columns: [
{ {
label: '域名', label: t('Domain'),
fieldname: 'domain', fieldname: 'domain',
}, },
{ {
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
type: 'Badge', type: 'Badge',
format(value) { format(value) {
const statusMap = { const statusMap = {
'Active': '激活', 'Active': t('Active'),
'Inactive': '未激活', 'Inactive': t('Inactive'),
'Suspended': '已暂停', 'Suspended': t('Suspended'),
'Broken': '损坏', 'Broken': t('Broken'),
'Archived': '已归档', 'Archived': t('Archived'),
'Pending': '待处理', 'Pending': t('Pending'),
'Installing': '安装中', 'Installing': t('Installing'),
'Running': '运行中', 'Running': '运行中',
'Success': '成功', 'Success': '成功',
'Failure': '失败' 'Failure': '失败'
@ -463,10 +464,10 @@ export default {
domain: row.domain, domain: row.domain,
}), }),
{ {
loading: '正在移除域名...', loading: t('Removing domain...'),
success: () => { success: () => {
hide(); hide();
return '域名已移除'; return t('Domain removed');
}, },
error: (e) => getToastErrorMessage(e), error: (e) => getToastErrorMessage(e),
}, },
@ -476,12 +477,12 @@ export default {
}, },
}, },
{ {
label: '设为主域名', label: t('Set as Primary Domain'),
condition: () => !row.primary && row.status === 'Active', condition: () => !row.primary && row.status === 'Active',
onClick() { onClick() {
confirmDialog({ confirmDialog({
title: `设为主域名`, title: t('Set as Primary Domain'),
message: `您确定要将域名 <b>${row.domain}</b> 设为站点 <b>${site.pg?.name}</b> 的主域名吗?`, message: t('Are you sure you want to set domain <b>{domain}</b> as the primary domain for site <b>{site}</b>?', { domain: row.domain, site: site.pg?.name }),
onSuccess({ hide }) { onSuccess({ hide }) {
if (site.setPrimaryDomain.loading) return; if (site.setPrimaryDomain.loading) return;
toast.promise( toast.promise(
@ -489,10 +490,10 @@ export default {
domain: row.domain, domain: row.domain,
}), }),
{ {
loading: '正在设置主域名...', loading: t('Setting primary domain...'),
success: () => { success: () => {
hide(); hide();
return '主域名已设置'; return t('Primary domain set');
}, },
error: (e) => getToastErrorMessage(e), error: (e) => getToastErrorMessage(e),
}, },
@ -502,15 +503,15 @@ export default {
}, },
}, },
{ {
label: '重定向到主域名', label: t('Redirect to Primary Domain'),
condition: () => condition: () =>
!row.primary && !row.primary &&
!row.redirect_to_primary && !row.redirect_to_primary &&
row.status === 'Active', row.status === 'Active',
onClick() { onClick() {
confirmDialog({ confirmDialog({
title: `重定向域名`, title: t('Redirect Domain'),
message: `您确定要将域名 <b>${row.domain}</b> 重定向到站点 <b>${site.pg?.name}</b> 的主域名吗?`, message: t('Are you sure you want to redirect domain <b>{domain}</b> to the primary domain of site <b>{site}</b>?', { domain: row.domain, site: site.pg?.name }),
onSuccess({ hide }) { onSuccess({ hide }) {
if (site.redirectToPrimary.loading) return; if (site.redirectToPrimary.loading) return;
toast.promise( toast.promise(
@ -518,10 +519,10 @@ export default {
domain: row.domain, domain: row.domain,
}), }),
{ {
loading: '正在重定向域名...', loading: t('Redirecting domain...'),
success: () => { success: () => {
hide(); hide();
return '域名已重定向'; return t('Domain redirected');
}, },
error: (e) => getToastErrorMessage(e), error: (e) => getToastErrorMessage(e),
}, },
@ -884,7 +885,7 @@ export default {
}, },
getJobsTab('Site'), getJobsTab('Site'),
{ {
label: '操作', label: t('Actions'),
icon: icon('sliders'), icon: icon('sliders'),
route: 'actions', route: 'actions',
type: 'Component', type: 'Component',
@ -895,7 +896,7 @@ export default {
}, },
}, },
{ {
label: '更新', label: t('Update'),
icon: icon('arrow-up-circle'), icon: icon('arrow-up-circle'),
route: 'updates', route: 'updates',
type: 'list', type: 'list',
@ -916,7 +917,7 @@ export default {
], ],
columns: [ columns: [
{ {
label: '类型', label: t('Type'),
fieldname: 'deploy_type', fieldname: 'deploy_type',
width: 0.3, width: 0.3,
format(value) { format(value) {
@ -924,7 +925,7 @@ export default {
} }
}, },
{ {
label: '状态', label: t('Status'),
fieldname: 'status', fieldname: 'status',
type: 'Badge', type: 'Badge',
width: 0.5, width: 0.5,
@ -933,7 +934,7 @@ export default {
} }
}, },
// { // {
// label: '备份', // label: t('Backup'),
// width: 0.4, // width: 0.4,
// type: 'Component', // type: 'Component',
// component({ row }) { // component({ row }) {
@ -943,24 +944,24 @@ export default {
// class: 'truncate text-base', // class: 'truncate text-base',
// }, // },
// row.skipped_backups // row.skipped_backups
// ? '跳过' // ? t('Skipped')
// : row.backup_type || '逻辑', // : row.backup_type || t('Logical'),
// ); // );
// }, // },
// }, // },
{ {
label: '创建者', label: t('Owner'),
fieldname: 'owner', fieldname: 'owner',
}, },
{ {
label: '计划时间', label: t('Scheduled Time'),
fieldname: 'scheduled_time', fieldname: 'scheduled_time',
format(value) { format(value) {
return date(value, 'lll'); return date(value, 'lll');
}, },
}, },
{ {
label: '更新时间', label: t('Updated On'),
fieldname: 'updated_on', fieldname: 'updated_on',
format(value) { format(value) {
return date(value, 'lll'); return date(value, 'lll');
@ -970,7 +971,7 @@ export default {
rowActions({ row, documentResource: site }) { rowActions({ row, documentResource: site }) {
return [ return [
{ {
label: '编辑', label: t('Update'),
condition: () => row.status === 'Scheduled', condition: () => row.status === 'Scheduled',
onClick() { onClick() {
let SiteUpdateDialog = defineAsyncComponent( let SiteUpdateDialog = defineAsyncComponent(
@ -985,22 +986,22 @@ export default {
}, },
}, },
{ {
label: '取消', label: t('Cancel'),
condition: () => row.status === 'Scheduled', condition: () => row.status === 'Scheduled',
onClick() { onClick() {
confirmDialog({ confirmDialog({
title: '取消更新', title: t('Cancel Update'),
message: `您确定要取消计划的更新吗?`, message: t('Are you sure you want to cancel the scheduled update?'),
onSuccess({ hide }) { onSuccess({ hide }) {
if (site.cancelUpdate.loading) return; if (site.cancelUpdate.loading) return;
toast.promise( toast.promise(
site.cancelUpdate.submit({ site_update: row.name }), site.cancelUpdate.submit({ site_update: row.name }),
{ {
loading: '正在取消更新...', loading: t('Cancelling update...'),
success: () => { success: () => {
hide(); hide();
site.reload(); site.reload();
return '更新已取消'; return t('Update cancelled');
}, },
error: (e) => getToastErrorMessage(e), error: (e) => getToastErrorMessage(e),
}, },
@ -1010,7 +1011,7 @@ export default {
}, },
}, },
{ {
label: '查看任务', label: t('View Job'),
condition: () => row.status !== 'Scheduled', condition: () => row.status !== 'Scheduled',
onClick() { onClick() {
router.push({ router.push({
@ -1020,7 +1021,7 @@ export default {
}, },
}, },
{ {
label: '立即更新', label: t('Update Now'),
condition: () => row.status === 'Scheduled', condition: () => row.status === 'Scheduled',
onClick() { onClick() {
let siteUpdate = getDocResource({ let siteUpdate = getDocResource({
@ -1032,21 +1033,21 @@ export default {
}); });
toast.promise(siteUpdate.updateNow.submit(), { toast.promise(siteUpdate.updateNow.submit(), {
loading: '正在更新站点...', loading: t('Updating site...'),
success: () => { success: () => {
router.push({ router.push({
name: 'Site Update', name: 'Site Update',
params: { id: row.name }, params: { id: row.name },
}); });
return '站点更新已启动'; return t('Site update started');
}, },
error: '更新站点失败', error: t('Failed to update site'),
}); });
}, },
}, },
{ {
label: '查看应用更改', label: t('View App Changes'),
onClick() { onClick() {
createListResource({ createListResource({
pagetype: 'Deploy Candidate Difference App', pagetype: 'Deploy Candidate Difference App',
@ -1338,7 +1339,7 @@ export default {
routes: [ routes: [
{ {
name: '站点更新', name: t('Site Update'),
path: 'updates/:id', path: 'updates/:id',
component: () => import('../pages/SiteUpdate.vue'), component: () => import('../pages/SiteUpdate.vue'),
}, },

View File

@ -944,7 +944,6 @@ export default {
/[0-9]/.test(this.signupPassword); /[0-9]/.test(this.signupPassword);
}, },
isPhoneNumberValid() { isPhoneNumberValid() {
// 1113-9
const phoneRegex = /^1[3-9]\d{9}$/; const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(this.phoneNumber); return phoneRegex.test(this.phoneNumber);
}, },

View File

@ -4,13 +4,13 @@
<header <header
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-5 py-2.5" class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-5 py-2.5"
> >
<Breadcrumbs :items="[{ label: 'Sites', route: { name: 'Sites' } }]"> <Breadcrumbs :items="[{ label: $t('Sites'), route: { name: 'Sites' } }]">
<template v-if="this.$account?.team.enabled" #actions> <template v-if="this.$account?.team.enabled" #actions>
<Button <Button
variant="solid" variant="solid"
icon-left="plus" icon-left="plus"
class="ml-2" class="ml-2"
label="Create" :label="$t('Create')"
@click="validateCreateSite" @click="validateCreateSite"
> >
</Button> </Button>
@ -88,13 +88,13 @@
<div class="pb-20"> <div class="pb-20">
<div class="flex"> <div class="flex">
<div class="flex w-full space-x-2 pb-4"> <div class="flex w-full space-x-2 pb-4">
<FormControl label="Search Sites" v-model="searchTerm"> <FormControl :label="$t('Search Sites')" v-model="searchTerm">
<template #prefix> <template #prefix>
<FeatherIcon name="search" class="w-4 text-gray-600" /> <FeatherIcon name="search" class="w-4 text-gray-600" />
</template> </template>
</FormControl> </FormControl>
<FormControl <FormControl
label="Status" :label="$t('Status')"
class="mr-8" class="mr-8"
type="select" type="select"
:options="siteStatusFilterOptions" :options="siteStatusFilterOptions"
@ -282,7 +282,7 @@ export default {
name: 'Sites', name: 'Sites',
pageMeta() { pageMeta() {
return { return {
title: 'Sites - Jingrow' title: `${this.$t('Sites')} - Jingrow`
}; };
}, },
props: ['bench'], props: ['bench'],

View File

@ -11,7 +11,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
import vitePluginTranslate from './vite-plugin-translate.mjs'; import vitePluginTranslate from './vite-plugin-translate.mjs';
// 语言配置:设置目标语言,默认为 'en'(英文),可设置为 'zh'(中文)等 // 语言配置:设置目标语言,默认为 'en'(英文),可设置为 'zh'(中文)等
const locale = process.env.DASHBOARD_LOCALE || 'zh'; const locale = process.env.DASHBOARD_LOCALE || 'en';
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [

View File

@ -1,6 +1,7 @@
API Key,API密钥, API Key,API密钥,
API Secret,API密钥, API Secret,API密钥,
Access Key ID,访问密钥ID, Access Key ID,访问密钥ID,
Access Server,访问服务器,
Account,科目, Account,科目,
Action,行动, Action,行动,
Action Type,动作类型, Action Type,动作类型,
@ -13,6 +14,7 @@ Additional Permissions,额外的权限,
Alert,警报, Alert,警报,
All,所有, All,所有,
Allocated To,分配给, Allocated To,分配给,
Analytics,分析,
Amended From,修订源, Amended From,修订源,
Amount,金额, Amount,金额,
Amount Due,应付金额, Amount Due,应付金额,
@ -20,6 +22,7 @@ Annual,全年,
App,应用, App,应用,
App Name,应用程序名称, App Name,应用程序名称,
Application Server,应用服务器, Application Server,应用服务器,
Application Server Plan,应用服务器计划,
Apply,应用, Apply,应用,
Apply Patch,应用补丁, Apply Patch,应用补丁,
Approved,已批准, Approved,已批准,
@ -36,8 +39,11 @@ Beta,Beta版,
Billing,账单, Billing,账单,
Bucket Name,桶名, Bucket Name,桶名,
Cancel,取消, Cancel,取消,
Cancel Update,取消更新,
Cancelled,取消, Cancelled,取消,
Cancelling update...,正在取消更新...,
Card,, Card,,
China Mainland,中国大陆,
Category,类别, Category,类别,
Change Plan,更改计划, Change Plan,更改计划,
Check,校验, Check,校验,
@ -66,6 +72,7 @@ Dashboard,仪表板,
Data,数据, Data,数据,
Database Name,数据库名称, Database Name,数据库名称,
Database Server,数据库服务器, Database Server,数据库服务器,
Database Server Plan,数据库服务器计划,
Date,日期, Date,日期,
Datetime,时间日期, Datetime,时间日期,
Deactivate Site,停用站点, Deactivate Site,停用站点,
@ -81,10 +88,13 @@ Disabled,禁用,
Document Name,文档名称, Document Name,文档名称,
Document Type,页面类型, Document Type,页面类型,
Domain,主域名, Domain,主域名,
Domain redirected,域名已重定向,
Domain removed,域名已移除,
Domains,, Domains,,
Download,下载, Download,下载,
Draft,草案, Draft,草案,
Due Date,到期日, Due Date,到期日,
Export as CSV,导出为CSV,
Duration,持续时间, Duration,持续时间,
JERP Partner,JERP合作伙伴, JERP Partner,JERP合作伙伴,
Email,邮箱, Email,邮箱,
@ -102,6 +112,7 @@ Execute,执行,
Expired,已过期, Expired,已过期,
Expires On,到期, Expires On,到期,
Failed,失败, Failed,失败,
Failed to update site,更新站点失败,
Failure,失败, Failure,失败,
Field,字段, Field,字段,
Fieldname,字段名, Fieldname,字段名,
@ -124,12 +135,14 @@ Group,组,
Group By,通过...分组, Group By,通过...分组,
HTML,HTML, HTML,HTML,
High,, High,,
Hong Kong,中国香港,
Host,主办, Host,主办,
Hostname,主机名, Hostname,主机名,
ID,ID,D ID,ID,D
IP Address,IP地址, IP Address,IP地址,
Image,图像, Image,图像,
Impersonate Team,模拟团队, Impersonate Team,模拟团队,
Impersonate Server Owner,模拟服务器所有者,
In Progress,进行中, In Progress,进行中,
Inactive,未激活, Inactive,未激活,
Index,索引, Index,索引,
@ -166,6 +179,8 @@ Message (Markdown),讯息(降价),
Method,方法, Method,方法,
Monday,星期一, Monday,星期一,
Monthly,每月, Monthly,每月,
New Release Group,新建站点分组,
New Server,新建服务器,
Naming,命名, Naming,命名,
Net Amount,净金额, Net Amount,净金额,
New Plan,新计划, New Plan,新计划,
@ -183,6 +198,7 @@ Number,数,
Onboarding,入职, Onboarding,入职,
Open,, Open,,
Options,选项, Options,选项,
Overview,概览,
Other,其他, Other,其他,
Output,输出, Output,输出,
Partner Payment Payout,合作伙伴付款, Partner Payment Payout,合作伙伴付款,
@ -204,7 +220,9 @@ Posting Date,发布日期,
Prepaid Credits,预付额度, Prepaid Credits,预付额度,
Preview,预览, Preview,预览,
Primary,初级, Primary,初级,
Primary domain set,主域名已设置,
Print Format,打印格式, Print Format,打印格式,
Removing domain...,正在移除域名...,
Priority,优先, Priority,优先,
Privacy Policy,隐私政策, Privacy Policy,隐私政策,
Private,私人, Private,私人,
@ -229,7 +247,12 @@ Reference PageType,参考页面类型,
Reference Pagetype,参考页面类型, Reference Pagetype,参考页面类型,
Reference Name,参考名称, Reference Name,参考名称,
Region,区域, Region,区域,
Release Group,站点分组,
Redirect Domain,重定向域名,
Redirecting domain...,正在重定向域名...,
Rejected,拒绝, Rejected,拒绝,
Singapore,新加坡,
Germany - Frankfurt,德国-法兰克福,
Reload,重新载入, Reload,重新载入,
Request Data,请求数据, Request Data,请求数据,
Response,响应, Response,响应,
@ -246,6 +269,7 @@ Run,跑,
Saturday,星期六, Saturday,星期六,
Save,保存, Save,保存,
Scheduled,已计划, Scheduled,已计划,
Scheduled Time,计划时间,
Script,脚本, Script,脚本,
Secret Key,密钥, Secret Key,密钥,
Security,安全, Security,安全,
@ -263,7 +287,12 @@ Show,显示,
Sign Up,注册, Sign Up,注册,
Signature,签名, Signature,签名,
Sites,网站, Sites,网站,
Search Sites,搜索站点,
Site Update,站点更新,
Site update started,站点更新已启动,
Size,尺寸, Size,尺寸,
Servers,服务器,
Servers,服务器,
Skip,跳跃, Skip,跳跃,
Social Login Key,社交登录密钥, Social Login Key,社交登录密钥,
Source,, Source,,
@ -304,13 +333,22 @@ Total,总,
Total Amount,总金额, Total Amount,总金额,
Total Discount Amount,总折扣金额, Total Discount Amount,总折扣金额,
Traceback,回溯, Traceback,回溯,
UAE - Dubai,阿联酋-迪拜,
UK - London,英国-伦敦,
US - Los Angeles,美国-洛杉矶,
Waiting for Deployment,等待部署,
Transaction ID,交易ID, Transaction ID,交易ID,
Transferred Credits,已转移额度, Transferred Credits,已转移额度,
Tuesday,星期二, Tuesday,星期二,
Type,类型, Type,类型,
URL,网址, URL,网址,
Update,更新, Update,更新,
Update Available,可更新,
Update Now,立即更新,
Update cancelled,更新已取消,
Updating,更新, Updating,更新,
Updating site...,正在更新站点...,
Updated On,更新时间,
User,用户, User,用户,
User Image,用户图片, User Image,用户图片,
Username,用户名, Username,用户名,
@ -321,7 +359,10 @@ Verified,验证,
Verify,确认,Submit verification code Verify,确认,Submit verification code
Version,版本, Version,版本,
View,查看, View,查看,
View App Changes,查看应用更改,
View Feedback,查看反馈, View Feedback,查看反馈,
View in Desk,在 Desk 中查看,
View Job,查看任务,
View Website,查看网站, View Website,查看网站,
Warning,警告, Warning,警告,
Webhook,网络挂接, Webhook,网络挂接,
@ -441,6 +482,7 @@ Migrate,迁移,
Pull,拉取, Pull,拉取,
Uninstall,卸载, Uninstall,卸载,
Upgrade,升级, Upgrade,升级,
Upgrade Plan,升级计划,
Downgrade,降级, Downgrade,降级,
Rollback,回滚, Rollback,回滚,
You are not logged in.,您尚未登录。, You are not logged in.,您尚未登录。,

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