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