应用市场菜单增加多语言支持
This commit is contained in:
parent
fc4152cf19
commit
2a350e93ce
@ -28,7 +28,7 @@
|
|||||||
v-if="rows.length === 0"
|
v-if="rows.length === 0"
|
||||||
class="text-center text-sm leading-10 text-gray-500"
|
class="text-center text-sm leading-10 text-gray-500"
|
||||||
>
|
>
|
||||||
未找到结果
|
{{ $t('No results found') }}
|
||||||
</div>
|
</div>
|
||||||
<ListRow v-for="(row, i) in rows" :row="row" :key="row.name">
|
<ListRow v-for="(row, i) in rows" :row="row" :key="row.name">
|
||||||
<template v-slot="{ column, item }">
|
<template v-slot="{ column, item }">
|
||||||
|
|||||||
@ -1,23 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<Card
|
<Card
|
||||||
class="md:col-span-2"
|
class="md:col-span-2"
|
||||||
title="App Descriptions"
|
:title="$t('App Descriptions')"
|
||||||
subtitle="Details about your app"
|
:subtitle="$t('Details about your app')"
|
||||||
>
|
>
|
||||||
<div class="divide-y" v-if="app">
|
<div class="divide-y" v-if="app">
|
||||||
<ListItem title="Summary" :description="$sanitize(app.description)">
|
<ListItem :title="$t('Summary')" :description="$sanitize(app.description)">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<Button icon-left="edit" @click="showEditSummaryDialog = true">
|
<Button icon-left="edit" @click="showEditSummaryDialog = true">
|
||||||
Edit
|
{{ $t('Edit') }}
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Dialog
|
<Dialog
|
||||||
:options="{
|
:options="{
|
||||||
title: 'Update App Summary',
|
title: $t('Update App Summary'),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: 'Save Changes',
|
label: $t('Save Changes'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
loading: $resources.updateAppSummary.loading,
|
loading: $resources.updateAppSummary.loading,
|
||||||
onClick: () => $resources.updateAppSummary.submit()
|
onClick: () => $resources.updateAppSummary.submit()
|
||||||
@ -28,7 +28,7 @@
|
|||||||
>
|
>
|
||||||
<template v-slot:body-content>
|
<template v-slot:body-content>
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Summary of the app"
|
:label="$t('Summary of the app')"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
v-model="app.description"
|
v-model="app.description"
|
||||||
/>
|
/>
|
||||||
@ -39,10 +39,10 @@
|
|||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<div class="py-3">
|
<div class="py-3">
|
||||||
<ListItem title="Long Description">
|
<ListItem :title="$t('Long Description')">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<Button icon-left="edit" @click="showEditDescriptionDialog = true">
|
<Button icon-left="edit" @click="showEditDescriptionDialog = true">
|
||||||
Edit
|
{{ $t('Edit') }}
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
@ -53,11 +53,11 @@
|
|||||||
></div>
|
></div>
|
||||||
<Dialog
|
<Dialog
|
||||||
:options="{
|
:options="{
|
||||||
title: 'Update App Description',
|
title: $t('Update App Description'),
|
||||||
size: '5xl',
|
size: '5xl',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: 'Save Changes',
|
label: $t('Save Changes'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
loading: $resources.updateAppDescription.loading,
|
loading: $resources.updateAppDescription.loading,
|
||||||
onClick: () => $resources.updateAppDescription.submit()
|
onClick: () => $resources.updateAppDescription.submit()
|
||||||
@ -91,7 +91,7 @@
|
|||||||
:loading="$resources.fetchReadme.loading"
|
:loading="$resources.fetchReadme.loading"
|
||||||
@click="$resources.fetchReadme.submit()"
|
@click="$resources.fetchReadme.submit()"
|
||||||
>
|
>
|
||||||
Fetch Readme
|
{{ $t('Fetch Readme') }}
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Card>
|
</Card>
|
||||||
@ -122,7 +122,7 @@ export default {
|
|||||||
summary: description
|
summary: description
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
this.notifySuccess('App Summary Updated!');
|
this.notifySuccess(this.$t('App Summary Updated!'));
|
||||||
this.showEditSummaryDialog = false;
|
this.showEditSummaryDialog = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -136,7 +136,7 @@ export default {
|
|||||||
description: long_description
|
description: long_description
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
this.notifySuccess('App Description Updated!');
|
this.notifySuccess(this.$t('App Description Updated!'));
|
||||||
this.showEditDescriptionDialog = false;
|
this.showEditDescriptionDialog = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -147,8 +147,8 @@ export default {
|
|||||||
params: { name: this.app.name },
|
params: { name: this.app.name },
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
notify({
|
notify({
|
||||||
title: 'Successfully fetched latest readme',
|
title: this.$t('Successfully fetched latest readme'),
|
||||||
message: 'Long description updated!',
|
message: this.$t('Long description updated!'),
|
||||||
icon: 'check',
|
icon: 'check',
|
||||||
color: 'green'
|
color: 'green'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,18 +3,18 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex justify-between border-b pb-4">
|
<div class="flex justify-between border-b pb-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-lg font-medium text-gray-900">应用资料</h2>
|
<h2 class="text-lg font-medium text-gray-900">{{ $t('App Profile') }}</h2>
|
||||||
<p class="mt-1 text-sm leading-6 text-gray-600">
|
<p class="mt-1 text-sm leading-6 text-gray-600">
|
||||||
这些信息将公开显示在市场上。请确保输入正确的信息,没有损坏的链接和图片。
|
{{ $t('This information will be publicly displayed on the marketplace. Please ensure you enter correct information, with no broken links and images.') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button :variant="editing ? 'solid' : 'subtle'" @click="updateListing"
|
<Button :variant="editing ? 'solid' : 'subtle'" @click="updateListing"
|
||||||
>保存</Button
|
>{{ $t('Save') }}</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 gap-x-5 border-b py-6 md:grid-cols-2">
|
<div class="grid grid-cols-1 gap-x-5 border-b py-6 md:grid-cols-2">
|
||||||
<div class="border-r pr-6">
|
<div class="border-r pr-6">
|
||||||
<span class="text-base font-medium">资料</span>
|
<span class="text-base font-medium">{{ $t('Profile') }}</span>
|
||||||
<div class="group relative my-4 flex">
|
<div class="group relative my-4 flex">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<Avatar
|
<Avatar
|
||||||
@ -25,7 +25,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<FileUploader
|
<FileUploader
|
||||||
@success="() => imageAddSuccess('资料照片已更新')"
|
@success="() => imageAddSuccess($t('Profile photo updated'))"
|
||||||
@failure="imageAddFailure"
|
@failure="imageAddFailure"
|
||||||
fileTypes="image/*"
|
fileTypes="image/*"
|
||||||
:upload-args="{
|
:upload-args="{
|
||||||
@ -44,7 +44,7 @@
|
|||||||
:class="{ 'opacity-50': uploading }"
|
:class="{ 'opacity-50': uploading }"
|
||||||
>
|
>
|
||||||
<span v-if="uploading">{{ progress }}%</span>
|
<span v-if="uploading">{{ progress }}%</span>
|
||||||
<span v-else>编辑</span>
|
<span v-else>{{ $t('Edit') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -53,18 +53,18 @@
|
|||||||
<div class="pb-8 sm:col-span-4">
|
<div class="pb-8 sm:col-span-4">
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="标题"
|
:label="$t('Title')"
|
||||||
type="text"
|
type="text"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
v-model="marketplaceApp.title"
|
v-model="marketplaceApp.title"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="sm:col-span-4">
|
<div class="sm:col-span-4">
|
||||||
<span class="text-base font-medium">链接</span>
|
<span class="text-base font-medium">{{ $t('Links') }}</span>
|
||||||
<div>
|
<div>
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="文档"
|
:label="$t('Documentation')"
|
||||||
type="text"
|
type="text"
|
||||||
@blur="validateLink('documentation')"
|
@blur="validateLink('documentation')"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
@ -72,7 +72,7 @@
|
|||||||
/>
|
/>
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="网站"
|
:label="$t('Website')"
|
||||||
type="text"
|
type="text"
|
||||||
@blur="validateLink('website')"
|
@blur="validateLink('website')"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
@ -80,7 +80,7 @@
|
|||||||
/>
|
/>
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="支持"
|
:label="$t('Support')"
|
||||||
type="text"
|
type="text"
|
||||||
@blur="validateLink('support')"
|
@blur="validateLink('support')"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
@ -88,7 +88,7 @@
|
|||||||
/>
|
/>
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="服务条款"
|
:label="$t('Terms of Service')"
|
||||||
type="text"
|
type="text"
|
||||||
@blur="validateLink('terms_of_service')"
|
@blur="validateLink('terms_of_service')"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
@ -96,7 +96,7 @@
|
|||||||
/>
|
/>
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="隐私政策"
|
:label="$t('Privacy Policy')"
|
||||||
type="text"
|
type="text"
|
||||||
@blur="validateLink('privacy_policy')"
|
@blur="validateLink('privacy_policy')"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
@ -107,10 +107,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="hidden md:block">
|
<div class="hidden md:block">
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<span class="text-base font-medium">截图和视频</span>
|
<span class="text-base font-medium">{{ $t('Screenshots and Videos') }}</span>
|
||||||
<FileUploader
|
<FileUploader
|
||||||
class="ml-auto"
|
class="ml-auto"
|
||||||
@success="() => imageAddSuccess('已添加截图')"
|
@success="() => imageAddSuccess($t('Screenshot added'))"
|
||||||
@failure="imageAddFailure"
|
@failure="imageAddFailure"
|
||||||
fileTypes="image/*"
|
fileTypes="image/*"
|
||||||
:upload-args="{
|
:upload-args="{
|
||||||
@ -126,7 +126,7 @@
|
|||||||
:loading="uploading"
|
:loading="uploading"
|
||||||
@click="openFileSelector()"
|
@click="openFileSelector()"
|
||||||
icon-left="plus"
|
icon-left="plus"
|
||||||
label="添加"
|
:label="$t('Add')"
|
||||||
>
|
>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
@ -152,16 +152,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<span class="text-base font-medium">描述</span>
|
<span class="text-base font-medium">{{ $t('Description') }}</span>
|
||||||
<FormControl
|
<FormControl
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
label="摘要"
|
:label="$t('Summary')"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
@input="editing = true"
|
@input="editing = true"
|
||||||
v-model="marketplaceApp.description"
|
v-model="marketplaceApp.description"
|
||||||
/>
|
/>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<span class="text-xs text-gray-600">描述</span>
|
<span class="text-xs text-gray-600">{{ $t('Description') }}</span>
|
||||||
<TextEditor
|
<TextEditor
|
||||||
class="mt-1 block w-full rounded border border-gray-100 bg-gray-100 px-2 py-1.5 text-base text-gray-800 placeholder-gray-500 transition-colors hover:border-gray-200 hover:bg-gray-200 focus:border-gray-500 focus:bg-white focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-gray-400"
|
class="mt-1 block w-full rounded border border-gray-100 bg-gray-100 px-2 py-1.5 text-base text-gray-800 placeholder-gray-500 transition-colors hover:border-gray-200 hover:bg-gray-200 focus:border-gray-500 focus:bg-white focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-gray-400"
|
||||||
ref="textEditor"
|
ref="textEditor"
|
||||||
@ -258,21 +258,21 @@ export default {
|
|||||||
toast.promise(this.$resources.updateListing.submit(), {
|
toast.promise(this.$resources.updateListing.submit(), {
|
||||||
success: () => {
|
success: () => {
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
return '更新成功';
|
return this.$t('Listing updated successfully');
|
||||||
},
|
},
|
||||||
loading: '正在更新列表...',
|
loading: this.$t('Updating listing...'),
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
return err.messages?.length
|
return err.messages?.length
|
||||||
? err.messages.join('\n')
|
? err.messages.join('\n')
|
||||||
: err.message || '更新列表失败';
|
: err.message || this.$t('Failed to update listing');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
dropdownOptions(image) {
|
dropdownOptions(image) {
|
||||||
return [
|
return [
|
||||||
{ label: '查看', onClick: () => window.open(image) },
|
{ label: this.$t('View'), onClick: () => window.open(image) },
|
||||||
{
|
{
|
||||||
label: '删除',
|
label: this.$t('Delete'),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
this.$resources.removeScreenshot.submit({
|
this.$resources.removeScreenshot.submit({
|
||||||
@ -280,15 +280,15 @@ onClick: () => {
|
|||||||
file: image,
|
file: image,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: '正在删除截图...',
|
loading: this.$t('Deleting screenshot...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
this.$resources.listingData.reload();
|
this.$resources.listingData.reload();
|
||||||
return '截图删除成功';
|
return this.$t('Screenshot deleted successfully');
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
return err.messages?.length
|
return err.messages?.length
|
||||||
? err.messages.join('\n')
|
? err.messages.join('\n')
|
||||||
: err.message || '删除截图失败';
|
: err.message || this.$t('Failed to delete screenshot');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Card title="App Profile" subtitle="Your app's primary profile">
|
<Card :title="$t('App Profile')" :subtitle="$t('Your app's primary profile')">
|
||||||
<div class="flex items-center border-b pb-6">
|
<div class="flex items-center border-b pb-6">
|
||||||
<div class="group relative">
|
<div class="group relative">
|
||||||
<Avatar
|
<Avatar
|
||||||
@ -26,12 +26,12 @@
|
|||||||
:class="{ 'opacity-50': uploading }"
|
:class="{ 'opacity-50': uploading }"
|
||||||
>
|
>
|
||||||
<span v-if="uploading">{{ progress }}%</span>
|
<span v-if="uploading">{{ progress }}%</span>
|
||||||
<span v-else>Edit</span>
|
<span v-else>{{ $t('Edit') }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="absolute bottom-0 left-0 grid w-full place-items-center rounded-md bg-gray-900 text-xs font-semibold text-white text-opacity-70 opacity-80 group-hover:opacity-0"
|
class="absolute bottom-0 left-0 grid w-full place-items-center rounded-md bg-gray-900 text-xs font-semibold text-white text-opacity-70 opacity-80 group-hover:opacity-0"
|
||||||
>
|
>
|
||||||
<span>Edit</span>
|
<span>{{ $t('Edit') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -45,12 +45,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<Button icon-left="edit" @click="showAppProfileEditDialog = true">
|
<Button icon-left="edit" @click="showAppProfileEditDialog = true">
|
||||||
Edit
|
{{ $t('Edit') }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-8 flex justify-between">
|
<div class="mt-8 flex justify-between">
|
||||||
<p class="text-lg font-semibold">Published Versions</p>
|
<p class="text-lg font-semibold">{{ $t('Published Versions') }}</p>
|
||||||
<Button
|
<Button
|
||||||
icon-left="plus"
|
icon-left="plus"
|
||||||
@click="
|
@click="
|
||||||
@ -59,7 +59,7 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Add
|
{{ $t('Add') }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div class="divide-y" v-if="app">
|
<div class="divide-y" v-if="app">
|
||||||
@ -83,10 +83,10 @@
|
|||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
:options="{
|
:options="{
|
||||||
title: 'Update App Title',
|
title: $t('Update App Title'),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: 'Save Changes',
|
label: $t('Save Changes'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
loading: $resources.updateAppTitle.loading,
|
loading: $resources.updateAppTitle.loading,
|
||||||
onClick: () => $resources.updateAppTitle.submit()
|
onClick: () => $resources.updateAppTitle.submit()
|
||||||
@ -96,7 +96,7 @@
|
|||||||
v-model="showAppProfileEditDialog"
|
v-model="showAppProfileEditDialog"
|
||||||
>
|
>
|
||||||
<template v-slot:body-content>
|
<template v-slot:body-content>
|
||||||
<FormControl label="App Title" v-model="app.title" />
|
<FormControl :label="$t('App Title')" v-model="app.title" />
|
||||||
|
|
||||||
<ErrorMessage class="mt-4" :message="$resources.updateAppTitle.error" />
|
<ErrorMessage class="mt-4" :message="$resources.updateAppTitle.error" />
|
||||||
</template>
|
</template>
|
||||||
@ -206,7 +206,7 @@ export default {
|
|||||||
dropdownItems(source) {
|
dropdownItems(source) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Change Branch',
|
label: this.$t('Change Branch'),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
this.selectedSource = source.source;
|
this.selectedSource = source.source;
|
||||||
this.selectedVersion = source.version;
|
this.selectedVersion = source.version;
|
||||||
@ -215,7 +215,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Remove',
|
label: this.$t('Remove'),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
this.$resources.removeVersion.submit({
|
this.$resources.removeVersion.submit({
|
||||||
name: this.app.name,
|
name: this.app.name,
|
||||||
@ -227,7 +227,7 @@ export default {
|
|||||||
},
|
},
|
||||||
notifySuccess() {
|
notifySuccess() {
|
||||||
notify({
|
notify({
|
||||||
title: 'App Profile Updated!',
|
title: this.$t('App Profile Updated!'),
|
||||||
icon: 'check',
|
icon: 'check',
|
||||||
color: 'green'
|
color: 'green'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -128,7 +128,7 @@ export default {
|
|||||||
disabled: enforce2FA,
|
disabled: enforce2FA,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '应用市场',
|
name: this.$t('Marketplace'),
|
||||||
icon: () => h(App),
|
icon: () => h(App),
|
||||||
route: '/apps',
|
route: '/apps',
|
||||||
isActive: routeName.startsWith('Marketplace'),
|
isActive: routeName.startsWith('Marketplace'),
|
||||||
|
|||||||
@ -427,7 +427,7 @@ this.$socket.emit('pagetype_unsubscribe', pagetype);
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
emptyStateMessage() {
|
emptyStateMessage() {
|
||||||
return this.options.emptyStateMessage || '未找到结果';
|
return this.options.emptyStateMessage || this.$t('No results found');
|
||||||
},
|
},
|
||||||
banner() {
|
banner() {
|
||||||
if (this.options.banner) {
|
if (this.options.banner) {
|
||||||
|
|||||||
@ -2,14 +2,14 @@
|
|||||||
<Dialog
|
<Dialog
|
||||||
v-model="show"
|
v-model="show"
|
||||||
:options="{
|
:options="{
|
||||||
title: '应用发布前需要完成的步骤',
|
title: $t('Steps to complete before publishing your app'),
|
||||||
size: '2xl'
|
size: '2xl'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #body-content>
|
<template #body-content>
|
||||||
<div v-if="appDoc.pg.review_stage === 'Ready for Review'">
|
<div v-if="appDoc.pg.review_stage === 'Ready for Review'">
|
||||||
<p class="text-p-base text-gray-700">
|
<p class="text-p-base text-gray-700">
|
||||||
您的应用已发送给我们的团队进行审核。请等待审核完成。
|
{{ $t('Your app has been sent to our team for review. Please wait for the review to complete.') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<ObjectList v-else :options="listOptions" />
|
<ObjectList v-else :options="listOptions" />
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
label="标记应用为待审核"
|
:label="$t('Mark app as ready for review')"
|
||||||
:loading="appDoc.markAppReadyForReview.loading"
|
:loading="appDoc.markAppReadyForReview.loading"
|
||||||
:disabled="$resources.reviewSteps.data.some(step => !step.completed)"
|
:disabled="$resources.reviewSteps.data.some(step => !step.completed)"
|
||||||
@click="appDoc.markAppReadyForReview.submit"
|
@click="appDoc.markAppReadyForReview.submit"
|
||||||
@ -64,11 +64,11 @@ export default {
|
|||||||
hideControls: true,
|
hideControls: true,
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '步骤',
|
label: this.$t('Step'),
|
||||||
fieldname: 'step'
|
fieldname: 'step'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '已完成',
|
label: this.$t('Completed'),
|
||||||
fieldname: 'completed',
|
fieldname: 'completed',
|
||||||
type: 'Icon',
|
type: 'Icon',
|
||||||
width: 0.3,
|
width: 0.3,
|
||||||
@ -87,7 +87,7 @@ export default {
|
|||||||
route += row.step.includes('Publish') ? 'versions' : 'listing';
|
route += row.step.includes('Publish') ? 'versions' : 'listing';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label: '查看',
|
label: this.$t('View'),
|
||||||
variant: 'ghost',
|
variant: 'ghost',
|
||||||
route
|
route
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,10 +2,10 @@
|
|||||||
<Dialog
|
<Dialog
|
||||||
v-if="source"
|
v-if="source"
|
||||||
:options="{
|
:options="{
|
||||||
title: '更改 ' + app + ' 的 ' + version + ' 分支',
|
title: $t('Change {app} {version} branch', { app, version }),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: '更改分支',
|
label: this.$t('Change Branch'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
loading: $resources.changeBranch.loading,
|
loading: $resources.changeBranch.loading,
|
||||||
onClick: () => changeBranch()
|
onClick: () => changeBranch()
|
||||||
@ -70,8 +70,8 @@ export default {
|
|||||||
to_branch: this.selectedBranch
|
to_branch: this.selectedBranch
|
||||||
},
|
},
|
||||||
validate() {
|
validate() {
|
||||||
if (this.selectedBranch == this.app.branch) {
|
if (this.selectedBranch == this.activeBranch) {
|
||||||
throw new DashboardError('请选择一个不同的分支');
|
throw new DashboardError(this.$t('Please select a different branch'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -80,11 +80,11 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
changeBranch() {
|
changeBranch() {
|
||||||
toast.promise(this.$resources.changeBranch.submit(), {
|
toast.promise(this.$resources.changeBranch.submit(), {
|
||||||
loading: '正在更新版本的分支...',
|
loading: this.$t('Updating version branch...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
this.show = false;
|
this.show = false;
|
||||||
this.$emit('branch-changed');
|
this.$emit('branch-changed');
|
||||||
return '分支更改成功';
|
return this.$t('Branch changed successfully');
|
||||||
},
|
},
|
||||||
error: e => getToastErrorMessage(e)
|
error: e => getToastErrorMessage(e)
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<div class="col-span-2 mb-5 rounded-md border">
|
<div class="col-span-2 mb-5 rounded-md border">
|
||||||
<div class="grid grid-cols-2 lg:grid-cols-5">
|
<div class="grid grid-cols-2 lg:grid-cols-5">
|
||||||
<div class="border-b border-r p-5 lg:border-b-0">
|
<div class="border-b border-r p-5 lg:border-b-0">
|
||||||
<div class="text-base text-gray-700">总安装量</div>
|
<div class="text-base text-gray-700">{{ $t('Total Installs') }}</div>
|
||||||
<div class="mt-2 flex items-start justify-between">
|
<div class="mt-2 flex items-start justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="leading-4">
|
<div class="leading-4">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-b border-r p-5 lg:border-b-0">
|
<div class="border-b border-r p-5 lg:border-b-0">
|
||||||
<div class="text-base text-gray-700">激活站点</div>
|
<div class="text-base text-gray-700">{{ $t('Active Sites') }}</div>
|
||||||
<div class="mt-2 flex items-start justify-between">
|
<div class="mt-2 flex items-start justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="leading-4">
|
<div class="leading-4">
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-b border-r p-5 lg:border-b-0">
|
<div class="border-b border-r p-5 lg:border-b-0">
|
||||||
<div class="text-base text-gray-700">激活站点分组</div>
|
<div class="text-base text-gray-700">{{ $t('Active Benches') }}</div>
|
||||||
<div class="mt-2 flex items-start justify-between">
|
<div class="mt-2 flex items-start justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="leading-4">
|
<div class="leading-4">
|
||||||
@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-b border-r p-5 lg:border-b-0">
|
<div class="border-b border-r p-5 lg:border-b-0">
|
||||||
<div class="text-base text-gray-700">每周安装量</div>
|
<div class="text-base text-gray-700">{{ $t('Weekly Installs') }}</div>
|
||||||
<div class="mt-2 flex items-start justify-between">
|
<div class="mt-2 flex items-start justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="leading-4">
|
<div class="leading-4">
|
||||||
@ -55,7 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-b border-r p-5 lg:border-b-0">
|
<div class="border-b border-r p-5 lg:border-b-0">
|
||||||
<div class="text-base text-gray-700">总收入</div>
|
<div class="text-base text-gray-700">{{ $t('Total Earnings') }}</div>
|
||||||
<div class="mt-2 flex items-start justify-between">
|
<div class="mt-2 flex items-start justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="leading-4">
|
<div class="leading-4">
|
||||||
@ -74,7 +74,7 @@
|
|||||||
class="grid grid-cols-1 gap-5 lg:grid-cols-2"
|
class="grid grid-cols-1 gap-5 lg:grid-cols-2"
|
||||||
>
|
>
|
||||||
<LineChart
|
<LineChart
|
||||||
title="页面浏览量"
|
:title="$t('Pageviews')"
|
||||||
type="time"
|
type="time"
|
||||||
key="Page Views"
|
key="Page Views"
|
||||||
:data="
|
:data="
|
||||||
@ -88,7 +88,7 @@
|
|||||||
:error="$resources.plausible_analytics.error"
|
:error="$resources.plausible_analytics.error"
|
||||||
/>
|
/>
|
||||||
<LineChart
|
<LineChart
|
||||||
title="独立访客"
|
:title="$t('Unique Visitors')"
|
||||||
type="time"
|
type="time"
|
||||||
key="Unique Visitors"
|
key="Unique Visitors"
|
||||||
:data="
|
:data="
|
||||||
@ -105,7 +105,7 @@
|
|||||||
<LineChart
|
<LineChart
|
||||||
v-if="$resources.plausible_analytics.data"
|
v-if="$resources.plausible_analytics.data"
|
||||||
class="mt-5"
|
class="mt-5"
|
||||||
title="每周安装量"
|
:title="$t('Weekly Installs')"
|
||||||
type="time"
|
type="time"
|
||||||
key="Weekly Installs"
|
key="Weekly Installs"
|
||||||
:data="
|
:data="
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
:options="{
|
:options="{
|
||||||
title: '添加新的应用市场应用',
|
title: $t('Add New Marketplace App'),
|
||||||
size: 'xl',
|
size: 'xl',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: '添加应用',
|
label: $t('Add App'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
disabled: (!appValidated && !selectedVersion) || !this.app.is_public,
|
disabled: (!appValidated && !selectedVersion) || !this.app.is_public,
|
||||||
onClick: addApp
|
onClick: addApp
|
||||||
@ -29,7 +29,7 @@
|
|||||||
v-if="selectedBranch"
|
v-if="selectedBranch"
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
type="autocomplete"
|
type="autocomplete"
|
||||||
label="选择版本"
|
:label="$t('Select Version')"
|
||||||
:options="{ pagetype: 'Jingrow Version', filters: { public: 1 } }"
|
:options="{ pagetype: 'Jingrow Version', filters: { public: 1 } }"
|
||||||
v-model="selectedVersion"
|
v-model="selectedVersion"
|
||||||
/>
|
/>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
class="flex text-base text-gray-700"
|
class="flex text-base text-gray-700"
|
||||||
>
|
>
|
||||||
<LoadingIndicator class="mr-2 w-4" />
|
<LoadingIndicator class="mr-2 w-4" />
|
||||||
正在验证应用...
|
{{ $t('Validating app...') }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="appValidated" class="flex text-base text-gray-700">
|
<div v-if="appValidated" class="flex text-base text-gray-700">
|
||||||
<div v-if="this.app.is_public === true" class="flex gap-1">
|
<div v-if="this.app.is_public === true" class="flex gap-1">
|
||||||
@ -48,7 +48,7 @@
|
|||||||
name="check"
|
name="check"
|
||||||
:stroke-width="3"
|
:stroke-width="3"
|
||||||
/>
|
/>
|
||||||
找到 {{ this.app.title }} ({{ this.app.name }})
|
{{ $t('Found {title} ({name})', { title: this.app.title, name: this.app.name }) }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="this.app.is_public === false">
|
<div v-else-if="this.app.is_public === false">
|
||||||
<div class="flex text-base text-gray-700 gap-1">
|
<div class="flex text-base text-gray-700 gap-1">
|
||||||
@ -56,12 +56,12 @@
|
|||||||
class="w-4 p-0.5 text-white rounded bg-red-500"
|
class="w-4 p-0.5 text-white rounded bg-red-500"
|
||||||
name="x"
|
name="x"
|
||||||
/>
|
/>
|
||||||
Github 仓库是私有的。
|
{{ $t('Github repository is private.') }}
|
||||||
<Link
|
<Link
|
||||||
href="https://jingrow.com/marketplace/terms"
|
href="https://jingrow.com/marketplace/terms"
|
||||||
class="font-medium"
|
class="font-medium"
|
||||||
>
|
>
|
||||||
条款和政策
|
{{ $t('Terms and Policies') }}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -140,14 +140,14 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
addApp() {
|
addApp() {
|
||||||
toast.promise(this.$resources.addApp.submit(), {
|
toast.promise(this.$resources.addApp.submit(), {
|
||||||
loading: '正在添加新应用...',
|
loading: this.$t('Adding new app...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
this.show = false;
|
this.show = false;
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'Marketplace App Detail Listing',
|
name: 'Marketplace App Detail Listing',
|
||||||
params: { name: this.app.name }
|
params: { name: this.app.name }
|
||||||
});
|
});
|
||||||
return '新应用已添加';
|
return this.$t('New app added');
|
||||||
},
|
},
|
||||||
error: e => getToastErrorMessage(e)
|
error: e => getToastErrorMessage(e)
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,6 +7,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: 'Jsite Domain',
|
pagetype: 'Jsite Domain',
|
||||||
@ -19,7 +20,7 @@ export default {
|
|||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
route: '/domains',
|
route: '/domains',
|
||||||
title: '域名',
|
title: t('Domains'),
|
||||||
fields: [
|
fields: [
|
||||||
'name',
|
'name',
|
||||||
'domain',
|
'domain',
|
||||||
@ -39,12 +40,12 @@ export default {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '状态',
|
label: t('Status'),
|
||||||
fieldname: 'status',
|
fieldname: 'status',
|
||||||
options: [
|
options: [
|
||||||
{ label: '', value: '' },
|
{ label: '', value: '' },
|
||||||
{ label: '正常', value: 'ok' },
|
{ label: t('Normal'), value: 'ok' },
|
||||||
{ label: '锁定', value: 'clienthold' }
|
{ label: t('Locked'), value: 'clienthold' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -53,7 +54,7 @@ export default {
|
|||||||
searchField: 'domain',
|
searchField: 'domain',
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '域名',
|
label: t('Domain'),
|
||||||
fieldname: 'domain',
|
fieldname: 'domain',
|
||||||
width: 2,
|
width: 2,
|
||||||
class: 'font-medium',
|
class: 'font-medium',
|
||||||
@ -62,20 +63,20 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: t('Status'),
|
||||||
fieldname: 'status',
|
fieldname: 'status',
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
width: 0.8,
|
width: 0.8,
|
||||||
format(value) {
|
format(value) {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
'ok': '正常',
|
'ok': t('Normal'),
|
||||||
'clienthold': '锁定'
|
'clienthold': t('Locked')
|
||||||
};
|
};
|
||||||
return statusMap[value] || value;
|
return statusMap[value] || value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '注册时间',
|
label: t('Registration Date'),
|
||||||
fieldname: 'registration_date',
|
fieldname: 'registration_date',
|
||||||
format(value) {
|
format(value) {
|
||||||
if (!value) return '-';
|
if (!value) return '-';
|
||||||
@ -83,7 +84,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '到期时间',
|
label: t('Expiry Date'),
|
||||||
fieldname: 'end_date',
|
fieldname: 'end_date',
|
||||||
format(value) {
|
format(value) {
|
||||||
if (!value) return '-';
|
if (!value) return '-';
|
||||||
@ -93,7 +94,7 @@ export default {
|
|||||||
],
|
],
|
||||||
primaryAction({ listResource: domains }) {
|
primaryAction({ listResource: domains }) {
|
||||||
return {
|
return {
|
||||||
label: '新建域名',
|
label: t('New Domain'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('plus')
|
prefix: icon('plus')
|
||||||
@ -106,11 +107,11 @@ export default {
|
|||||||
statusBadge({ documentResource: domain }) {
|
statusBadge({ documentResource: domain }) {
|
||||||
const status = domain.pg?.status;
|
const status = domain.pg?.status;
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
'Pending': '待处理',
|
'Pending': t('Pending'),
|
||||||
'Active': '正常',
|
'Active': t('Normal'),
|
||||||
'Expired': '已过期',
|
'Expired': t('Expired'),
|
||||||
'Suspended': '已暂停',
|
'Suspended': t('Suspended'),
|
||||||
'Cancelled': '已取消'
|
'Cancelled': t('Cancelled')
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
label: statusMap[status] || status
|
label: statusMap[status] || status
|
||||||
@ -119,7 +120,7 @@ export default {
|
|||||||
breadcrumbs({ documentResource: domain }) {
|
breadcrumbs({ documentResource: domain }) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '域名',
|
label: t('Domains'),
|
||||||
route: '/domains'
|
route: '/domains'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -133,7 +134,7 @@ export default {
|
|||||||
|
|
||||||
const actions = [
|
const actions = [
|
||||||
{
|
{
|
||||||
label: '续费',
|
label: t('Renew'),
|
||||||
icon: 'refresh-cw',
|
icon: 'refresh-cw',
|
||||||
onClick() {
|
onClick() {
|
||||||
domain.renew.submit();
|
domain.renew.submit();
|
||||||
@ -141,14 +142,14 @@ export default {
|
|||||||
condition: () => domain.pg?.status === 'Active'
|
condition: () => domain.pg?.status === 'Active'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '重命名',
|
label: t('Rename'),
|
||||||
icon: 'edit-3',
|
icon: 'edit-3',
|
||||||
onClick() {
|
onClick() {
|
||||||
domain.rename.submit();
|
domain.rename.submit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '删除',
|
label: t('Delete'),
|
||||||
icon: 'trash-2',
|
icon: 'trash-2',
|
||||||
onClick() {
|
onClick() {
|
||||||
domain.dropDomain.submit();
|
domain.dropDomain.submit();
|
||||||
@ -161,10 +162,10 @@ export default {
|
|||||||
},
|
},
|
||||||
detail: {
|
detail: {
|
||||||
route: '/domains/:name',
|
route: '/domains/:name',
|
||||||
title: '域名详细信息',
|
title: t('Domain Details'),
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
label: '概览',
|
label: t('Overview'),
|
||||||
route: '',
|
route: '',
|
||||||
type: 'Component',
|
type: 'Component',
|
||||||
component: defineAsyncComponent(() => import('../components/JsiteDomainOverview.vue')),
|
component: defineAsyncComponent(() => import('../components/JsiteDomainOverview.vue')),
|
||||||
@ -173,7 +174,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '域名解析',
|
label: t('DNS Records'),
|
||||||
route: 'dns',
|
route: 'dns',
|
||||||
type: 'Component',
|
type: 'Component',
|
||||||
component: defineAsyncComponent(() => import('../components/JsiteDomainDNSRecords.vue')),
|
component: defineAsyncComponent(() => import('../components/JsiteDomainDNSRecords.vue')),
|
||||||
@ -182,7 +183,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '所有者模板',
|
label: t('Owner Template'),
|
||||||
route: 'owners',
|
route: 'owners',
|
||||||
type: 'Component',
|
type: 'Component',
|
||||||
component: defineAsyncComponent(() => import('../components/DomainOwner.vue')),
|
component: defineAsyncComponent(() => import('../components/DomainOwner.vue')),
|
||||||
@ -193,7 +194,7 @@ export default {
|
|||||||
],
|
],
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: '基本信息',
|
label: t('Basic Information'),
|
||||||
fields: [
|
fields: [
|
||||||
'domain',
|
'domain',
|
||||||
'status',
|
'status',
|
||||||
@ -204,7 +205,7 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '价格信息',
|
label: t('Pricing Information'),
|
||||||
fields: [
|
fields: [
|
||||||
'price',
|
'price',
|
||||||
'period',
|
'period',
|
||||||
@ -213,7 +214,7 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'DNS设置',
|
label: t('DNS Settings'),
|
||||||
fields: [
|
fields: [
|
||||||
'dns_host1',
|
'dns_host1',
|
||||||
'dns_host2',
|
'dns_host2',
|
||||||
@ -224,7 +225,7 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '其他信息',
|
label: t('Other Information'),
|
||||||
fields: [
|
fields: [
|
||||||
'description',
|
'description',
|
||||||
'whois_protection'
|
'whois_protection'
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { userCurrency, currency } from '../utils/format';
|
|||||||
import { getToastErrorMessage } from '../utils/toast';
|
import { getToastErrorMessage } from '../utils/toast';
|
||||||
import { isMobile } from '../utils/device';
|
import { isMobile } from '../utils/device';
|
||||||
import router from '../router';
|
import router from '../router';
|
||||||
|
import { t } from '../utils/i18n';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
pagetype: 'Marketplace App',
|
pagetype: 'Marketplace App',
|
||||||
@ -25,11 +26,11 @@ export default {
|
|||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
route: '/apps',
|
route: '/apps',
|
||||||
title: '应用市场',
|
title: t('Marketplace'),
|
||||||
fields: ['image', 'title', 'status', 'description'],
|
fields: ['image', 'title', 'status', 'description'],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '应用',
|
label: t('App'),
|
||||||
fieldname: 'title',
|
fieldname: 'title',
|
||||||
class: 'font-medium',
|
class: 'font-medium',
|
||||||
width: 0.3,
|
width: 0.3,
|
||||||
@ -51,20 +52,20 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: t('Status'),
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
fieldname: 'status',
|
fieldname: 'status',
|
||||||
width: 0.3
|
width: 0.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '描述',
|
label: t('Description'),
|
||||||
fieldname: 'description',
|
fieldname: 'description',
|
||||||
width: 1.0
|
width: 1.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
primaryAction() {
|
primaryAction() {
|
||||||
return {
|
return {
|
||||||
label: '新建应用',
|
label: t('New App'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('plus')
|
prefix: icon('plus')
|
||||||
@ -96,7 +97,7 @@ export default {
|
|||||||
},
|
},
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
label: '分析',
|
label: t('Analytics'),
|
||||||
icon: icon('bar-chart-2'),
|
icon: icon('bar-chart-2'),
|
||||||
route: 'analytics',
|
route: 'analytics',
|
||||||
type: 'Component',
|
type: 'Component',
|
||||||
@ -108,7 +109,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '列表',
|
label: t('Listing'),
|
||||||
icon: icon('shopping-cart'),
|
icon: icon('shopping-cart'),
|
||||||
route: 'listing',
|
route: 'listing',
|
||||||
type: 'Component',
|
type: 'Component',
|
||||||
@ -120,7 +121,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '版本',
|
label: t('Versions'),
|
||||||
icon: icon('package'),
|
icon: icon('package'),
|
||||||
route: 'versions',
|
route: 'versions',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
@ -140,24 +141,24 @@ export default {
|
|||||||
],
|
],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '版本',
|
label: t('Version'),
|
||||||
fieldname: 'version',
|
fieldname: 'version',
|
||||||
width: 0.5
|
width: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '来源',
|
label: t('Source'),
|
||||||
fieldname: 'source',
|
fieldname: 'source',
|
||||||
width: 0.5
|
width: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '仓库',
|
label: t('Repository'),
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
format: (value, row) => {
|
format: (value, row) => {
|
||||||
return `${row.repository_owner}/${row.repository}`;
|
return `${row.repository_owner}/${row.repository}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '分支',
|
label: t('Branch'),
|
||||||
fieldname: 'branch',
|
fieldname: 'branch',
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
width: 0.5
|
width: 0.5
|
||||||
@ -165,7 +166,7 @@ export default {
|
|||||||
],
|
],
|
||||||
primaryAction({ listResource: versions, documentResource: app }) {
|
primaryAction({ listResource: versions, documentResource: app }) {
|
||||||
return {
|
return {
|
||||||
label: '新建版本',
|
label: t('New Version'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('plus')
|
prefix: icon('plus')
|
||||||
},
|
},
|
||||||
@ -175,7 +176,7 @@ export default {
|
|||||||
GenericDialog,
|
GenericDialog,
|
||||||
{
|
{
|
||||||
options: {
|
options: {
|
||||||
title: `为 ${app.pg.title} 添加版本支持`,
|
title: t('Add version support for {appTitle}', { appTitle: app.pg.title }),
|
||||||
size: '4xl'
|
size: '4xl'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -183,16 +184,16 @@ export default {
|
|||||||
default: () =>
|
default: () =>
|
||||||
h(ObjectList, {
|
h(ObjectList, {
|
||||||
options: {
|
options: {
|
||||||
label: '版本',
|
label: t('Version'),
|
||||||
fieldname: 'version',
|
fieldname: 'version',
|
||||||
fieldtype: 'ListSelection',
|
fieldtype: 'ListSelection',
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '版本',
|
label: t('Version'),
|
||||||
fieldname: 'version'
|
fieldname: 'version'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '分支',
|
label: t('Branch'),
|
||||||
type: 'Select',
|
type: 'Select',
|
||||||
fieldname: 'branch',
|
fieldname: 'branch',
|
||||||
format: (value, row) => {
|
format: (value, row) => {
|
||||||
@ -214,7 +215,7 @@ export default {
|
|||||||
width: '5rem',
|
width: '5rem',
|
||||||
Button({ row, listResource: versionsOptions }) {
|
Button({ row, listResource: versionsOptions }) {
|
||||||
return {
|
return {
|
||||||
label: '添加',
|
label: t('Add'),
|
||||||
onClick() {
|
onClick() {
|
||||||
if (app.addVersion.loading) return;
|
if (app.addVersion.loading) return;
|
||||||
toast.promise(
|
toast.promise(
|
||||||
@ -223,11 +224,11 @@ export default {
|
|||||||
branch: row.selectedOption
|
branch: row.selectedOption
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: '正在添加新版本...',
|
loading: t('Adding new version...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
versions.reload();
|
versions.reload();
|
||||||
versionsOptions.reload();
|
versionsOptions.reload();
|
||||||
return '新版本已添加';
|
return t('New version added');
|
||||||
},
|
},
|
||||||
error: e => getToastErrorMessage(e)
|
error: e => getToastErrorMessage(e)
|
||||||
}
|
}
|
||||||
@ -257,7 +258,7 @@ export default {
|
|||||||
rowActions({ row, listResource: versions, documentResource: app }) {
|
rowActions({ row, listResource: versions, documentResource: app }) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '显示发布',
|
label: t('Show Releases'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('plus')
|
prefix: icon('plus')
|
||||||
},
|
},
|
||||||
@ -266,7 +267,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '更改分支',
|
label: t('Change Branch'),
|
||||||
onClick() {
|
onClick() {
|
||||||
renderDialog(
|
renderDialog(
|
||||||
h(ChangeAppBranchDialog, {
|
h(ChangeAppBranchDialog, {
|
||||||
@ -282,15 +283,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '移除版本',
|
label: t('Remove Version'),
|
||||||
onClick() {
|
onClick() {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
app.removeVersion.submit({ version: row.version }),
|
app.removeVersion.submit({ version: row.version }),
|
||||||
{
|
{
|
||||||
loading: '正在移除版本...',
|
loading: t('Removing version...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
versions.reload();
|
versions.reload();
|
||||||
return '版本已成功移除';
|
return t('Version removed successfully');
|
||||||
},
|
},
|
||||||
error: e => getToastErrorMessage(e)
|
error: e => getToastErrorMessage(e)
|
||||||
}
|
}
|
||||||
@ -302,7 +303,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '定价',
|
label: t('Pricing'),
|
||||||
icon: icon('dollar-sign'),
|
icon: icon('dollar-sign'),
|
||||||
route: 'pricing',
|
route: 'pricing',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
@ -314,26 +315,26 @@ export default {
|
|||||||
fields: ['name', 'title', 'price_cny', 'price_usd', 'enabled'],
|
fields: ['name', 'title', 'price_cny', 'price_usd', 'enabled'],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '标题',
|
label: t('Title'),
|
||||||
fieldname: 'title'
|
fieldname: 'title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '启用',
|
label: t('Enabled'),
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
fieldname: 'enabled',
|
fieldname: 'enabled',
|
||||||
format: value => {
|
format: value => {
|
||||||
return value == 1 ? '已启用' : '已禁用';
|
return value == 1 ? t('Enabled') : t('Disabled');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '价格 (CNY)',
|
label: t('Price CNY'),
|
||||||
fieldname: 'price_cny',
|
fieldname: 'price_cny',
|
||||||
format: value => {
|
format: value => {
|
||||||
return currency(value, 'CNY');
|
return currency(value, 'CNY');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '价格 (USD)',
|
label: t('Price USD'),
|
||||||
fieldname: 'price_usd',
|
fieldname: 'price_usd',
|
||||||
format: value => {
|
format: value => {
|
||||||
return currency(value, 'USD');
|
return currency(value, 'USD');
|
||||||
@ -342,7 +343,7 @@ export default {
|
|||||||
],
|
],
|
||||||
primaryAction({ listResource: plans, documentResource: app }) {
|
primaryAction({ listResource: plans, documentResource: app }) {
|
||||||
return {
|
return {
|
||||||
label: '新建计划',
|
label: t('New Plan'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('plus')
|
prefix: icon('plus')
|
||||||
},
|
},
|
||||||
@ -361,7 +362,7 @@ export default {
|
|||||||
rowActions({ row, listResource: plans, documentResource: app }) {
|
rowActions({ row, listResource: plans, documentResource: app }) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '编辑',
|
label: t('Edit'),
|
||||||
onClick() {
|
onClick() {
|
||||||
renderDialog(
|
renderDialog(
|
||||||
h(PlansDialog, {
|
h(PlansDialog, {
|
||||||
@ -379,7 +380,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '订阅',
|
label: t('Subscriptions'),
|
||||||
icon: icon('users'),
|
icon: icon('users'),
|
||||||
route: 'subscription',
|
route: 'subscription',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
@ -396,30 +397,30 @@ export default {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '状态',
|
label: t('Status'),
|
||||||
class: !isMobile() ? 'w-24' : '',
|
class: !isMobile() ? 'w-24' : '',
|
||||||
fieldname: 'enabled',
|
fieldname: 'enabled',
|
||||||
options: ['', '激活', '禁用']
|
options: ['', t('Active'), t('Disabled')]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '站点',
|
label: t('Site'),
|
||||||
fieldname: 'site',
|
fieldname: 'site',
|
||||||
width: 0.6
|
width: 0.6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: t('Status'),
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
fieldname: 'enabled',
|
fieldname: 'enabled',
|
||||||
width: 0.3,
|
width: 0.3,
|
||||||
format: value => {
|
format: value => {
|
||||||
return value ? '激活' : '禁用';
|
return value ? t('Active') : t('Disabled');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '价格',
|
label: t('Price'),
|
||||||
fieldname: 'price',
|
fieldname: 'price',
|
||||||
width: 0.3,
|
width: 0.3,
|
||||||
format: value => {
|
format: value => {
|
||||||
@ -427,11 +428,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '已激活天数',
|
label: t('Active Days'),
|
||||||
fieldname: 'active_for',
|
fieldname: 'active_for',
|
||||||
width: 0.3,
|
width: 0.3,
|
||||||
format: value => {
|
format: value => {
|
||||||
return value + (value == 1 ? ' 天' : ' 天');
|
return value + (value == 1 ? ` ${t('day')}` : ` ${t('days')}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -441,7 +442,7 @@ export default {
|
|||||||
actions({ documentResource: app }) {
|
actions({ documentResource: app }) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '在市场中查看',
|
label: t('View in Marketplace'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('external-link')
|
prefix: icon('external-link')
|
||||||
},
|
},
|
||||||
@ -454,7 +455,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '指南',
|
label: t('Guide'),
|
||||||
slots: {
|
slots: {
|
||||||
icon: icon('help-circle')
|
icon: icon('help-circle')
|
||||||
},
|
},
|
||||||
@ -467,7 +468,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '完成列表',
|
label: t('Complete Listing'),
|
||||||
variant: 'solid',
|
variant: 'solid',
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('alert-circle')
|
prefix: icon('alert-circle')
|
||||||
@ -486,24 +487,24 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项',
|
label: t('Options'),
|
||||||
condition: () => app.pg.status === 'Draft',
|
condition: () => app.pg.status === 'Draft',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '删除',
|
label: t('Delete'),
|
||||||
icon: icon('trash-2'),
|
icon: icon('trash-2'),
|
||||||
condition: () => app.pg.status === 'Draft',
|
condition: () => app.pg.status === 'Draft',
|
||||||
onClick() {
|
onClick() {
|
||||||
confirmDialog({
|
confirmDialog({
|
||||||
title: `删除应用 ${app.pg.title}`,
|
title: t('Delete app {appTitle}', { appTitle: app.pg.title }),
|
||||||
message: '您确定要删除此应用吗?',
|
message: t('Are you sure you want to delete this app?'),
|
||||||
onSuccess({ hide }) {
|
onSuccess({ hide }) {
|
||||||
toast.promise(app.delete.submit(), {
|
toast.promise(app.delete.submit(), {
|
||||||
loading: '正在删除应用...',
|
loading: t('Deleting app...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
hide();
|
hide();
|
||||||
router.push({ name: 'Marketplace App List' });
|
router.push({ name: 'Marketplace App List' });
|
||||||
return '应用删除成功';
|
return t('App deleted successfully');
|
||||||
},
|
},
|
||||||
error: e => getToastErrorMessage(e)
|
error: e => getToastErrorMessage(e)
|
||||||
});
|
});
|
||||||
@ -524,7 +525,7 @@ function showReleases(row, app) {
|
|||||||
GenericDialog,
|
GenericDialog,
|
||||||
{
|
{
|
||||||
options: {
|
options: {
|
||||||
title: `${app.pg.name} 在 ${row.branch} 分支的发布`,
|
title: t('Releases for {appName} on {branch} branch', { appName: app.pg.name, branch: row.branch }),
|
||||||
size: '6xl'
|
size: '6xl'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -532,7 +533,7 @@ function showReleases(row, app) {
|
|||||||
default: () =>
|
default: () =>
|
||||||
h(ObjectList, {
|
h(ObjectList, {
|
||||||
options: {
|
options: {
|
||||||
label: '版本',
|
label: t('Version'),
|
||||||
type: 'list',
|
type: 'list',
|
||||||
pagetype: 'App Release',
|
pagetype: 'App Release',
|
||||||
filters: {
|
filters: {
|
||||||
@ -543,13 +544,13 @@ function showReleases(row, app) {
|
|||||||
orderBy: 'creation desc',
|
orderBy: 'creation desc',
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '提交信息',
|
label: t('Commit Message'),
|
||||||
fieldname: 'message',
|
fieldname: 'message',
|
||||||
class: 'w-64',
|
class: 'w-64',
|
||||||
width: 0.5
|
width: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '哈希值',
|
label: t('Hash'),
|
||||||
fieldname: 'hash',
|
fieldname: 'hash',
|
||||||
class: 'w-24',
|
class: 'w-24',
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
@ -559,18 +560,18 @@ function showReleases(row, app) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '作者',
|
label: t('Author'),
|
||||||
fieldname: 'author',
|
fieldname: 'author',
|
||||||
width: 0.2
|
width: 0.2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: t('Status'),
|
||||||
fieldname: 'status',
|
fieldname: 'status',
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
width: 0.3
|
width: 0.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '代码审查',
|
label: t('Code Review'),
|
||||||
type: 'Component',
|
type: 'Component',
|
||||||
width: 0.2,
|
width: 0.2,
|
||||||
component: ({ row, listResource: releases, app }) => {
|
component: ({ row, listResource: releases, app }) => {
|
||||||
@ -580,7 +581,7 @@ function showReleases(row, app) {
|
|||||||
row.screening_status === 'Complete'
|
row.screening_status === 'Complete'
|
||||||
) {
|
) {
|
||||||
return h(Button, {
|
return h(Button, {
|
||||||
label: '代码审查',
|
label: t('Code Review'),
|
||||||
variant: 'subtle',
|
variant: 'subtle',
|
||||||
theme: 'blue',
|
theme: 'blue',
|
||||||
size: 'sm',
|
size: 'sm',
|
||||||
@ -589,7 +590,7 @@ function showReleases(row, app) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return h(Badge, {
|
return h(Badge, {
|
||||||
label: row.screening_status || '未开始'
|
label: row.screening_status || t('Not Started')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -605,14 +606,13 @@ function showReleases(row, app) {
|
|||||||
let loadingMessage = '';
|
let loadingMessage = '';
|
||||||
|
|
||||||
if (row.status === 'Awaiting Approval') {
|
if (row.status === 'Awaiting Approval') {
|
||||||
label = '取消';
|
label = t('Cancel');
|
||||||
successMessage = '发布已取消';
|
successMessage = t('Release cancelled');
|
||||||
loadingMessage = '正在取消发布...';
|
loadingMessage = t('Cancelling release...');
|
||||||
} else if (row.status === 'Draft') {
|
} else if (row.status === 'Draft') {
|
||||||
label = '提交';
|
label = t('Submit');
|
||||||
loadingMessage = '正在提交发布以供审批...';
|
loadingMessage = t('Submitting release for approval...');
|
||||||
successMessage =
|
successMessage = t('Release submitted for approval');
|
||||||
'发布已提交以供审批';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -372,15 +372,15 @@ export default {
|
|||||||
'Archived': t('Archived'),
|
'Archived': t('Archived'),
|
||||||
'Pending': t('Pending'),
|
'Pending': t('Pending'),
|
||||||
'Installing': t('Installing'),
|
'Installing': t('Installing'),
|
||||||
'Running': '运行中',
|
'Running': t('Running'),
|
||||||
'Success': '成功',
|
'Success': t('Success'),
|
||||||
'Failure': '失败'
|
'Failure': t('Failure')
|
||||||
};
|
};
|
||||||
return statusMap[value] || value;
|
return statusMap[value] || value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '主域名',
|
label: t('Primary Domain'),
|
||||||
fieldname: 'primary',
|
fieldname: 'primary',
|
||||||
type: 'Icon',
|
type: 'Icon',
|
||||||
Icon(value) {
|
Icon(value) {
|
||||||
@ -388,7 +388,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'DNS 类型',
|
label: t('DNS Type'),
|
||||||
fieldname: 'dns_type',
|
fieldname: 'dns_type',
|
||||||
type: 'Badge',
|
type: 'Badge',
|
||||||
},
|
},
|
||||||
@ -396,11 +396,10 @@ export default {
|
|||||||
banner({ documentResource: site }) {
|
banner({ documentResource: site }) {
|
||||||
if (site.pg.broken_domain_error) {
|
if (site.pg.broken_domain_error) {
|
||||||
return {
|
return {
|
||||||
title:
|
title: t('Error occurred while obtaining HTTPS certificate for your domain.'),
|
||||||
'获取您的域名的 HTTPS 证书时出错。',
|
|
||||||
type: 'error',
|
type: 'error',
|
||||||
button: {
|
button: {
|
||||||
label: '查看错误',
|
label: t('View Error'),
|
||||||
variant: 'outline',
|
variant: 'outline',
|
||||||
onClick() {
|
onClick() {
|
||||||
renderDialog(
|
renderDialog(
|
||||||
@ -408,7 +407,7 @@ export default {
|
|||||||
GenericDialog,
|
GenericDialog,
|
||||||
{
|
{
|
||||||
options: {
|
options: {
|
||||||
title: '获取证书时出错',
|
title: t('Error obtaining certificate'),
|
||||||
size: 'xl',
|
size: 'xl',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -432,7 +431,7 @@ export default {
|
|||||||
},
|
},
|
||||||
primaryAction({ listResource: domains, documentResource: site }) {
|
primaryAction({ listResource: domains, documentResource: site }) {
|
||||||
return {
|
return {
|
||||||
label: '添加域名',
|
label: t('Add Domain'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('plus'),
|
prefix: icon('plus'),
|
||||||
},
|
},
|
||||||
@ -451,12 +450,12 @@ export default {
|
|||||||
rowActions({ row, listResource: domains, documentResource: site }) {
|
rowActions({ row, listResource: domains, documentResource: site }) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '移除',
|
label: t('Remove'),
|
||||||
condition: () => row.domain !== site.pg?.name,
|
condition: () => row.domain !== site.pg?.name,
|
||||||
onClick() {
|
onClick() {
|
||||||
confirmDialog({
|
confirmDialog({
|
||||||
title: `移除域名`,
|
title: t('Remove Domain'),
|
||||||
message: `您确定要从站点 <b>${site.pg?.name}</b> 中移除域名 <b>${row.domain}</b> 吗?`,
|
message: t('Are you sure you want to remove domain <b>{domain}</b> from site <b>{site}</b>?', { domain: row.domain, site: site.pg?.name }),
|
||||||
onSuccess({ hide }) {
|
onSuccess({ hide }) {
|
||||||
if (site.removeDomain.loading) return;
|
if (site.removeDomain.loading) return;
|
||||||
toast.promise(
|
toast.promise(
|
||||||
@ -532,15 +531,15 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '移除重定向',
|
label: t('Remove Redirect'),
|
||||||
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('Remove Redirect'),
|
||||||
message: `您确定要移除从域名 <b>${row.domain}</b> 到站点 <b>${site.pg?.name}</b> 主域名的重定向吗?`,
|
message: t('Are you sure you want to remove redirect from domain <b>{domain}</b> to primary domain of site <b>{site}</b>?', { domain: row.domain, site: site.pg?.name }),
|
||||||
onSuccess({ hide }) {
|
onSuccess({ hide }) {
|
||||||
if (site.removeRedirect.loading) return;
|
if (site.removeRedirect.loading) return;
|
||||||
toast.promise(
|
toast.promise(
|
||||||
@ -548,10 +547,10 @@ export default {
|
|||||||
domain: row.domain,
|
domain: row.domain,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: '正在移除重定向...',
|
loading: t('Removing redirect...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
hide();
|
hide();
|
||||||
return '重定向已移除';
|
return t('Redirect removed');
|
||||||
},
|
},
|
||||||
error: (e) => getToastErrorMessage(e),
|
error: (e) => getToastErrorMessage(e),
|
||||||
},
|
},
|
||||||
@ -565,7 +564,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '备份',
|
label: t('Backups'),
|
||||||
icon: icon('archive'),
|
icon: icon('archive'),
|
||||||
route: 'backups',
|
route: 'backups',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
@ -595,16 +594,16 @@ export default {
|
|||||||
],
|
],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '时间戳',
|
label: t('Timestamp'),
|
||||||
fieldname: 'creation',
|
fieldname: 'creation',
|
||||||
width: 1,
|
width: 1,
|
||||||
format(value) {
|
format(value) {
|
||||||
return `备份于 ${date(value, 'llll')}`;
|
return t('Backed up on {date}', { date: date(value, 'llll') });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: '数据库',
|
label: t('Database'),
|
||||||
fieldname: 'database_size',
|
fieldname: 'database_size',
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
format(value) {
|
format(value) {
|
||||||
@ -612,7 +611,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '公共文件',
|
label: t('Public Files'),
|
||||||
fieldname: 'public_size',
|
fieldname: 'public_size',
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
format(value) {
|
format(value) {
|
||||||
@ -620,7 +619,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '私有文件',
|
label: t('Private Files'),
|
||||||
fieldname: 'private_size',
|
fieldname: 'private_size',
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
format(value) {
|
format(value) {
|
||||||
@ -628,7 +627,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '包含文件的备份',
|
label: t('Backup with Files'),
|
||||||
fieldname: 'with_files',
|
fieldname: 'with_files',
|
||||||
type: 'Icon',
|
type: 'Icon',
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
@ -637,7 +636,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '异地备份',
|
label: t('Offsite Backup'),
|
||||||
fieldname: 'offsite',
|
fieldname: 'offsite',
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
type: 'Icon',
|
type: 'Icon',
|
||||||
@ -650,7 +649,7 @@ export default {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
label: '异地备份',
|
label: t('Offsite Backup'),
|
||||||
fieldname: 'offsite',
|
fieldname: 'offsite',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -658,23 +657,21 @@ export default {
|
|||||||
rowActions({ row, documentResource: site }) {
|
rowActions({ row, documentResource: site }) {
|
||||||
if (row.status != 'Success') return;
|
if (row.status != 'Success') return;
|
||||||
|
|
||||||
function getFileName(file) {
|
|
||||||
if (file == 'database') return 'database';
|
|
||||||
if (file == 'public') return 'public files';
|
|
||||||
if (file == 'private') return 'private files';
|
|
||||||
if (file == 'config') return 'config file';
|
|
||||||
}
|
|
||||||
|
|
||||||
function confirmDownload(backup, file) {
|
function confirmDownload(backup, file) {
|
||||||
|
const fileNameMap = {
|
||||||
|
'database': t('database'),
|
||||||
|
'public': t('public files'),
|
||||||
|
'private': t('private files'),
|
||||||
|
'config': t('config file')
|
||||||
|
};
|
||||||
|
const fileName = fileNameMap[file] || file;
|
||||||
|
const message = !backup.offsite
|
||||||
|
? t('You will download the {fileName} backup for site <b>{siteName}</b>, created on {date}.<br><br><div class="p-2 bg-gray-100 border-gray-200 rounded">You need to log in as <b>System Administrator</b> on <em>your site</em> to download the backup.<div>', { fileName, siteName: site.pg?.host_name || site.pg?.name, date: date(backup.creation, 'llll') })
|
||||||
|
: t('You will download the {fileName} backup for site <b>{siteName}</b>, created on {date}.', { fileName, siteName: site.pg?.host_name || site.pg?.name, date: date(backup.creation, 'llll') });
|
||||||
confirmDialog({
|
confirmDialog({
|
||||||
title: '下载备份',
|
title: t('Download Backup'),
|
||||||
message: `您将下载站点 <b>${
|
message: message,
|
||||||
site.pg?.host_name || site.pg?.name
|
|
||||||
}</b> 的 ${getFileName(file)} 备份,该备份创建于 ${date(backup.creation, 'llll')}。${
|
|
||||||
!backup.offsite
|
|
||||||
? '<br><br><div class="p-2 bg-gray-100 border-gray-200 rounded">您需要以 <b>系统管理员</b> 身份登录 <em>您的站点</em> 才能下载备份。<div>'
|
|
||||||
: ''
|
|
||||||
}`,
|
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
downloadBackup(backup, file);
|
downloadBackup(backup, file);
|
||||||
},
|
},
|
||||||
@ -712,10 +709,10 @@ export default {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
group: '详情',
|
group: t('Details'),
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: '查看任务',
|
label: t('View Job'),
|
||||||
onClick() {
|
onClick() {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'Site Job',
|
name: 'Site Job',
|
||||||
@ -726,30 +723,30 @@ export default {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
group: '下载',
|
group: t('Download'),
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: '下载数据库',
|
label: t('Download Database'),
|
||||||
onClick() {
|
onClick() {
|
||||||
return confirmDownload(row, 'database');
|
return confirmDownload(row, 'database');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '下载公共文件',
|
label: t('Download Public Files'),
|
||||||
onClick() {
|
onClick() {
|
||||||
return confirmDownload(row, 'public');
|
return confirmDownload(row, 'public');
|
||||||
},
|
},
|
||||||
condition: () => row.public_url,
|
condition: () => row.public_url,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '下载私有文件',
|
label: t('Download Private Files'),
|
||||||
onClick() {
|
onClick() {
|
||||||
return confirmDownload(row, 'private');
|
return confirmDownload(row, 'private');
|
||||||
},
|
},
|
||||||
condition: () => row.private_url,
|
condition: () => row.private_url,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '下载配置文件',
|
label: t('Download Config File'),
|
||||||
onClick() {
|
onClick() {
|
||||||
return confirmDownload(row, 'config');
|
return confirmDownload(row, 'config');
|
||||||
},
|
},
|
||||||
@ -758,18 +755,16 @@ export default {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
group: '恢复',
|
group: t('Restore'),
|
||||||
condition: () => row.offsite,
|
condition: () => row.offsite,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: '恢复备份',
|
label: t('Restore Backup'),
|
||||||
condition: () => site.pg.status !== 'Archived',
|
condition: () => site.pg.status !== 'Archived',
|
||||||
onClick() {
|
onClick() {
|
||||||
confirmDialog({
|
confirmDialog({
|
||||||
title: '恢复备份',
|
title: t('Restore Backup'),
|
||||||
message: `您确定要将您的站点恢复到<b>${dayjs(
|
message: t('Are you sure you want to restore your site to the offsite backup from <b>{date}</b>?', { date: dayjs(row.creation).format('lll') }),
|
||||||
row.creation,
|
|
||||||
).format('lll')}</b>的异地备份吗?`,
|
|
||||||
onSuccess({ hide }) {
|
onSuccess({ hide }) {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
site.restoreSiteFromFiles.submit({
|
site.restoreSiteFromFiles.submit({
|
||||||
@ -781,7 +776,7 @@ export default {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: '正在安排备份恢复...',
|
loading: t('Scheduling backup restore...'),
|
||||||
success: (jobId) => {
|
success: (jobId) => {
|
||||||
hide();
|
hide();
|
||||||
router.push({
|
router.push({
|
||||||
@ -791,7 +786,7 @@ export default {
|
|||||||
id: jobId,
|
id: jobId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return '备份恢复已成功安排。';
|
return t('Backup restore scheduled successfully.');
|
||||||
},
|
},
|
||||||
error: (e) => getToastErrorMessage(e),
|
error: (e) => getToastErrorMessage(e),
|
||||||
},
|
},
|
||||||
@ -801,7 +796,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '在另一个站点上恢复备份',
|
label: t('Restore Backup on Another Site'),
|
||||||
onClick() {
|
onClick() {
|
||||||
let SelectSiteForRestore = defineAsyncComponent(
|
let SelectSiteForRestore = defineAsyncComponent(
|
||||||
() =>
|
() =>
|
||||||
@ -826,13 +821,13 @@ export default {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: '正在安排备份恢复...',
|
loading: t('Scheduling backup restore...'),
|
||||||
success: (jobId) => {
|
success: (jobId) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'Site Job',
|
name: 'Site Job',
|
||||||
params: { name: siteName, id: jobId },
|
params: { name: siteName, id: jobId },
|
||||||
});
|
});
|
||||||
return '备份恢复已成功安排。';
|
return t('Backup restore scheduled successfully.');
|
||||||
},
|
},
|
||||||
error: (e) => getToastErrorMessage(e),
|
error: (e) => getToastErrorMessage(e),
|
||||||
},
|
},
|
||||||
@ -848,30 +843,29 @@ export default {
|
|||||||
},
|
},
|
||||||
primaryAction({ listResource: backups, documentResource: site }) {
|
primaryAction({ listResource: backups, documentResource: site }) {
|
||||||
return {
|
return {
|
||||||
label: '安排备份',
|
label: t('Schedule Backup'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('upload-cloud'),
|
prefix: icon('upload-cloud'),
|
||||||
},
|
},
|
||||||
loading: site.backup.loading,
|
loading: site.backup.loading,
|
||||||
onClick() {
|
onClick() {
|
||||||
confirmDialog({
|
confirmDialog({
|
||||||
title: '安排备份',
|
title: t('Schedule Backup'),
|
||||||
message:
|
message: t('Are you sure you want to schedule a backup? This will create a local backup.'),
|
||||||
'您确定要安排备份吗?这将创建一个本地备份。',
|
|
||||||
onSuccess({ hide }) {
|
onSuccess({ hide }) {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
site.backup.submit({
|
site.backup.submit({
|
||||||
with_files: true,
|
with_files: true,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
loading: '正在安排备份...',
|
loading: t('Scheduling backup...'),
|
||||||
success: () => {
|
success: () => {
|
||||||
hide();
|
hide();
|
||||||
router.push({
|
router.push({
|
||||||
name: 'Site Jobs',
|
name: 'Site Jobs',
|
||||||
params: { name: site.name },
|
params: { name: site.name },
|
||||||
});
|
});
|
||||||
return '备份已成功安排。';
|
return t('Backup scheduled successfully.');
|
||||||
},
|
},
|
||||||
error: (e) => getToastErrorMessage(e),
|
error: (e) => getToastErrorMessage(e),
|
||||||
},
|
},
|
||||||
@ -1070,7 +1064,7 @@ export default {
|
|||||||
GenericDialog,
|
GenericDialog,
|
||||||
{
|
{
|
||||||
options: {
|
options: {
|
||||||
title: '应用更改',
|
title: t('App Changes'),
|
||||||
size: '2xl',
|
size: '2xl',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1081,11 +1075,11 @@ export default {
|
|||||||
data: () => data,
|
data: () => data,
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
label: '应用',
|
label: t('App'),
|
||||||
fieldname: 'app',
|
fieldname: 'app',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '从',
|
label: t('From'),
|
||||||
fieldname: 'source_hash',
|
fieldname: 'source_hash',
|
||||||
type: 'Button',
|
type: 'Button',
|
||||||
Button({ row }) {
|
Button({ row }) {
|
||||||
@ -1102,7 +1096,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '到',
|
label: t('To'),
|
||||||
fieldname: 'destination_hash',
|
fieldname: 'destination_hash',
|
||||||
type: 'Button',
|
type: 'Button',
|
||||||
Button({ row }) {
|
Button({ row }) {
|
||||||
@ -1119,13 +1113,13 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '应用变更',
|
label: t('App Changes'),
|
||||||
fieldname: 'diff_url',
|
fieldname: 'diff_url',
|
||||||
align: 'right',
|
align: 'right',
|
||||||
type: 'Button',
|
type: 'Button',
|
||||||
Button({ row }) {
|
Button({ row }) {
|
||||||
return {
|
return {
|
||||||
label: '查看',
|
label: t('View'),
|
||||||
variant: 'ghost',
|
variant: 'ghost',
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('external-link'),
|
prefix: icon('external-link'),
|
||||||
@ -1140,7 +1134,7 @@ export default {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else toast.error('未找到应用变更');
|
} else toast.error(t('No app changes found'));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -1152,7 +1146,7 @@ export default {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '配置',
|
label: t('Config'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('settings'),
|
prefix: icon('settings'),
|
||||||
},
|
},
|
||||||
@ -1184,7 +1178,7 @@ export default {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '进行中的任务',
|
label: t('Jobs in Progress'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: () => h(LoadingIndicator, { class: 'w-4 h-4' }),
|
prefix: () => h(LoadingIndicator, { class: 'w-4 h-4' }),
|
||||||
},
|
},
|
||||||
@ -1203,7 +1197,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '有可用更新',
|
label: t('Update Available'),
|
||||||
variant: site.pg?.setup_wizard_complete ? 'solid' : 'subtle',
|
variant: site.pg?.setup_wizard_complete ? 'solid' : 'subtle',
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('alert-circle'),
|
prefix: icon('alert-circle'),
|
||||||
@ -1226,7 +1220,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '已安排更新',
|
label: t('Scheduled Updates'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('calendar'),
|
prefix: icon('calendar'),
|
||||||
},
|
},
|
||||||
@ -1239,8 +1233,8 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '模拟站点所有者',
|
label: t('Impersonate Site Owner'),
|
||||||
title: '模拟站点所有者', // for label to pop-up on hover
|
title: t('Impersonate Site Owner'), // for label to pop-up on hover
|
||||||
slots: {
|
slots: {
|
||||||
icon: defineAsyncComponent(
|
icon: defineAsyncComponent(
|
||||||
() => import('~icons/lucide/venetian-mask'),
|
() => import('~icons/lucide/venetian-mask'),
|
||||||
@ -1253,7 +1247,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '访问站点',
|
label: t('Visit Site'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('external-link'),
|
prefix: icon('external-link'),
|
||||||
},
|
},
|
||||||
@ -1264,7 +1258,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '设置站点',
|
label: t('Setup Site'),
|
||||||
slots: {
|
slots: {
|
||||||
prefix: icon('external-link'),
|
prefix: icon('external-link'),
|
||||||
},
|
},
|
||||||
@ -1284,11 +1278,11 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项',
|
label: t('Options'),
|
||||||
context,
|
context,
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '在 Desk 中查看',
|
label: t('View in Desk'),
|
||||||
icon: 'external-link',
|
icon: 'external-link',
|
||||||
condition: () => $team.pg?.is_desk_user,
|
condition: () => $team.pg?.is_desk_user,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@ -1299,18 +1293,18 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '以管理员身份登录',
|
label: t('Login as Administrator'),
|
||||||
icon: 'external-link',
|
icon: 'external-link',
|
||||||
condition: () => ['Active', 'Broken'].includes(site.pg.status),
|
condition: () => ['Active', 'Broken'].includes(site.pg.status),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
confirmDialog({
|
confirmDialog({
|
||||||
title: '以管理员身份登录',
|
title: t('Login as Administrator'),
|
||||||
message: `您确定要以管理员身份登录站点 <b>${site.pg?.name}</b> 吗?`,
|
message: t('Are you sure you want to login as administrator to site <b>{site}</b>?', { site: site.pg?.name }),
|
||||||
fields:
|
fields:
|
||||||
$team.name !== site.pg.team
|
$team.name !== site.pg.team
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
label: '原因',
|
label: t('Reason'),
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
fieldname: 'reason',
|
fieldname: 'reason',
|
||||||
},
|
},
|
||||||
@ -1318,7 +1312,7 @@ export default {
|
|||||||
: [],
|
: [],
|
||||||
onSuccess: ({ hide, values }) => {
|
onSuccess: ({ hide, values }) => {
|
||||||
if (!values.reason && $team.name !== site.pg.team) {
|
if (!values.reason && $team.name !== site.pg.team) {
|
||||||
throw new Error('原因必填');
|
throw new Error(t('Reason is required'));
|
||||||
}
|
}
|
||||||
return site.loginAsAdmin
|
return site.loginAsAdmin
|
||||||
.submit({ reason: values.reason })
|
.submit({ reason: values.reason })
|
||||||
|
|||||||
@ -3,12 +3,12 @@
|
|||||||
<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: 'Apps', route: '/marketplace' }]">
|
<Breadcrumbs :items="[{ label: $t('Apps'), route: '/marketplace' }]">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<Button
|
<Button
|
||||||
variant="solid"
|
variant="solid"
|
||||||
icon-left="plus"
|
icon-left="plus"
|
||||||
label="New"
|
:label="$t('New')"
|
||||||
class="ml-2"
|
class="ml-2"
|
||||||
@click="
|
@click="
|
||||||
!$resources.appOptions.data
|
!$resources.appOptions.data
|
||||||
@ -20,11 +20,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</header>
|
</header>
|
||||||
<SectionHeader class="mx-5 mt-6" heading="Apps" />
|
<SectionHeader class="mx-5 mt-6" :heading="$t('Apps')" />
|
||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
:options="{
|
:options="{
|
||||||
title: 'Add App to Marketplace',
|
title: $t('Add App to Marketplace'),
|
||||||
size: 'xl'
|
size: 'xl'
|
||||||
}"
|
}"
|
||||||
v-model="showAddAppDialog"
|
v-model="showAddAppDialog"
|
||||||
@ -40,7 +40,7 @@
|
|||||||
v-model="selectedApp"
|
v-model="selectedApp"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
/>
|
/>
|
||||||
<p v-else class="text-base">No app sources available.</p>
|
<p v-else class="text-base">{{ $t('No app sources available.') }}</p>
|
||||||
|
|
||||||
<ErrorMessage
|
<ErrorMessage
|
||||||
class="mt-2"
|
class="mt-2"
|
||||||
@ -48,8 +48,8 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<p class="mt-4 text-base" @click="showAddAppDialog = false">
|
<p class="mt-4 text-base" @click="showAddAppDialog = false">
|
||||||
Don't find your app here?
|
{{ $t("Don't find your app here?") }}
|
||||||
<Link :to="`/marketplace/apps/new`"> Add from GitHub </Link>
|
<Link :to="`/marketplace/apps/new`"> {{ $t('Add from GitHub') }} </Link>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
@ -65,7 +65,7 @@
|
|||||||
})
|
})
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Add {{ selectedApp.app }}
|
{{ $t('Add {app}', { app: selectedApp.app }) }}
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
@ -84,19 +84,26 @@ export default {
|
|||||||
name: 'Marketplace',
|
name: 'Marketplace',
|
||||||
pageMeta() {
|
pageMeta() {
|
||||||
return {
|
return {
|
||||||
title: 'Developer - 今果 Jingrow'
|
title: this.$t('Developer') + ' - 今果 Jingrow'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Tabs,
|
Tabs,
|
||||||
AppSourceSelector
|
AppSourceSelector
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
tabs() {
|
||||||
|
return [
|
||||||
|
{ label: this.$t('My Apps'), route: '/marketplace/apps' },
|
||||||
|
{ label: this.$t('Publisher Profile'), route: '/marketplace/publisher-profile' },
|
||||||
|
{ label: this.$t('Payouts'), route: '/marketplace/payouts' }
|
||||||
|
];
|
||||||
|
},
|
||||||
|
availableApps() {
|
||||||
|
return this.$resources.appOptions.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
tabs: [
|
|
||||||
{ label: 'My Apps', route: '/marketplace/apps' },
|
|
||||||
{ label: 'Publisher Profile', route: '/marketplace/publisher-profile' },
|
|
||||||
{ label: 'Payouts', route: '/marketplace/payouts' }
|
|
||||||
],
|
|
||||||
showAddAppDialog: false,
|
showAddAppDialog: false,
|
||||||
selectedApp: null
|
selectedApp: null
|
||||||
}),
|
}),
|
||||||
@ -116,11 +123,6 @@ export default {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
availableApps() {
|
|
||||||
return this.$resources.appOptions.data;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activated() {
|
activated() {
|
||||||
if (this.$route.matched.length === 1) {
|
if (this.$route.matched.length === 1) {
|
||||||
let path = this.$route.fullPath;
|
let path = this.$route.fullPath;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
:items="[
|
:items="[
|
||||||
{
|
{
|
||||||
label: 'Apps',
|
label: $t('Apps'),
|
||||||
route: {
|
route: {
|
||||||
name: 'Marketplace',
|
name: 'Marketplace',
|
||||||
params: { appName: app.name }
|
params: { appName: app.name }
|
||||||
@ -27,7 +27,7 @@
|
|||||||
v-if="app.status === 'Published'"
|
v-if="app.status === 'Published'"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
icon-left="external-link"
|
icon-left="external-link"
|
||||||
label="View in Marketplace"
|
:label="$t('View in Marketplace')"
|
||||||
class="ml-2"
|
class="ml-2"
|
||||||
:link="`/marketplace/apps/${app.name}`"
|
:link="`/marketplace/apps/${app.name}`"
|
||||||
/>
|
/>
|
||||||
@ -96,34 +96,34 @@ export default {
|
|||||||
},
|
},
|
||||||
tabs() {
|
tabs() {
|
||||||
let tabsByStatus = {
|
let tabsByStatus = {
|
||||||
Draft: ['Overview', 'Releases', 'Review'],
|
Draft: [this.$t('Overview'), this.$t('Releases'), this.$t('Review')],
|
||||||
'In Review': ['Overview', 'Releases', 'Review'],
|
'In Review': [this.$t('Overview'), this.$t('Releases'), this.$t('Review')],
|
||||||
Rejected: ['Overview', 'Releases', 'Review'],
|
Rejected: [this.$t('Overview'), this.$t('Releases'), this.$t('Review')],
|
||||||
Published: [
|
Published: [
|
||||||
'Overview',
|
this.$t('Overview'),
|
||||||
'Releases',
|
this.$t('Releases'),
|
||||||
'Analytics',
|
this.$t('Analytics'),
|
||||||
'Subscriptions',
|
this.$t('Subscriptions'),
|
||||||
'Pricing'
|
this.$t('Pricing')
|
||||||
],
|
],
|
||||||
'Attention Required': [
|
'Attention Required': [
|
||||||
'Overview',
|
this.$t('Overview'),
|
||||||
'Releases',
|
this.$t('Releases'),
|
||||||
'Review',
|
this.$t('Review'),
|
||||||
'Analytics',
|
this.$t('Analytics'),
|
||||||
'Subscriptions',
|
this.$t('Subscriptions'),
|
||||||
'Pricing'
|
this.$t('Pricing')
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
let tabRoute = subRoute =>
|
let tabRoute = subRoute =>
|
||||||
`/marketplace/apps/${this.appName}/${subRoute}`;
|
`/marketplace/apps/${this.appName}/${subRoute}`;
|
||||||
let tabs = [
|
let tabs = [
|
||||||
{ label: 'Overview', route: 'overview' },
|
{ label: this.$t('Overview'), route: 'overview' },
|
||||||
{ label: 'Releases', route: 'releases' },
|
{ label: this.$t('Releases'), route: 'releases' },
|
||||||
{ label: 'Review', route: 'review' },
|
{ label: this.$t('Review'), route: 'review' },
|
||||||
{ label: 'Analytics', route: 'analytics' },
|
{ label: this.$t('Analytics'), route: 'analytics' },
|
||||||
{ label: 'Subscriptions', route: 'subscriptions' },
|
{ label: this.$t('Subscriptions'), route: 'subscriptions' },
|
||||||
{ label: 'Pricing', route: 'pricing' }
|
{ label: this.$t('Pricing'), route: 'pricing' }
|
||||||
];
|
];
|
||||||
|
|
||||||
if (this.app) {
|
if (this.app) {
|
||||||
|
|||||||
@ -3,19 +3,19 @@
|
|||||||
v-if="$resources.analytics.data"
|
v-if="$resources.analytics.data"
|
||||||
class="grid grid-cols-1 gap-5 sm:grid-cols-2"
|
class="grid grid-cols-1 gap-5 sm:grid-cols-2"
|
||||||
>
|
>
|
||||||
<Card title="Earnings">
|
<Card :title="$t('Earnings')">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<a
|
<a
|
||||||
class="text-base text-gray-700 hover:text-gray-800"
|
class="text-base text-gray-700 hover:text-gray-800"
|
||||||
href="/support/tickets"
|
href="/support/tickets"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
Contact Support →
|
{{ $t('Contact Support') }} →
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<ListItem
|
<ListItem
|
||||||
title="Total Earnings"
|
:title="$t('Total Earnings')"
|
||||||
:subtitle="`Total earnings for ${app.title}`"
|
:subtitle="$t('Total earnings for {app}', { app: app.title })"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<span class="text-base font-semibold text-green-500">{{
|
<span class="text-base font-semibold text-green-500">{{
|
||||||
@ -28,8 +28,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
title="Pending Payout"
|
:title="$t('Pending Payout')"
|
||||||
subtitle="Payout you are yet to receive from 今果 Jingrow"
|
:subtitle="$t('Payout you are yet to receive from 今果 Jingrow')"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<span class="text-base font-semibold">{{
|
<span class="text-base font-semibold">{{
|
||||||
@ -42,8 +42,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
title="Commission"
|
:title="$t('Commission')"
|
||||||
subtitle="Payouts start once you have passed $500 threshold"
|
:subtitle="$t('Payouts start once you have passed $500 threshold')"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<span class="text-base font-semibold">{{
|
<span class="text-base font-semibold">{{
|
||||||
@ -56,7 +56,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</Card>
|
</Card>
|
||||||
<Card title="Installs">
|
<Card :title="$t('Installs')">
|
||||||
<div class="divide-y" v-if="analytics">
|
<div class="divide-y" v-if="analytics">
|
||||||
<ListItem
|
<ListItem
|
||||||
v-for="stat in analytics"
|
v-for="stat in analytics"
|
||||||
@ -68,11 +68,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="py-10 text-center" v-if="$resources.analytics.loading">
|
<div class="py-10 text-center" v-if="$resources.analytics.loading">
|
||||||
<Button :loading="true">Loading</Button>
|
<Button :loading="true">{{ $t('Loading') }}</Button>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
<LineChart
|
<LineChart
|
||||||
title="Pageviews"
|
:title="$t('Pageviews')"
|
||||||
type="time"
|
type="time"
|
||||||
:key="pageViewsData"
|
:key="pageViewsData"
|
||||||
:data="pageViewsData"
|
:data="pageViewsData"
|
||||||
@ -88,12 +88,12 @@
|
|||||||
:href="`/marketplace/apps/${app.app}`"
|
:href="`/marketplace/apps/${app.app}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
View Marketplace Page →
|
{{ $t('View Marketplace Page') }} →
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
</LineChart>
|
</LineChart>
|
||||||
<LineChart
|
<LineChart
|
||||||
title="Unique Visitors"
|
:title="$t('Unique Visitors')"
|
||||||
type="time"
|
type="time"
|
||||||
:key="visitorsData"
|
:key="visitorsData"
|
||||||
:data="visitorsData"
|
:data="visitorsData"
|
||||||
@ -175,25 +175,25 @@ export default {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: 'Total Installs',
|
title: this.$t('Total Installs'),
|
||||||
value:
|
value:
|
||||||
total_installs.toString() +
|
total_installs.toString() +
|
||||||
' ' +
|
' ' +
|
||||||
(total_installs == 1 ? 'Site' : 'Sites')
|
(total_installs == 1 ? this.$t('Site') : this.$t('Sites'))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Active Sites with this App',
|
title: this.$t('Active Sites with this App'),
|
||||||
value:
|
value:
|
||||||
num_installs_active_sites.toString() +
|
num_installs_active_sites.toString() +
|
||||||
' ' +
|
' ' +
|
||||||
(num_installs_active_sites == 1 ? 'Site' : 'Sites')
|
(num_installs_active_sites == 1 ? this.$t('Site') : this.$t('Sites'))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Active Benches with this App',
|
title: this.$t('Active Benches with this App'),
|
||||||
value:
|
value:
|
||||||
num_installs_active_benches.toString() +
|
num_installs_active_benches.toString() +
|
||||||
' ' +
|
' ' +
|
||||||
(num_installs_active_benches == 1 ? 'Bench' : 'Benches')
|
(num_installs_active_benches == 1 ? this.$t('Bench') : this.$t('Benches'))
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ function resetCurrentEditingPlan() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Card title="Pricing Plans" subtitle="Set up pricing plans for this app">
|
<Card :title="$t('Pricing Plans')" :subtitle="$t('Set up pricing plans for this app')">
|
||||||
<div class="m-4">
|
<div class="m-4">
|
||||||
<div class="flex justify-center" v-if="appPlans.loading">
|
<div class="flex justify-center" v-if="appPlans.loading">
|
||||||
<Button :loading="true">Loading</Button>
|
<Button :loading="true">Loading</Button>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const appSubscriptions = createResource({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Card title="Subscriptions">
|
<Card :title="$t('Subscriptions')">
|
||||||
<div v-if="appSubscriptions.data">
|
<div v-if="appSubscriptions.data">
|
||||||
<div v-if="appSubscriptions.data.length === 0">
|
<div v-if="appSubscriptions.data.length === 0">
|
||||||
<p class="my-3 text-center text-base text-gray-600">
|
<p class="my-3 text-center text-base text-gray-600">
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<Button
|
<Button
|
||||||
v-if="$resources.apps.loading && !$resources.apps.data"
|
v-if="$resources.apps.loading && !$resources.apps.data"
|
||||||
:loading="true"
|
:loading="true"
|
||||||
loadingText="Loading..."
|
:loadingText="$t('Loading...')"
|
||||||
></Button>
|
></Button>
|
||||||
<ErrorMessage
|
<ErrorMessage
|
||||||
v-else-if="!$resources.apps.data"
|
v-else-if="!$resources.apps.data"
|
||||||
@ -11,7 +11,7 @@
|
|||||||
/>
|
/>
|
||||||
<div v-else-if="$resources.apps.data.length < 1">
|
<div v-else-if="$resources.apps.data.length < 1">
|
||||||
<p class="text-lg text-gray-600">
|
<p class="text-lg text-gray-600">
|
||||||
You have not published any app on our Marketplace.
|
{{ $t('You have not published any app on our Marketplace.') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
|||||||
@ -17,8 +17,8 @@ const payouts = createResource({
|
|||||||
<template>
|
<template>
|
||||||
<Card
|
<Card
|
||||||
v-if="!props.payoutOrderName"
|
v-if="!props.payoutOrderName"
|
||||||
title="Payouts"
|
:title="$t('Payouts')"
|
||||||
subtitle="Look what you have earned"
|
:subtitle="$t('Look what you have earned')"
|
||||||
>
|
>
|
||||||
<Button v-if="payouts.loading" :loading="true">Loading</Button>
|
<Button v-if="payouts.loading" :loading="true">Loading</Button>
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ const payouts = createResource({
|
|||||||
</div>
|
</div>
|
||||||
<ErrorMessage :message="payouts.error" />
|
<ErrorMessage :message="payouts.error" />
|
||||||
</Card>
|
</Card>
|
||||||
<Card v-else title="Payout Details">
|
<Card v-else :title="$t('Payout Details')">
|
||||||
<template #actions-left>
|
<template #actions-left>
|
||||||
<Button route="/marketplace/payouts"> ← Back </Button>
|
<Button route="/marketplace/payouts"> ← Back </Button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<Button
|
<Button
|
||||||
v-if="$resources.getPublisherProfileInfo.loading"
|
v-if="$resources.getPublisherProfileInfo.loading"
|
||||||
:loading="true"
|
:loading="true"
|
||||||
loadingText="Loading..."
|
:loadingText="$t('Loading...')"
|
||||||
></Button>
|
></Button>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-5 md:grid-cols-2">
|
<div class="grid grid-cols-1 gap-5 md:grid-cols-2">
|
||||||
|
|||||||
@ -555,6 +555,201 @@ Are you sure you want to remove app <b>{app}</b>?,确定要移除应用 <b>{app}
|
|||||||
Removing app...,正在移除应用...,
|
Removing app...,正在移除应用...,
|
||||||
Are you sure you want to delete config <b>{key}</b>?,确定要删除配置 <b>{key}</b> 吗?,
|
Are you sure you want to delete config <b>{key}</b>?,确定要删除配置 <b>{key}</b> 吗?,
|
||||||
Are you sure you want to delete environment variable <b>{key}</b>?,确定要删除环境变量 <b>{key}</b> 吗?,
|
Are you sure you want to delete environment variable <b>{key}</b>?,确定要删除环境变量 <b>{key}</b> 吗?,
|
||||||
|
My Apps,我的应用,
|
||||||
|
Publisher Profile,发布者资料,
|
||||||
|
Payouts,付款,
|
||||||
|
Releases,发布,
|
||||||
|
Review,审核,
|
||||||
|
Subscriptions,订阅,
|
||||||
|
Pricing,定价,
|
||||||
|
Add App to Marketplace,添加应用到市场,
|
||||||
|
No app sources available.,没有可用的应用源。,
|
||||||
|
Don't find your app here?,在这里找不到您的应用?,
|
||||||
|
Add from GitHub,从 GitHub 添加,
|
||||||
|
Add {app},添加 {app},
|
||||||
|
You have not published any app on our Marketplace.,您尚未在我们的市场上发布任何应用。,
|
||||||
|
View in Marketplace,在市场查看,
|
||||||
|
Pricing Plans,定价计划,
|
||||||
|
Set up pricing plans for this app,为此应用设置定价计划,
|
||||||
|
Payout Details,付款详情,
|
||||||
|
Look what you have earned,查看您的收入,
|
||||||
|
Earnings,收入,
|
||||||
|
Total Earnings,总收入,
|
||||||
|
Total earnings for {app},{app} 的总收入,
|
||||||
|
Pending Payout,待付款,
|
||||||
|
Payout you are yet to receive from 今果 Jingrow,您尚未从今果 Jingrow 收到的付款,
|
||||||
|
Commission,佣金,
|
||||||
|
Payouts start once you have passed $500 threshold,一旦您超过 $500 阈值,付款将开始,
|
||||||
|
Installs,安装,
|
||||||
|
Total Installs,总安装数,
|
||||||
|
Active Sites with this App,使用此应用的活跃站点,
|
||||||
|
Active Benches with this App,使用此应用的活跃工作台,
|
||||||
|
Pageviews,页面浏览量,
|
||||||
|
Unique Visitors,独立访客,
|
||||||
|
View Marketplace Page,查看市场页面,
|
||||||
|
Contact Support,联系支持,
|
||||||
|
Loading...,加载中...,
|
||||||
|
Site,站点,
|
||||||
|
Bench,工作台,
|
||||||
|
Listing updated successfully,更新成功,
|
||||||
|
Updating listing...,正在更新列表...,
|
||||||
|
Failed to update listing,更新列表失败,
|
||||||
|
View,查看,
|
||||||
|
Delete,删除,
|
||||||
|
Deleting screenshot...,正在删除截图...,
|
||||||
|
Screenshot deleted successfully,截图删除成功,
|
||||||
|
Failed to delete screenshot,删除截图失败,
|
||||||
|
Add New Marketplace App,添加新的应用市场应用,
|
||||||
|
Select Version,选择版本,
|
||||||
|
Validating app...,正在验证应用...,
|
||||||
|
Found {title} ({name}),找到 {title} ({name}),
|
||||||
|
Github repository is private.,Github 仓库是私有的。,
|
||||||
|
Terms and Policies,条款和政策,
|
||||||
|
Adding new app...,正在添加新应用...,
|
||||||
|
New app added,新应用已添加,
|
||||||
|
Steps to complete before publishing your app,应用发布前需要完成的步骤,
|
||||||
|
Your app has been sent to our team for review. Please wait for the review to complete.,您的应用已发送给我们的团队进行审核。请等待审核完成。,
|
||||||
|
Mark app as ready for review,标记应用为待审核,
|
||||||
|
Step,步骤,
|
||||||
|
Completed,已完成,
|
||||||
|
App Profile,应用资料,
|
||||||
|
This information will be publicly displayed on the marketplace. Please ensure you enter correct information, with no broken links and images.,这些信息将公开显示在市场上。请确保输入正确的信息,没有损坏的链接和图片。,
|
||||||
|
Save,保存,
|
||||||
|
Profile,资料,
|
||||||
|
Profile photo updated,资料照片已更新,
|
||||||
|
Links,链接,
|
||||||
|
Documentation,文档,
|
||||||
|
Website,网站,
|
||||||
|
Support,支持,
|
||||||
|
Terms of Service,服务条款,
|
||||||
|
Privacy Policy,隐私政策,
|
||||||
|
Screenshots and Videos,截图和视频,
|
||||||
|
Screenshot added,已添加截图,
|
||||||
|
Add,添加,
|
||||||
|
Summary,摘要,
|
||||||
|
Your app's primary profile,您应用的主要资料,
|
||||||
|
Published Versions,已发布版本,
|
||||||
|
Update App Title,更新应用标题,
|
||||||
|
Save Changes,保存更改,
|
||||||
|
App Title,应用标题,
|
||||||
|
Change Branch,更改分支,
|
||||||
|
Remove,移除,
|
||||||
|
App Profile Updated!,应用资料已更新!,
|
||||||
|
App Descriptions,应用描述,
|
||||||
|
Details about your app,关于您应用的详细信息,
|
||||||
|
Update App Summary,更新应用摘要,
|
||||||
|
Summary of the app,应用摘要,
|
||||||
|
Long Description,详细描述,
|
||||||
|
Update App Description,更新应用描述,
|
||||||
|
Fetch Readme,获取 Readme,
|
||||||
|
App Summary Updated!,应用摘要已更新!,
|
||||||
|
App Description Updated!,应用描述已更新!,
|
||||||
|
Successfully fetched latest readme,成功获取最新 readme,
|
||||||
|
Long description updated!,详细描述已更新!,
|
||||||
|
Active Sites,激活站点,
|
||||||
|
Active Benches,激活站点分组,
|
||||||
|
Weekly Installs,每周安装量,
|
||||||
|
Updating version branch...,正在更新版本的分支...,
|
||||||
|
Change {app} {version} branch,更改 {app} 的 {version} 分支,
|
||||||
|
Please select a different branch,请选择一个不同的分支,
|
||||||
|
Branch changed successfully,分支更改成功,
|
||||||
|
New App,新建应用,
|
||||||
|
Listing,列表,
|
||||||
|
Source,来源,
|
||||||
|
New Version,新建版本,
|
||||||
|
Add version support for {appTitle},为 {appTitle} 添加版本支持,
|
||||||
|
Adding new version...,正在添加新版本...,
|
||||||
|
New version added,新版本已添加,
|
||||||
|
Show Releases,显示发布,
|
||||||
|
Remove Version,移除版本,
|
||||||
|
Removing version...,正在移除版本...,
|
||||||
|
Version removed successfully,版本已成功移除,
|
||||||
|
Price,价格,
|
||||||
|
Active Days,已激活天数,
|
||||||
|
day,天,
|
||||||
|
days,天,
|
||||||
|
Guide,指南,
|
||||||
|
Complete Listing,完成列表,
|
||||||
|
Delete app {appTitle},删除应用 {appTitle},
|
||||||
|
Are you sure you want to delete this app?,您确定要删除此应用吗?,
|
||||||
|
Deleting app...,正在删除应用...,
|
||||||
|
App deleted successfully,应用删除成功,
|
||||||
|
Releases for {appName} on {branch} branch,{appName} 在 {branch} 分支的发布,
|
||||||
|
Commit Message,提交信息,
|
||||||
|
Hash,哈希值,
|
||||||
|
Code Review,代码审查,
|
||||||
|
Not Started,未开始,
|
||||||
|
Cancel,取消,
|
||||||
|
Release cancelled,发布已取消,
|
||||||
|
Cancelling release...,正在取消发布...,
|
||||||
|
Submit,提交,
|
||||||
|
Submitting release for approval...,正在提交发布以供审批...,
|
||||||
|
Release submitted for approval,发布已提交以供审批,
|
||||||
|
No results found,未找到结果,
|
||||||
|
Primary Domain,主域名,
|
||||||
|
DNS Type,DNS 类型,
|
||||||
|
Error occurred while obtaining HTTPS certificate for your domain.,获取您的域名的 HTTPS 证书时出错。,
|
||||||
|
View Error,查看错误,
|
||||||
|
Error obtaining certificate,获取证书时出错,
|
||||||
|
Add Domain,添加域名,
|
||||||
|
Remove,移除,
|
||||||
|
Are you sure you want to remove domain <b>{domain}</b> from site <b>{site}</b>?,您确定要从站点 <b>{site}</b> 中移除域名 <b>{domain}</b> 吗?,
|
||||||
|
Backups,备份,
|
||||||
|
Timestamp,时间戳,
|
||||||
|
Backed up on {date},备份于 {date},
|
||||||
|
Database,数据库,
|
||||||
|
Public Files,公共文件,
|
||||||
|
Private Files,私有文件,
|
||||||
|
Backup with Files,包含文件的备份,
|
||||||
|
Offsite Backup,异地备份,
|
||||||
|
Download Backup,下载备份,
|
||||||
|
You will download the {fileName} backup for site <b>{siteName}</b>, created on {date}.,您将下载站点 <b>{siteName}</b> 的 {fileName} 备份,该备份创建于 {date}。,
|
||||||
|
You will download the {fileName} backup for site <b>{siteName}</b>, created on {date}.<br><br><div class="p-2 bg-gray-100 border-gray-200 rounded">You need to log in as <b>System Administrator</b> on <em>your site</em> to download the backup.<div>,您将下载站点 <b>{siteName}</b> 的 {fileName} 备份,该备份创建于 {date}。<br><br><div class="p-2 bg-gray-100 border-gray-200 rounded">您需要以 <b>系统管理员</b> 身份登录 <em>您的站点</em> 才能下载备份。<div>,
|
||||||
|
database,数据库,
|
||||||
|
public files,公共文件,
|
||||||
|
private files,私有文件,
|
||||||
|
config file,配置文件,
|
||||||
|
Details,详情,
|
||||||
|
Download,下载,
|
||||||
|
Download Database,下载数据库,
|
||||||
|
Download Public Files,下载公共文件,
|
||||||
|
Download Private Files,下载私有文件,
|
||||||
|
Download Config File,下载配置文件,
|
||||||
|
Restore,恢复,
|
||||||
|
Restore Backup,恢复备份,
|
||||||
|
Are you sure you want to restore your site to the offsite backup from <b>{date}</b>?,您确定要将您的站点恢复到<b>{date}</b>的异地备份吗?,
|
||||||
|
Scheduling backup restore...,正在安排备份恢复...,
|
||||||
|
Backup restore scheduled successfully.,备份恢复已成功安排。,
|
||||||
|
Restore Backup on Another Site,在另一个站点上恢复备份,
|
||||||
|
Schedule Backup,安排备份,
|
||||||
|
Are you sure you want to schedule a backup? This will create a local backup.,您确定要安排备份吗?这将创建一个本地备份。,
|
||||||
|
Scheduling backup...,正在安排备份...,
|
||||||
|
Backup scheduled successfully.,备份已成功安排。,
|
||||||
|
App Changes,应用更改,
|
||||||
|
From,从,
|
||||||
|
To,到,
|
||||||
|
No app changes found,未找到应用变更,
|
||||||
|
Jobs in Progress,进行中的任务,
|
||||||
|
Scheduled Updates,已安排更新,
|
||||||
|
Impersonate Site Owner,模拟站点所有者,
|
||||||
|
Visit Site,访问站点,
|
||||||
|
Setup Site,设置站点,
|
||||||
|
Login as Administrator,以管理员身份登录,
|
||||||
|
Are you sure you want to login as administrator to site <b>{site}</b>?,您确定要以管理员身份登录站点 <b>{site}</b> 吗?,
|
||||||
|
Reason,原因,
|
||||||
|
Reason is required,原因必填,
|
||||||
|
Normal,正常,
|
||||||
|
Locked,锁定,
|
||||||
|
Registration Date,注册时间,
|
||||||
|
Expiry Date,到期时间,
|
||||||
|
New Domain,新建域名,
|
||||||
|
Domain Details,域名详细信息,
|
||||||
|
DNS Records,域名解析,
|
||||||
|
Owner Template,所有者模板,
|
||||||
|
Basic Information,基本信息,
|
||||||
|
Pricing Information,价格信息,
|
||||||
|
DNS Settings,DNS设置,
|
||||||
|
Other Information,其他信息,
|
||||||
|
Renew,续费,
|
||||||
|
Rename,重命名,
|
||||||
|
|
||||||
|
|||||||
|
Can't render this file because it has a wrong number of fields in line 386.
|
Loading…
x
Reference in New Issue
Block a user