Compare commits

...
11 Commits
Author SHA1 Message Date
xiaojunnuo 53db97b6f2 chore: i18n 优化 2026-10-12 00:18:36 +08:00
xiaojunnuo cd2dcaa859 chore: 国际化持续完善 2026-10-11 23:28:45 +08:00
xiaojunnuo d0463abc26 perf: 完善插件翻译 2026-10-11 18:24:42 +08:00
xiaojunnuo 8f1b38ad7d perf: 多语言国际化优化,插件支持国际化配置
- 新增钱包模块,包含余额、提现、收益明细等功能
- 为插件、访问授权、任务等添加英文国际化支持
- 重构页面标题为多语言文本,统一国际化展示
- 完善导航、设置等页面的多语言支持
- 修复部分代码格式问题,优化插件国际化处理逻辑
2026-10-11 15:09:52 +08:00
xiaojunnuo e11349b8cc refactor: 重构国际化文案结构,按模块拆分命名空间
调整所有国际化文案的命名空间,将零散的文案归类到对应业务模块下,优化语言文件的组织结构,便于后续维护和扩展。
2026-10-11 13:39:34 +08:00
xiaojunnuo 2394cc6dd9 chore(certd-client): 修复开关选项的字典数据顺序
调整了字典数据的顺序,确保“否”选项在“是”选项之后,符合常规交互逻辑
2026-10-11 13:23:27 +08:00
xiaojunnuo 8209c3d6e1 chore(open-api): 添加返回证书密码开关及多语言支持
在开放接口密钥配置中新增返回证书密码的开关选项,添加中英文多语言提示文本和开关选项文案,明确开关开启时响应会包含证书密码,提醒妥善保管。
2026-10-11 13:22:58 +08:00
xiaojunnuo 3e001b8ba4 perf: 开放接口支持返回证书密码,需要在openKey主动开启该设置,客户端部署证书时可以直接获取密码部署
新增证书密码字段到证书信息和开放密钥表,添加返回开关,开放接口可根据开关决定是否返回证书密码
2026-10-11 12:24:09 +08:00
xiaojunnuo 41ca198116 perf: 插件市场新增同步按钮并调整搜索区域布局 2026-10-04 14:23:51 +08:00
xiaojunnuo 6eca5dad9b chore(wangsu): 修复网宿access getCertList 不支持普通CDN的bug 2026-10-04 00:35:31 +08:00
xiaojunnuo c285522500 chore(wangsu): 新增网宿CDN Pro证书列表获取方法,更新插件说明
新增getCdnProCertList方法用于获取网宿CDN Pro的证书列表,同时更新WangsuRefreshCert插件的描述,明确仅支持普通CDN证书更新,CDN Pro证书需使用对应在线插件。
2026-10-04 00:08:10 +08:00
548 changed files with 5629 additions and 2630 deletions
+2
View File
@@ -23,6 +23,8 @@ version: 1.0.0
- 配置插件的唯一标识、标题、图标和描述
- 继承 `BaseAccess` 类
- 插件默认文案使用中文;需要英文时,在注解参数对象中添加同级 `i18n: { "en-US": { ... } }`,不要写成 `metadata.i18n`。`define` 本身就是插件 metadata。
- `i18n["en-US"]` 仅配置要翻译的展示字段,如 `title`、`desc`、`input`;输入字段可翻译 `title`、`helper`、组件展示文案和 `optionsMapping`。缺少英文翻译时回退默认中文。
3. **定义授权属性**
+2
View File
@@ -30,6 +30,8 @@ version: 1.0.0
- 指定对应的云平台的 access 类型名称
- 设置排序值(可选)
- 继承 `AbstractDnsProvider` 类
- 插件默认文案使用中文;需要英文时,在注解参数对象中添加同级 `i18n: { "en-US": { ... } }`,不要写成 `metadata.i18n`。`define` 本身就是插件 metadata。
- `i18n["en-US"]` 仅配置要翻译的展示字段,如 `title`、`desc`、`input`;输入字段可翻译 `title`、`helper`、组件展示文案和 `optionsMapping`。缺少英文翻译时回退默认中文。
4. **实现 onInstance 方法**
+2
View File
@@ -28,6 +28,8 @@ version: 1.0.0
- 设置插件分组
- 配置默认策略(如 `SkipWhenSucceed`)
- 确保类名与插件名称一致
- 插件默认文案使用中文;需要英文时,在注解参数对象中添加同级 `i18n: { "en-US": { ... } }`,不要写成 `metadata.i18n`。`define` 本身就是插件 metadata。
- `i18n["en-US"]` 仅配置要翻译的展示字段,如 `title`、`desc`、`group`、`input`、`output`;未配置的字段自动回退默认中文。不要翻译插件标识、组件类型、默认值或执行参数。
3. **定义任务输入参数**
@@ -0,0 +1 @@
export default { setSuccess: "Settings saved", editTitle: "Edit Certificate Application Template", addTitle: "Add Certificate Application Template", name: "Template Name", default: "Default", setDefault: "Set as Default", disabled: "Disabled", createTime: "Created At", config: "Configuration" };
+1
View File
@@ -19,6 +19,7 @@ export type AccessInputDefine = FormItemProps & {
encrypt?: boolean;
};
export type AccessDefine = Registrable & {
i18n?: Record<string, any>;
icon?: string;
subtype?: string;
dependPlugins?: Record<string, string>;
@@ -44,6 +44,7 @@ export type NotificationDefine = Registrable & {
input?: {
[key: string]: NotificationInputDefine;
};
i18n?: Record<string, any>;
};
export type NotificationInstanceConfig = {
+2
View File
@@ -43,6 +43,7 @@ export type TaskInputDefine = {
} & FormItemProps;
export type PluginDefine = Registrable & {
i18n?: Record<string, any>;
default?: any;
group?: string;
icon?: string;
@@ -97,6 +98,7 @@ export type CertTargetItem = {
export type PipelineEvent<T = any> = {
cert: T;
certPassword?: string;
runnableId: string;
pipelineId: number;
};
@@ -26,6 +26,7 @@ export type AddonDefine = Registrable & {
};
showTest?: boolean;
icon?: string;
i18n?: Record<string, any>;
};
export type AddonInstanceConfig = {
@@ -3,6 +3,7 @@ import { IAccess, IAccessService, IServiceGetter, PageRes, PageSearch, Registrab
export type DnsProviderDefine = Registrable & {
accessType: string;
i18n?: Record<string, any>;
icon?: string;
dependPlugins?: Record<string, string>;
dependPackages?: Record<string, string>;
@@ -4,6 +4,7 @@ import { errorLog, errorCreate } from "./tools";
import { env } from "/src/utils/util.env";
import { useUserStore } from "/@/store/user";
import { useProjectStore } from "../store/project";
import { i18n } from "/@/locales";
export class CodeError extends Error {
code: number;
@@ -139,6 +140,7 @@ function createRequestFunction(service: any) {
const configDefault: any = {
headers: {
"Content-Type": get(config, "headers.Content-Type", "application/json"),
"Accept-Language": i18n.global.locale.value,
} as any,
timeout: 30000,
baseURL: env.API,
@@ -154,6 +156,10 @@ function createRequestFunction(service: any) {
configDefault.headers.Authorization = token;
}
Object.assign(configDefault, config);
configDefault.headers = {
...configDefault.headers,
"Accept-Language": i18n.global.locale.value,
};
if (!configDefault.params.projectId && projectStore.isEnterprise && !config.url.startsWith("/sys") && !config.url.startsWith("http")) {
configDefault.params.projectId = projectStore.currentProject?.id;
@@ -1,11 +1,11 @@
<template>
<div class="flex captcha-image-input">
<a-input :value="valueRef" :placeholder="t('certd.captcha.inputImageCode')" autocomplete="off" @update:value="onChange">
<a-input :value="valueRef" :placeholder="t('certd.common.captcha.inputImageCode')" autocomplete="off" @update:value="onChange">
<template #prefix>
<fs-icon icon="ion:image-outline"></fs-icon>
</template>
</a-input>
<div class="input-right pointer" :title="t('certd.captcha.refresh')">
<div class="input-right pointer" :title="t('certd.common.captcha.refresh')">
<img class="image-code" :src="imageCodeSrc" @click="resetImageCode" />
</div>
</div>
@@ -4,8 +4,8 @@
<div class="sweep-animation"></div>
<div class="box-content">
<div class="box-icon">✓</div>
<span v-if="modelValue == null" class="status-text">{{ t("certd.captcha.clickToVerify") }}</span>
<span v-else class="status-text">{{ t("certd.captcha.verifySuccess") }}</span>
<span v-if="modelValue == null" class="status-text">{{ t("certd.common.captcha.clickToVerify") }}</span>
<span v-else class="status-text">{{ t("certd.common.captcha.verifySuccess") }}</span>
</div>
</div>
</div>
@@ -58,7 +58,7 @@ function callback(res: { ret: number; ticket: string; randstr: string; errorCode
if (res.errorCode && res.errorCode > 0) {
notification.error({
message: t("certd.captcha.verifyFailed", { message: res.errorMessage || res.errorCode }),
message: t("certd.common.captcha.verifyFailed", { message: res.errorMessage || res.errorCode }),
});
}
@@ -85,13 +85,13 @@ function loadErrorCallback(error: any) {
// errorMessage: "jsload_error",
// });
notification.error({
message: t("certd.captcha.loadFailed", { message: error?.message || error }),
message: t("certd.common.captcha.loadFailed", { message: error?.message || error }),
});
}
async function triggerCaptcha() {
if (!loaded.value) {
notification.error({
message: t("certd.captcha.notLoaded"),
message: t("certd.common.captcha.notLoaded"),
});
return;
}
@@ -5,6 +5,7 @@
<script lang="ts">
import { ref } from "vue";
import * as api from "./api";
import { resolvePluginLocale } from "/@/store/plugin";
export default {
name: "DnsProviderSelector",
@@ -21,12 +22,13 @@ export default {
async function onCreate() {
const list = await api.GetList();
const array: any[] = [];
for (let item of list) {
for (const item of list) {
const localizedItem = resolvePluginLocale(item);
array.push({
value: item.name,
label: item.title,
icon: item.icon,
accessType: item.accessType,
value: localizedItem.name,
label: localizedItem.title,
icon: localizedItem.icon,
accessType: localizedItem.accessType,
});
}
options.value = array;
@@ -4,7 +4,7 @@
<!-- <td class="domain">-->
<!-- {{ props.domain }}-->
<!-- </td>-->
<td class="host-record" :title="t('certd.verifyPlan.domainTitle', { domain: props.domain })">
<td class="host-record" :title="t('certd.certdomain.verifyPlan.domainTitle', { domain: props.domain })">
<fs-copyable v-model="cnameRecord.hostRecord"></fs-copyable>
</td>
<td style="text-align: center">CNAME</td>
@@ -17,18 +17,18 @@
<a-tooltip v-if="cnameRecord.error" :title="cnameRecord.error">
<fs-icon class="ml-5 color-red" icon="ion:warning-outline"></fs-icon>
</a-tooltip>
<a-tooltip v-if="cnameRecord.status === 'valid'" :title="t('certd.verifyPlan.resetStatusTooltip')">
<a-tooltip v-if="cnameRecord.status === 'valid'" :title="t('certd.certdomain.verifyPlan.resetStatusTooltip')">
<fs-icon class="ml-2 color-yellow text-md pointer" icon="solar:undo-left-square-bold" @click="resetStatus"></fs-icon>
</a-tooltip>
</span>
</td>
<td class="center">
<template v-if="cnameRecord.status !== 'valid'">
<a-button type="primary" size="small" :loading="loading" @click="doVerify">{{ t("certd.verifyPlan.clickToValidate") }}</a-button>
<a-button type="primary" size="small" :loading="loading" @click="doVerify">{{ t("certd.certdomain.verifyPlan.clickToValidate") }}</a-button>
<cname-tip :record="cnameRecord"></cname-tip>
</template>
<div v-else class="helper" :title="t('certd.verifyPlan.keepCnameTitle')">{{ t("certd.verifyPlan.keepCname") }}</div>
<div v-else class="helper" :title="t('certd.certdomain.verifyPlan.keepCnameTitle')">{{ t("certd.certdomain.verifyPlan.keepCname") }}</div>
</td>
</tr>
</tbody>
@@ -46,11 +46,11 @@ import { utils } from "/@/utils/index.js";
const { t } = useI18n();
const statusDict = dict({
data: [
{ label: t("certd.verifyPlan.status.pendingCname"), value: "cname", color: "warning" },
{ label: t("certd.verifyPlan.status.validating"), value: "validating", color: "blue" },
{ label: t("certd.verifyPlan.status.valid"), value: "valid", color: "green" },
{ label: t("certd.verifyPlan.status.failed"), value: "failed", color: "red" },
{ label: t("certd.verifyPlan.status.timeout"), value: "timeout", color: "red" },
{ label: t("certd.certdomain.verifyPlan.status.pendingCname"), value: "cname", color: "warning" },
{ label: t("certd.certdomain.verifyPlan.status.validating"), value: "validating", color: "blue" },
{ label: t("certd.certdomain.verifyPlan.status.valid"), value: "valid", color: "green" },
{ label: t("certd.certdomain.verifyPlan.status.failed"), value: "failed", color: "red" },
{ label: t("certd.certdomain.verifyPlan.status.timeout"), value: "timeout", color: "red" },
],
});
@@ -129,8 +129,8 @@ async function doVerify() {
async function resetStatus() {
Modal.confirm({
title: t("certd.verifyPlan.resetStatus"),
content: t("certd.verifyPlan.confirmResetStatus"),
title: t("certd.certdomain.verifyPlan.resetStatus"),
content: t("certd.certdomain.verifyPlan.confirmResetStatus"),
onOk: async () => {
await api.ResetStatus(cnameRecord.value.id);
await loadRecord();
@@ -2,17 +2,17 @@
<a-tooltip :overlay-style="{ maxWidth: '400px' }">
<template #title>
<div>
<div>{{ t("certd.verifyPlan.cnameTip.intro") }}</div>
<div>{{ t("certd.verifyPlan.cnameTip.step1", { domain: record.domain }) }}</div>
<div>{{ t("certd.verifyPlan.cnameTip.step2") }}</div>
<div>{{ t("certd.verifyPlan.cnameTip.step3", { value: record.recordValue }) }}</div>
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.intro") }}</div>
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step1", { domain: record.domain }) }}</div>
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step2") }}</div>
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step3", { value: record.recordValue }) }}</div>
<div>
{{ t("certd.verifyPlan.cnameTip.step4") }}
{{ t("certd.certdomain.verifyPlan.cnameTip.step4") }}
<fs-copyable :style="{ color: '#52c41a' }" :model-value="nslookupCmd"></fs-copyable>
{{ t("certd.verifyPlan.cnameTip.or") }}
{{ t("certd.certdomain.verifyPlan.cnameTip.or") }}
<fs-copyable :style="{ color: '#52c41a' }" :model-value="digCmd"></fs-copyable>
</div>
<div>{{ t("certd.verifyPlan.cnameTip.step5") }}</div>
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step5") }}</div>
</div>
</template>
<fs-icon class="ml-5 pointer" icon="mingcute:question-line"></fs-icon>
@@ -2,11 +2,11 @@
<table class="cname-verify-plan">
<thead>
<tr>
<td class="col-host">{{ t("certd.verifyPlan.hostRecord") }}</td>
<td class="col-type center">{{ t("certd.verifyPlan.recordType") }}</td>
<td class="col-value">{{ t("certd.verifyPlan.setCnameRecord") }}</td>
<td class="col-status center">{{ t("certd.status") }}</td>
<td class="col-action center">{{ t("certd.verifyPlan.operation") }}</td>
<td class="col-host">{{ t("certd.certdomain.verifyPlan.hostRecord") }}</td>
<td class="col-type center">{{ t("certd.certdomain.verifyPlan.recordType") }}</td>
<td class="col-value">{{ t("certd.certdomain.verifyPlan.setCnameRecord") }}</td>
<td class="col-status center">{{ t("certd.common.status") }}</td>
<td class="col-action center">{{ t("certd.certdomain.verifyPlan.operation") }}</td>
</tr>
</thead>
<template v-for="key in domains" :key="key">
@@ -2,10 +2,10 @@
<table class="http-verify-plan">
<thead>
<tr>
<td style="width: 160px">{{ t("certd.verifyPlan.websiteDomain") }}</td>
<td style="width: 100px; text-align: center">{{ t("certd.verifyPlan.uploadMethod") }}</td>
<td style="width: 150px">{{ t("certd.verifyPlan.uploadAccess") }}</td>
<td style="width: 200px">{{ t("certd.verifyPlan.websiteRootPath") }}</td>
<td style="width: 160px">{{ t("certd.certdomain.verifyPlan.websiteDomain") }}</td>
<td style="width: 100px; text-align: center">{{ t("certd.certdomain.verifyPlan.uploadMethod") }}</td>
<td style="width: 150px">{{ t("certd.certdomain.verifyPlan.uploadAccess") }}</td>
<td style="width: 200px">{{ t("certd.certdomain.verifyPlan.websiteRootPath") }}</td>
</tr>
</thead>
<tbody v-if="records" class="http-record-body">
@@ -21,7 +21,7 @@
<access-selector v-model="item.httpUploaderAccess" :type="item.httpUploaderType" @change="onRecordChange"></access-selector>
</td>
<td>
<a-input v-model:value="item.httpUploadRootDir" :placeholder="t('certd.verifyPlan.websiteRootPlaceholder')" @change="onRecordChange"></a-input>
<a-input v-model:value="item.httpUploadRootDir" :placeholder="t('certd.certdomain.verifyPlan.websiteRootPlaceholder')" @change="onRecordChange"></a-input>
</td>
</tr>
</template>
@@ -5,7 +5,7 @@
<div class="plan-box bg-white dark:bg-neutral-700">
<div class="fullscreen-button pointer flex-center" @click="fullscreen = !fullscreen">
<span v-if="!fullscreen" style="font-size: 10px" class="flex-center">
{{ t("certd.verifyPlan.expandTip") }}
{{ t("certd.certdomain.verifyPlan.expandTip") }}
<fs-icon icon="ion:arrow-forward-outline"></fs-icon>
</span>
<fs-icon :icon="fullscreen ? 'material-symbols:fullscreen-exit' : 'material-symbols:fullscreen'"></fs-icon>
@@ -13,9 +13,9 @@
<table class="plan-table">
<thead>
<tr>
<th style="min-width: 100px">{{ t("certd.verifyPlan.mainDomain") }}</th>
<th>{{ t("certd.verifyPlan.challengeType") }}</th>
<th>{{ t("certd.verifyPlan.challengePlan") }}</th>
<th style="min-width: 100px">{{ t("certd.certdomain.verifyPlan.mainDomain") }}</th>
<th>{{ t("certd.certdomain.verifyPlan.challengeType") }}</th>
<th>{{ t("certd.certdomain.verifyPlan.challengePlan") }}</th>
</tr>
</thead>
<tbody>
@@ -30,13 +30,13 @@
<div class="plan">
<div v-if="item.type === 'dns'" class="plan-dns">
<div class="form-item">
<span class="label">{{ t("certd.verifyPlan.dnsType") }}:</span>
<span class="label">{{ t("certd.certdomain.verifyPlan.dnsType") }}:</span>
<span class="input">
<fs-dict-select
v-model:value="item.dnsProviderType"
size="small"
:dict="dnsProviderTypeDict"
:placeholder="t('certd.verifyPlan.dnsProvider')"
:placeholder="t('certd.certdomain.verifyPlan.dnsProvider')"
@change="onPlanChanged"
@selected-change="onDnsProviderChange(item, $event)"
></fs-dict-select>
@@ -44,13 +44,13 @@
</div>
<a-divider type="vertical" />
<div class="form-item">
<span class="label">{{ t("certd.verifyPlan.dnsAccess") }}:</span>
<span class="label">{{ t("certd.certdomain.verifyPlan.dnsAccess") }}:</span>
<span class="input">
<access-selector
v-model="item.dnsProviderAccessId"
size="small"
:type="item.dnsProviderAccessType || item.dnsProviderType"
:placeholder="t('certd.verifyPlan.pleaseSelect')"
:placeholder="t('certd.certdomain.verifyPlan.pleaseSelect')"
@change="onPlanChanged"
></access-selector>
</span>
@@ -70,7 +70,7 @@
</div>
<div v-if="item.type === 'http'" class="plan-http">
<http-verify-plan v-model="item.httpVerifyPlan" @change="onPlanChanged" />
<div class="helper">{{ t("certd.verifyPlan.httpHelper") }}</div>
<div class="helper">{{ t("certd.certdomain.verifyPlan.httpHelper") }}</div>
</div>
</div>
</td>
@@ -105,7 +105,7 @@ const { t } = useI18n();
const challengeTypeOptions = ref<any[]>([
{
label: t("certd.verifyPlan.dnsChallenge"),
label: t("certd.certdomain.verifyPlan.dnsChallenge"),
value: "dns",
},
{
@@ -113,11 +113,11 @@ const challengeTypeOptions = ref<any[]>([
value: "dns-persist",
},
{
label: t("certd.verifyPlan.cnameChallenge"),
label: t("certd.certdomain.verifyPlan.cnameChallenge"),
value: "cname",
},
{
label: t("certd.verifyPlan.httpChallenge"),
label: t("certd.certdomain.verifyPlan.httpChallenge"),
value: "http",
},
]);
@@ -14,7 +14,7 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
for (const subDomain of subDomains) {
const plan = value[domain].cnameVerifyPlan[subDomain];
if (plan.status !== "valid") {
throw new Error($t("certd.verifyPlan.errors.cnameNotValid", { domain: subDomain }));
throw new Error($t("certd.certdomain.verifyPlan.errors.cnameNotValid", { domain: subDomain }));
}
}
}
@@ -23,7 +23,7 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
for (const item of domains) {
//如果有通配符域名则不允许使用http校验
if (item.startsWith("*.")) {
throw new Error($t("certd.verifyPlan.errors.wildcardNotSupportHttp", { domain: item }));
throw new Error($t("certd.certdomain.verifyPlan.errors.wildcardNotSupportHttp", { domain: item }));
}
}
@@ -32,19 +32,19 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
for (const subDomain of subDomains) {
const plan = value[domain].httpVerifyPlan[subDomain];
if (!plan.httpUploaderType) {
throw new Error($t("certd.verifyPlan.errors.uploadMethodRequired", { domain: subDomain }));
throw new Error($t("certd.certdomain.verifyPlan.errors.uploadMethodRequired", { domain: subDomain }));
}
if (!plan.httpUploaderAccess) {
throw new Error($t("certd.verifyPlan.errors.uploadAccessRequired", { domain: subDomain }));
throw new Error($t("certd.certdomain.verifyPlan.errors.uploadAccessRequired", { domain: subDomain }));
}
if (!plan.httpUploadRootDir) {
throw new Error($t("certd.verifyPlan.errors.websiteRootRequired", { domain: subDomain }));
throw new Error($t("certd.certdomain.verifyPlan.errors.websiteRootRequired", { domain: subDomain }));
}
}
}
} else if (type === "dns") {
if (!value[domain].dnsProviderType || !value[domain].dnsProviderAccessId) {
throw new Error($t("certd.verifyPlan.errors.dnsProviderRequired", { domain }));
throw new Error($t("certd.certdomain.verifyPlan.errors.dnsProviderRequired", { domain }));
}
} else if (type === "dns-persist") {
const subDomains = Object.keys(value[domain].dnsPersistVerifyPlan || {});
@@ -1,7 +1,7 @@
<template>
<div class="api-test">
<div>
<fs-button :loading="loading" type="primary" :text="t('certd.pluginCommon.test')" icon="ion:refresh-outline" @click="doTest"></fs-button>
<fs-button :loading="loading" type="primary" :text="t('certd.common.pluginCommon.test')" icon="ion:refresh-outline" @click="doTest"></fs-button>
</div>
<div class="helper" :class="{ error: hasError }">
@@ -64,14 +64,14 @@ const doTest = async () => {
{
onError(err: any) {
hasError.value = true;
message.value = t("certd.pluginCommon.errorWithMessage", { message: err.message });
message.value = t("certd.common.pluginCommon.errorWithMessage", { message: err.message });
},
showErrorNotify: false,
}
);
message.value = t("certd.pluginCommon.testRequestSuccess");
message.value = t("certd.common.pluginCommon.testRequestSuccess");
if (res) {
message.value += t("certd.pluginCommon.responseSuffix", { response: JSON.stringify(res) });
message.value += t("certd.common.pluginCommon.responseSuffix", { response: JSON.stringify(res) });
}
} finally {
loading.value = false;
@@ -42,7 +42,7 @@ function findStepFromPipeline(targetStepId: string) {
const errorRef = ref("");
function getStepIdFromInputKey(inputKey: string) {
if (!inputKey) {
errorRef.value = t("certd.pluginCommon.selectCertFirst");
errorRef.value = t("certd.common.pluginCommon.selectCertFirst");
return;
}
return inputKey.split(".")[1];
@@ -51,7 +51,7 @@ function getDomainFromPipeline(inputKey: string) {
let targetStepId = getStepIdFromInputKey(inputKey);
let certStep = findStepFromPipeline(targetStepId);
if (!certStep) {
errorRef.value = t("certd.pluginCommon.targetStepNotFound");
errorRef.value = t("certd.common.pluginCommon.targetStepNotFound");
return;
}
@@ -60,7 +60,7 @@ function getDomainFromPipeline(inputKey: string) {
targetStepId = getStepIdFromInputKey(firstLevelValue);
certStep = findStepFromPipeline(targetStepId);
if (!certStep) {
errorRef.value = t("certd.pluginCommon.targetStepNotFound");
errorRef.value = t("certd.common.pluginCommon.targetStepNotFound");
return;
}
}
@@ -1,4 +1,4 @@
<template>
<template>
<div class="domain-select">
<div class="flex flex-row">
<a-select
@@ -18,12 +18,12 @@
<template v-if="search">
<div class="flex w-full items-center justify-between flex-wrap" style="padding: 4px 8px">
<div class="flex-1 flex flex-row items-center">
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.pluginCommon.domainSearchPlaceholder')" @keydown.enter="doSearch" />
<fs-button type="primary" class="m-1" :loading="loading" icon="mingcute:search-2-line" @click="doSearch">{{ t("certd.pluginCommon.search") }}</fs-button>
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.common.pluginCommon.domainSearchPlaceholder')" @keydown.enter="doSearch" />
<fs-button type="primary" class="m-1" :loading="loading" icon="mingcute:search-2-line" @click="doSearch">{{ t("certd.common.pluginCommon.search") }}</fs-button>
</div>
<div class="manager flex flex-row items-center">
<fs-button type="primary" class="m-1" icon="mingcute:vip-1-line" @click="openDomainImportDialog">{{ t("certd.pluginCommon.importDomain") }}</fs-button>
<fs-button class="m-1" type="primary" icon="carbon:gui-management" @click="openDomainManager">{{ t("certd.pluginCommon.manageDomain") }}</fs-button>
<fs-button type="primary" class="m-1" icon="mingcute:vip-1-line" @click="openDomainImportDialog">{{ t("certd.common.pluginCommon.importDomain") }}</fs-button>
<fs-button class="m-1" type="primary" icon="carbon:gui-management" @click="openDomainManager">{{ t("certd.common.pluginCommon.manageDomain") }}</fs-button>
</div>
</div>
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
@@ -49,7 +49,7 @@
</a-select>
<div class="ml-5 flex flex-row items-center">
<fs-button title="复制全部域名" icon="ion:copy-outline" class="domain-select-copy-icon mr-5" @click="copySelectedDomains" />
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshMyDomains')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshMyDomains')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
</div>
</div>
<div class="helper" :class="{ error: hasError }">
@@ -4,7 +4,7 @@
<a-auto-complete class="remote-auto-complete-input" :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
</a-auto-complete>
<div class="ml-5">
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
</div>
</div>
<div class="helper" :class="{ error: hasError }">
@@ -96,16 +96,16 @@ const getOptions = async () => {
{
onError(err: any) {
hasError.value = true;
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
message.value = t("certd.common.pluginCommon.getOptionsError", { message: err.message });
},
showErrorNotify: false,
}
);
const list = res?.list || res || [];
if (list.length > 0) {
message.value = t("certd.pluginCommon.getDataSuccessSelect");
message.value = t("certd.common.pluginCommon.getDataSuccessSelect");
} else {
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
message.value = t("certd.common.pluginCommon.getDataSuccessEmpty");
}
optionsRef.value = list;
@@ -55,7 +55,7 @@ async function openDialog() {
saveRemind: false,
},
afterSubmit() {
notification.success({ message: t("certd.operationSuccess") });
notification.success({ message: t("certd.common.operationSuccess") });
},
async doSubmit({ form }: any) {
return await doPluginFormSubmit(form);
@@ -5,12 +5,12 @@
<template #dropdownRender="{ menuNode: menu }">
<template v-if="search">
<div class="flex w-full" style="padding: 4px 8px">
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.pluginCommon.searchKeyword')" @keydown.enter="doSearch" />
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.common.pluginCommon.searchKeyword')" @keydown.enter="doSearch" />
<a-button class="ml-2" :loading="loading" type="text" @click="doSearch">
<template #icon>
<search-outlined />
</template>
{{ t("certd.pluginCommon.search") }}
{{ t("certd.common.pluginCommon.search") }}
</a-button>
</div>
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
@@ -26,7 +26,7 @@
</template>
</a-select>
<div class="ml-5 flex flex-row no-wrap">
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
<UploadCert v-if="uploadCert" class="ml-5" v-bind="uploadCert" @submit="refreshOptions"></UploadCert>
</div>
</div>
@@ -177,7 +177,7 @@ const getOptions = async () => {
{
onError(err: any) {
hasError.value = true;
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
message.value = t("certd.common.pluginCommon.getOptionsError", { message: err.message });
optionsRef.value = [];
},
showErrorNotify: false,
@@ -185,9 +185,9 @@ const getOptions = async () => {
);
let list = res?.list || res || [];
if (list.length > 0) {
message.value = t("certd.pluginCommon.getDataSuccessSelect");
message.value = t("certd.common.pluginCommon.getDataSuccessSelect");
} else {
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
message.value = t("certd.common.pluginCommon.getDataSuccessEmpty");
}
list = list.map((item: any) => {
return {
@@ -3,7 +3,7 @@
<div class="flex flex-row">
<a-tree-select class="remote-tree-select-input" :tree-data="optionsRef" :value="value" tree-checkable allow-clear v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)"> </a-tree-select>
<div class="ml-5">
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
</div>
</div>
<div class="helper" :class="{ error: hasError }">
@@ -107,16 +107,16 @@ const getOptions = async () => {
{
onError(err: any) {
hasError.value = true;
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
message.value = t("certd.common.pluginCommon.getOptionsError", { message: err.message });
},
showErrorNotify: false,
}
);
const list = res?.list || res || [];
if (list.length > 0) {
message.value = t("certd.pluginCommon.getDataSuccessSelect");
message.value = t("certd.common.pluginCommon.getDataSuccessSelect");
} else {
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
message.value = t("certd.common.pluginCommon.getDataSuccessEmpty");
}
optionsRef.value = list;
pagerRef.value.total = list.length;
@@ -1,6 +1,6 @@
<template>
<div class="upload-cert">
<fs-button v-model:loading="loading" type="primary" :text="t('certd.pluginCommon.upload')" v-bind="props.button" @click="openUploadCertDialog"></fs-button>
<fs-button v-model:loading="loading" type="primary" :text="t('certd.common.pluginCommon.upload')" v-bind="props.button" @click="openUploadCertDialog"></fs-button>
</div>
</template>
<script lang="ts" setup>
@@ -30,18 +30,18 @@ const getScope: any = inject("get:scope", () => {
const getPluginType: any = inject("get:plugin:type", () => {
return "plugin";
});
const title = computed(() => props.title || t("certd.pluginCommon.uploadCert"));
const title = computed(() => props.title || t("certd.common.pluginCommon.uploadCert"));
function openUploadCertDialog() {
const columns = merge(
{
certName: {
title: t("certd.pluginCommon.certName"),
title: t("certd.common.pluginCommon.certName"),
form: {
component: {
name: "a-input",
vModel: "value",
},
helper: t("certd.pluginCommon.certNameHelper"),
helper: t("certd.common.pluginCommon.certNameHelper"),
},
},
},
@@ -51,7 +51,7 @@ function openUploadCertDialog() {
title: title.value,
columns: {
certName: {
title: t("certd.pluginCommon.certName"),
title: t("certd.common.pluginCommon.certName"),
form: {
component: {
name: "a-input",
@@ -86,7 +86,7 @@ function openUploadCertDialog() {
showErrorNotify: true,
}
);
notification.success({ message: t("certd.pluginCommon.uploadSuccess") });
notification.success({ message: t("certd.common.pluginCommon.uploadSuccess") });
emit("submit");
} finally {
loading.value = false;
@@ -4,10 +4,10 @@ import { $t } from "/@/locales";
function createChallengeTypeDict() {
return dict({
data: [
{ value: "dns", label: $t("certd.verifyPlan.dnsChallenge"), color: "green" },
{ value: "dns", label: $t("certd.certdomain.verifyPlan.dnsChallenge"), color: "green" },
{ value: "dns-persist", label: "DNS持久验证", color: "cyan" },
{ value: "cname", label: $t("certd.verifyPlan.cnameProxyChallenge"), color: "blue" },
{ value: "http", label: $t("certd.verifyPlan.httpChallenge"), color: "yellow" },
{ value: "cname", label: $t("certd.certdomain.verifyPlan.cnameProxyChallenge"), color: "blue" },
{ value: "http", label: $t("certd.certdomain.verifyPlan.httpChallenge"), color: "yellow" },
],
});
}
@@ -18,11 +18,11 @@ function createUploaderTypeDict() {
{ label: "SFTP", value: "sftp" },
{ label: "SCP", value: "scp" },
{ label: "FTP", value: "ftp" },
{ label: $t("certd.verifyPlan.uploader.aliyunOss"), value: "alioss" },
{ label: $t("certd.verifyPlan.uploader.tencentCos"), value: "tencentcos" },
{ label: $t("certd.verifyPlan.uploader.qiniuOss"), value: "qiniuoss" },
{ label: $t("certd.certdomain.verifyPlan.uploader.aliyunOss"), value: "alioss" },
{ label: $t("certd.certdomain.verifyPlan.uploader.tencentCos"), value: "tencentcos" },
{ label: $t("certd.certdomain.verifyPlan.uploader.qiniuOss"), value: "qiniuoss" },
{ label: "S3/Minio", value: "s3" },
{ label: $t("certd.verifyPlan.uploader.sshDeprecated"), value: "ssh", disabled: true },
{ label: $t("certd.certdomain.verifyPlan.uploader.sshDeprecated"), value: "ssh", disabled: true },
],
});
}
@@ -30,8 +30,8 @@ function createUploaderTypeDict() {
function createDomainFromTypeDict() {
return dict({
data: [
{ value: "manual", label: $t("certd.verifyPlan.domainFrom.manual") },
{ value: "auto", label: $t("certd.verifyPlan.domainFrom.auto") },
{ value: "manual", label: $t("certd.certdomain.verifyPlan.domainFrom.manual") },
{ value: "auto", label: $t("certd.certdomain.verifyPlan.domainFrom.auto") },
],
});
}
@@ -33,11 +33,11 @@ const { t } = useI18n();
<div class="tutorial-button pointer" @click="open">
<template v-if="!slots.default">
<fs-icon v-if="showIcon === false" icon="ant-design:question-circle-outlined" class="mr-0.5"></fs-icon>
<div class="hidden md:block">{{ t("tutorial.title") }}</div>
<div class="hidden md:block">{{ t("certd.tutorial.title") }}</div>
</template>
<slot></slot>
<a-modal v-model:open="openedRef" class="tutorial-modal" width="90%">
<template #title>{{ t("tutorial.title") }}</template>
<template #title>{{ t("certd.tutorial.title") }}</template>
<tutorial-steps v-if="openedRef" />
<template #footer></template>
</a-modal>
@@ -18,9 +18,9 @@ import { ref } from "vue";
import { mitter } from "/@/utils/util.mitt";
const steps = ref<Step[]>([
{ title: t("certd.steps.createPipeline"), icon: <fs-icon icon="tabler:circle-number-1-filled"></fs-icon> },
{ title: t("certd.steps.addTask"), icon: <fs-icon icon="tabler:circle-number-2-filled"></fs-icon> },
{ title: t("certd.steps.scheduledRun"), icon: <fs-icon icon="tabler:circle-number-3-filled"></fs-icon> },
{ title: t("certd.tutorial.steps.createPipeline"), icon: <fs-icon icon="tabler:circle-number-1-filled"></fs-icon> },
{ title: t("certd.tutorial.steps.addTask"), icon: <fs-icon icon="tabler:circle-number-2-filled"></fs-icon> },
{ title: t("certd.tutorial.steps.scheduledRun"), icon: <fs-icon icon="tabler:circle-number-3-filled"></fs-icon> },
]);
function goPipeline() {
@@ -20,8 +20,8 @@
</div>
<div class="flex-center actions">
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">{{ t("guide.buttons.prev") }}</fs-button>
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">{{ t("guide.buttons.next") }}</fs-button>
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">{{ t("certd.guide.buttons.prev") }}</fs-button>
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">{{ t("certd.guide.buttons.next") }}</fs-button>
</div>
</div>
</template>
@@ -52,126 +52,126 @@ import { computed, nextTick, ref } from "vue";
const steps = ref<Step[]>([
{
title: t("guide.createCertPipeline.title"),
description: t("guide.createCertPipeline.description"),
title: t("certd.guide.createCertPipeline.title"),
description: t("certd.guide.createCertPipeline.description"),
items: [
{
title: t("guide.createCertPipeline.items.tutorialTitle"),
descriptions: [t("guide.createCertPipeline.items.tutorialDesc1"), t("guide.createCertPipeline.items.tutorialDesc2")],
title: t("certd.guide.createCertPipeline.items.tutorialTitle"),
descriptions: [t("certd.guide.createCertPipeline.items.tutorialDesc1"), t("certd.guide.createCertPipeline.items.tutorialDesc2")],
body: () => {
return <SimpleSteps></SimpleSteps>;
},
},
{
image: "/static/doc/images/1-add.png",
title: t("guide.createCertPipeline.items.createTitle"),
descriptions: [t("guide.createCertPipeline.items.createDesc")],
title: t("certd.guide.createCertPipeline.items.createTitle"),
descriptions: [t("certd.guide.createCertPipeline.items.createDesc")],
},
{
image: "/static/doc/images/3-add-success.png",
title: t("guide.createCertPipeline.items.successTitle"),
descriptions: [t("guide.createCertPipeline.items.successDesc")],
title: t("certd.guide.createCertPipeline.items.successTitle"),
descriptions: [t("certd.guide.createCertPipeline.items.successDesc")],
},
// {
// title: t("guide.createCertPipeline.items.nextTitle"),
// descriptions: [t("guide.createCertPipeline.items.nextDesc")],
// title: t("certd.guide.createCertPipeline.items.nextTitle"),
// descriptions: [t("certd.guide.createCertPipeline.items.nextDesc")],
// },
],
},
{
title: t("guide.addDeployTask.title"),
description: t("guide.addDeployTask.description"),
title: t("certd.guide.addDeployTask.title"),
description: t("certd.guide.addDeployTask.description"),
items: [
{
image: "/static/doc/images/5-1-add-host.png",
title: t("guide.addDeployTask.items.addTaskTitle"),
descriptions: [t("guide.addDeployTask.items.addTaskDesc1"), t("guide.addDeployTask.items.addTaskDesc2")],
title: t("certd.guide.addDeployTask.items.addTaskTitle"),
descriptions: [t("certd.guide.addDeployTask.items.addTaskDesc1"), t("certd.guide.addDeployTask.items.addTaskDesc2")],
},
{
image: "/static/doc/images/5-2-add-host.png",
title: t("guide.addDeployTask.items.fillParamsTitle"),
descriptions: [t("guide.addDeployTask.items.fillParamsDesc1"), t("guide.addDeployTask.items.fillParamsDesc2")],
title: t("certd.guide.addDeployTask.items.fillParamsTitle"),
descriptions: [t("certd.guide.addDeployTask.items.fillParamsDesc1"), t("certd.guide.addDeployTask.items.fillParamsDesc2")],
},
{
image: "/static/doc/images/5-3-add-host.png",
title: t("guide.addDeployTask.items.activateCertTitle"),
descriptions: [t("guide.addDeployTask.items.activateCertDesc1"), t("guide.addDeployTask.items.activateCertDesc2")],
title: t("certd.guide.addDeployTask.items.activateCertTitle"),
descriptions: [t("certd.guide.addDeployTask.items.activateCertDesc1"), t("certd.guide.addDeployTask.items.activateCertDesc2")],
},
{
image: "/static/doc/images/5-4-add-host.png",
title: t("guide.addDeployTask.items.taskSuccessTitle"),
descriptions: [t("guide.addDeployTask.items.taskSuccessDesc")],
title: t("certd.guide.addDeployTask.items.taskSuccessTitle"),
descriptions: [t("certd.guide.addDeployTask.items.taskSuccessDesc")],
},
{
image: "/static/doc/images/5-5-plugin-list.png",
title: t("guide.addDeployTask.items.pluginsTitle"),
descriptions: [t("guide.addDeployTask.items.pluginsDesc")],
title: t("certd.guide.addDeployTask.items.pluginsTitle"),
descriptions: [t("certd.guide.addDeployTask.items.pluginsDesc")],
},
],
},
{
title: t("guide.runAndTestTask.runAndTestTitle"),
description: t("guide.runAndTestTask.runAndTestDescription"),
title: t("certd.guide.runAndTestTask.runAndTestTitle"),
description: t("certd.guide.runAndTestTask.runAndTestDescription"),
items: [
{
image: "/static/doc/images/9-start.png",
title: t("guide.runAndTestTask.runTestOnce"),
descriptions: [t("guide.runAndTestTask.clickManualTriggerToTest")],
title: t("certd.guide.runAndTestTask.runTestOnce"),
descriptions: [t("certd.guide.runAndTestTask.clickManualTriggerToTest")],
},
{
image: "/static/doc/images/10-1-log.png",
title: t("guide.runAndTestTask.viewLogs"),
descriptions: [t("guide.runAndTestTask.clickTaskToViewStatusAndLogs")],
title: t("certd.guide.runAndTestTask.viewLogs"),
descriptions: [t("certd.guide.runAndTestTask.clickTaskToViewStatusAndLogs")],
},
{
image: "/static/doc/images/11-1-error.png",
title: t("guide.runAndTestTask.howToTroubleshootFailure"),
descriptions: [t("guide.runAndTestTask.viewErrorLogs")],
title: t("certd.guide.runAndTestTask.howToTroubleshootFailure"),
descriptions: [t("certd.guide.runAndTestTask.viewErrorLogs")],
},
{
image: "/static/doc/images/11-2-error.png",
title: t("guide.runAndTestTask.howToTroubleshootFailure"),
descriptions: [t("guide.runAndTestTask.viewErrorLogs"), t("guide.runAndTestTask.nginxContainerNotExistFix")],
title: t("certd.guide.runAndTestTask.howToTroubleshootFailure"),
descriptions: [t("certd.guide.runAndTestTask.viewErrorLogs"), t("certd.guide.runAndTestTask.nginxContainerNotExistFix")],
},
{
image: "/static/doc/images/12-1-log-success.png",
title: t("guide.runAndTestTask.executionSuccess"),
descriptions: [t("guide.runAndTestTask.retryAfterFix")],
title: t("certd.guide.runAndTestTask.executionSuccess"),
descriptions: [t("certd.guide.runAndTestTask.retryAfterFix")],
},
{
image: "/static/doc/images/12-2-skip-log.png",
title: t("guide.runAndTestTask.autoSkipAfterSuccess"),
descriptions: [t("guide.runAndTestTask.successSkipExplanation")],
title: t("certd.guide.runAndTestTask.autoSkipAfterSuccess"),
descriptions: [t("certd.guide.runAndTestTask.successSkipExplanation")],
},
{
image: "/static/doc/images/13-1-result.png",
title: t("guide.runAndTestTask.viewCertDeploymentSuccess"),
descriptions: [t("guide.runAndTestTask.visitNginxToSeeCert")],
title: t("certd.guide.runAndTestTask.viewCertDeploymentSuccess"),
descriptions: [t("certd.guide.runAndTestTask.visitNginxToSeeCert")],
},
{
image: "/static/doc/images/13-3-download.png",
title: t("guide.runAndTestTask.downloadCertManualDeploy"),
descriptions: [t("guide.runAndTestTask.downloadIfNoAutoDeployPlugin")],
title: t("certd.guide.runAndTestTask.downloadCertManualDeploy"),
descriptions: [t("certd.guide.runAndTestTask.downloadIfNoAutoDeployPlugin")],
},
],
},
{
title: t("guide.scheduleAndEmailTask.title"),
description: t("guide.scheduleAndEmailTask.description"),
title: t("certd.guide.scheduleAndEmailTask.title"),
description: t("certd.guide.scheduleAndEmailTask.description"),
items: [
{
image: "/static/doc/images/14-timer.png",
title: t("guide.scheduleAndEmailTask.setSchedule"),
descriptions: [t("guide.scheduleAndEmailTask.pipelineSuccessThenSchedule"), t("guide.scheduleAndEmailTask.recommendDailyRun")],
title: t("certd.guide.scheduleAndEmailTask.setSchedule"),
descriptions: [t("certd.guide.scheduleAndEmailTask.pipelineSuccessThenSchedule"), t("certd.guide.scheduleAndEmailTask.recommendDailyRun")],
},
{
image: "/static/doc/images/15-1-email.png",
title: t("guide.scheduleAndEmailTask.setEmailNotification"),
descriptions: [t("guide.scheduleAndEmailTask.suggestErrorAndRecoveryEmails")],
title: t("certd.guide.scheduleAndEmailTask.setEmailNotification"),
descriptions: [t("certd.guide.scheduleAndEmailTask.suggestErrorAndRecoveryEmails")],
},
{
title: t("guide.scheduleAndEmailTask.tutorialEndTitle"),
descriptions: [t("guide.scheduleAndEmailTask.thanksForWatching")],
title: t("certd.guide.scheduleAndEmailTask.tutorialEndTitle"),
descriptions: [t("certd.guide.scheduleAndEmailTask.thanksForWatching")],
},
],
},
@@ -48,56 +48,56 @@ const text = computed<Text>(() => {
const map = {
isComm: {
comm: {
name: t("vip.comm.name", { vipLabel }),
title: t("vip.comm.title", { expire: expireTime.value }),
name: t("certd.vip.comm.name", { vipLabel }),
title: t("certd.vip.comm.title", { expire: expireTime.value }),
},
button: {
name: t("vip.comm.name", { vipLabel }),
title: t("vip.comm.title", { expire: expireTime.value }),
name: t("certd.vip.comm.name", { vipLabel }),
title: t("certd.vip.comm.title", { expire: expireTime.value }),
},
icon: {
name: "",
title: t("vip.comm.name", { vipLabel }),
title: t("certd.vip.comm.name", { vipLabel }),
},
nav: {
name: t("vip.comm.nav", { vipLabel }),
title: t("vip.comm.title", { expire: expireTime.value }),
name: t("certd.vip.comm.nav", { vipLabel }),
title: t("certd.vip.comm.title", { expire: expireTime.value }),
},
},
isPlus: {
comm: {
name: t("vip.plus.name"),
title: t("vip.plus.title"),
name: t("certd.vip.plus.name"),
title: t("certd.vip.plus.title"),
},
button: {
name: t("vip.comm.name", { vipLabel }),
title: t("vip.comm.title", { expire: expireTime.value }),
name: t("certd.vip.comm.name", { vipLabel }),
title: t("certd.vip.comm.title", { expire: expireTime.value }),
},
icon: {
name: "",
title: t("vip.comm.name", { vipLabel }),
title: t("certd.vip.comm.name", { vipLabel }),
},
nav: {
name: t("vip.comm.nav", { vipLabel }),
title: t("vip.comm.title", { expire: expireTime.value }),
name: t("certd.vip.comm.nav", { vipLabel }),
title: t("certd.vip.comm.title", { expire: expireTime.value }),
},
},
free: {
comm: {
name: t("vip.free.comm.name"),
title: t("vip.free.comm.title"),
name: t("certd.vip.free.comm.name"),
title: t("certd.vip.free.comm.title"),
},
button: {
name: t("vip.free.button.name"),
title: t("vip.free.button.title"),
name: t("certd.vip.free.button.name"),
title: t("certd.vip.free.button.title"),
},
icon: {
name: "",
title: t("vip.free.button.name"),
title: t("certd.vip.free.button.name"),
},
nav: {
name: t("vip.free.nav.name"),
title: plusMessage || t("vip.free.nav.title"),
name: t("certd.vip.free.nav.name"),
title: plusMessage || t("certd.vip.free.nav.title"),
},
},
};
@@ -131,7 +131,7 @@ const userStore = useUserStore();
async function getVipTrial(vipType = "plus") {
const res = await api.getVipTrial(vipType);
notification.success({ message: t("vip.congratulations_vip_trial", { duration: res.duration }) });
notification.success({ message: t("certd.vip.congratulations_vip_trial", { duration: res.duration }) });
await settingStore.init();
}
@@ -139,8 +139,8 @@ function openTrialModal(vipType = "plus") {
Modal.destroyAll();
modal.confirm({
title: t("vip.trial_modal_title"),
okText: t("vip.trial_modal_ok_text"),
title: t("certd.vip.trial_modal_title"),
okText: t("certd.vip.trial_modal_ok_text"),
onOk() {
getVipTrial(vipType);
},
@@ -148,8 +148,8 @@ function openTrialModal(vipType = "plus") {
content: () => {
return (
<div class="flex-col mt-10 mb-10">
<div>{t("vip.trial_modal_thanks")}</div>
<div>{t("vip.trial_modal_click_confirm", { vipType })}</div>
<div>{t("certd.vip.trial_modal_thanks")}</div>
<div>{t("certd.vip.trial_modal_click_confirm", { vipType })}</div>
</div>
);
},
@@ -158,7 +158,7 @@ function openTrialModal(vipType = "plus") {
function openStarModal(vipType: string) {
if (settingStore.isPlus) {
notification.error({ message: t("vip.already_vip") });
notification.error({ message: t("certd.vip.already_vip") });
return;
}
Modal.destroyAll();
@@ -170,8 +170,8 @@ function openStarModal(vipType: string) {
// };
// modal.confirm({
// title: t("vip.get_7_day_pro_trial"),
// okText: t("vip.star_now"),
// title: t("certd.vip.get_7_day_pro_trial"),
// okText: t("certd.vip.star_now"),
// onOk() {
// goGithub();
// openTrialModal(vipType);
@@ -180,7 +180,7 @@ function openStarModal(vipType: string) {
// content: () => {
// return (
// <div class="flex mt-10 mb-10">
// <div>{t("vip.please_help_star")}</div>
// <div>{t("certd.vip.please_help_star")}</div>
// <img class="ml-5" src="https://img.shields.io/github/stars/certd/certd?logo=github" />
// </div>
// );
@@ -190,16 +190,16 @@ function openStarModal(vipType: string) {
function openUpgrade() {
if (!userStore.isAdmin) {
notification.info({ message: t("vip.admin_only_operation") });
notification.info({ message: t("certd.vip.admin_only_operation") });
return;
}
const placeholder = t("vip.enter_activation_code");
const placeholder = t("certd.vip.enter_activation_code");
const isPlus = settingStore.isPlus;
let title = t("vip.activate_pro_business");
let title = t("certd.vip.activate_pro_business");
if (settingStore.isComm) {
title = t("vip.renew_business");
title = t("certd.vip.renew_business");
} else if (settingStore.isPlus) {
title = t("vip.renew_pro_upgrade_business");
title = t("certd.vip.renew_pro_upgrade_business");
}
// const goBuyUrl = "https://afdian.com/a/greper"
@@ -214,10 +214,10 @@ function openUpgrade() {
function checkPerpetualPlus() {
if (settingStore.isPerpetual) {
Modal.warn({
title: t("vip.already_perpetual_plus"),
okText: t("vip.confirm"),
title: t("certd.vip.already_perpetual_plus"),
okText: t("certd.vip.confirm"),
});
throw new Error(t("vip.already_perpetual_plus"));
throw new Error(t("certd.vip.already_perpetual_plus"));
}
}
@@ -225,8 +225,8 @@ function openUpgrade() {
checkPerpetualPlus();
if (settingStore.isComm) {
Modal.warn({
title: t("vip.already_comm"),
okText: t("vip.confirm"),
title: t("certd.vip.already_comm"),
okText: t("certd.vip.confirm"),
});
return;
}
@@ -237,8 +237,8 @@ function openUpgrade() {
checkPerpetualPlus();
if (settingStore.isPlus && !settingStore.isComm) {
Modal.confirm({
title: t("vip.already_plus"),
okText: t("vip.confirm"),
title: t("certd.vip.already_plus"),
okText: t("certd.vip.confirm"),
onOk() {
window.open(goBuyCommUrl);
},
@@ -251,7 +251,7 @@ function openUpgrade() {
title,
class: "vip-modal",
maskClosable: true,
okText: t("vip.close"),
okText: t("certd.vip.close"),
width: 1180,
content: () => {
return <VipModalContent placeholder={placeholder} isPlus={isPlus} productInfo={productInfo} goBuyPlusPage={goBuyPlusPage} goBuyCommPage={goBuyCommPage} openStarModal={openStarModal} modalRef={modalRef} />;
@@ -34,7 +34,7 @@
</a-tooltip>
</span>
<span v-else>
<span class="price-text">{{ t("vip.freee") }}</span>
<span class="price-text">{{ t("certd.vip.freee") }}</span>
</span>
</div>
<div class="get-show">
@@ -44,15 +44,15 @@
<span class="color-red"> {{ todayOrderCount.vipTotal }}</span>
位伙伴支持
</span>
<a-tooltip :title="t('vip.afdian_support_vip')">
<a-tooltip :title="t('certd.vip.afdian_support_vip')">
<a-button size="small" type="primary" @click="goBuyPlusPage">
{{ t("vip.get_after_support") }}
{{ t("certd.vip.get_after_support") }}
</a-button>
</a-tooltip>
</template>
<template v-else-if="item.type === 'comm'">
<a-button size="small" type="primary" @click="goBuyCommPage">
{{ t("vip.buy") }}
{{ t("certd.vip.buy") }}
</a-button>
</template>
</div>
@@ -63,36 +63,36 @@
</div>
<div>
<a href="https://certd.docmirror.cn/guide/donate/#相关问题" target="_blank">
{{ t("vip.question") }}
{{ t("certd.vip.question") }}
</a>
</div>
<div class="mt-10">
<div class="w-100 flex-col md:flex-row">
<span>{{ t("vip.site_id") }}:</span>
<span>{{ t("certd.vip.site_id") }}:</span>
<fs-copyable v-model="computedSiteId" class="mr-2 inline-flex"></fs-copyable>
<a @click="goBindAccount">{{ t("vip.not_effective") }}</a>
<a @click="goBindAccount">{{ t("certd.vip.not_effective") }}</a>
</div>
</div>
<div v-if="isPlus" class="mt-10 flex flex-col md:flex-row">
<span class="mr-2"> {{ t("vip.current") }} {{ vipLabel }} {{ t("vip.activated_expire_time") }} {{ settingStore.expiresText }} </span>
<span class="mr-2"> {{ t("certd.vip.current") }} {{ vipLabel }} {{ t("certd.vip.activated_expire_time") }} {{ settingStore.expiresText }} </span>
<a href="https://app.handfree.work/subject/#/page/detail/1" target="_blank">
{{ t("vip.learn_more") }}
{{ t("certd.vip.learn_more") }}
</a>
</div>
<div class="mt-10">
<span class="mr-2">{{ t("vip.have_activation_code") }}</span>
<span class="mr-2">{{ t("certd.vip.have_activation_code") }}</span>
<span>
<a @click="showManualActivation">{{ t("vip.manual_activation") }}</a>
<a @click="showManualActivation">{{ t("certd.vip.manual_activation") }}</a>
</span>
</div>
<div v-if="manualActiveFlag" class="mt-10">
<div class="mt-10">
<a-input-search v-model:value="formState.code" class="w-2/6" :placeholder="placeholder" :enter-button="t('vip.activate')" @search="doActive"></a-input-search>
<a-input-search v-model:value="formState.code" class="w-2/6" :placeholder="placeholder" :enter-button="t('certd.vip.activate')" @search="doActive"></a-input-search>
</div>
<div class="mt-10">
{{ t("vip.activation_code_one_use") }}
<a @click="goAccount">{{ t("vip.bind_account") }}</a
>,{{ t("vip.transfer_vip") }}
{{ t("certd.vip.activation_code_one_use") }}
<a @click="goAccount">{{ t("certd.vip.bind_account") }}</a
>,{{ t("certd.vip.transfer_vip") }}
</div>
</div>
</div>
@@ -128,24 +128,24 @@ const formState = reactive({
async function doActive() {
if (!formState.code) {
notification.error({ message: t("vip.enterCode") });
throw new Error(t("vip.enterCode"));
notification.error({ message: t("certd.vip.enterCode") });
throw new Error(t("certd.vip.enterCode"));
}
const res = await api.doActive(formState);
if (res) {
await settingStore.init();
const vipLabel = settingStore.vipLabel;
Modal.success({
title: t("vip.successTitle"),
content: t("vip.successContent", {
title: t("certd.vip.successTitle"),
content: t("certd.vip.successContent", {
vipLabel,
expireDate: settingStore.plusInfo.expireTime === -1 ? t("vip.permanent") : dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"),
expireDate: settingStore.plusInfo.expireTime === -1 ? t("certd.vip.permanent") : dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"),
}),
onOk() {
if (!(settingStore.installInfo.bindUserId > 0)) {
Modal.confirm({
title: t("vip.bindAccountTitle"),
content: t("vip.bindAccountContent"),
title: t("certd.vip.bindAccountTitle"),
content: t("certd.vip.bindAccountContent"),
onOk() {
router.push("/sys/account");
},
@@ -179,39 +179,39 @@ function goBindAccount() {
const vipTypeDefine: any = {
free: {
title: t("vip.basic_edition"),
desc: t("vip.community_free_version"),
title: t("certd.vip.basic_edition"),
desc: t("certd.vip.community_free_version"),
type: "free",
icon: "lucide:package-open",
privilege: t("vip.free_privilege").split("\n"),
privilege: t("certd.vip.free_privilege").split("\n"),
},
plus: {
title: t("vip.professional_edition"),
desc: t("vip.open_source_support"),
title: t("certd.vip.professional_edition"),
desc: t("certd.vip.open_source_support"),
type: "plus",
privilege: t("vip.plus_privilege").split("\n"),
privilege: t("certd.vip.plus_privilege").split("\n"),
trial: {
title: t("vip.click_to_get_7_day_trial"),
title: t("certd.vip.click_to_get_7_day_trial"),
click: () => {
props.openStarModal("plus");
},
},
icon: "stash:thumb-up",
priceText: props.productInfo.plus.priceText || `¥${props.productInfo.plus.price}/${t("vip.years")}`,
discountText: props.productInfo.plus.discountText || `¥${props.productInfo.plus.price3}/3${t("vip.years")}`,
priceText: props.productInfo.plus.priceText || `¥${props.productInfo.plus.price}/${t("certd.vip.years")}`,
discountText: props.productInfo.plus.discountText || `¥${props.productInfo.plus.price3}/3${t("certd.vip.years")}`,
tooltip: props.productInfo.plus.tooltip,
},
comm: {
title: t("vip.business_edition"),
desc: t("vip.commercial_license"),
title: t("certd.vip.business_edition"),
desc: t("certd.vip.commercial_license"),
type: "comm",
icon: "vaadin:handshake",
privilege: t("vip.comm_privilege").split("\n"),
priceText: props.productInfo.comm.priceText || `¥${props.productInfo.comm.price}/${t("vip.years")}`,
discountText: props.productInfo.comm.discountText || `¥${props.productInfo.comm.price3}/3${t("vip.years")}`,
privilege: t("certd.vip.comm_privilege").split("\n"),
priceText: props.productInfo.comm.priceText || `¥${props.productInfo.comm.price}/${t("certd.vip.years")}`,
discountText: props.productInfo.comm.discountText || `¥${props.productInfo.comm.price3}/3${t("certd.vip.years")}`,
tooltip: props.productInfo.comm.tooltip,
trial: {
title: t("vip.click_to_get_7_day_trial"),
title: t("certd.vip.click_to_get_7_day_trial"),
click: () => {
props.openStarModal("comm");
},
@@ -1,4 +1,4 @@
<script lang="ts" setup>
<script lang="ts" setup>
import { BasicLayout, LockScreen, UserDropdown } from "/@/vben/layouts";
import { computed, onErrorCaptured, onMounted, provide, ref } from "vue";
@@ -23,14 +23,14 @@ const menus = computed(() => [
router.push("/cert/mine/user-profile");
},
icon: "fa-solid:book",
text: t("certd.accountInfo"),
text: t("certd.mine.accountInfo"),
},
{
handler: () => {
router.push("/cert/mine/security");
},
icon: "fluent:shield-keyhole-16-regular",
text: t("certd.securitySettings"),
text: t("certd.mine.securitySettings"),
},
]);
@@ -109,7 +109,7 @@ const projectStore = useProjectStore();
<vip-button class="flex-center header-btn" mode="nav" />
</div>
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
<fs-button shape="circle" type="text" icon="clarity:host-solid-badged" :text="null" :tooltip="{ title: t('certd.client') }" @click="goCertdClient" />
<fs-button shape="circle" type="text" icon="clarity:host-solid-badged" :text="null" :tooltip="{ title: t('certd.navigation.client') }" @click="goCertdClient" />
</div>
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
<fs-button shape="circle" type="text" icon="ion:logo-github" :text="null" @click="goGithub" />
@@ -13,36 +13,54 @@ import notification from "./certd/notification";
import addon from "./certd/addon";
import suite from "./certd/suite";
import project from "./certd/project";
import syssettings from "./certd/sys-settings";
import sysplugin from "./certd/sys-plugin";
import sysauthority from "./certd/sys-authority";
import syscname from "./certd/sys-cname";
import settings from "./certd/sys-settings";
import plugin from "./certd/sys-plugin";
import authority from "./certd/sys-authority";
import cnameSettings from "./certd/sys-cname";
import tutorial from "./certd/tutorial";
import cron from "./certd/cron";
import client from "./certd/client";
import wallet from "./certd/wallet";
import nettest from "./certd/nettest";
import audit from "./certd/audit";
import applyTemplate from "./certd/apply-template";
import dnsPersist from "./certd/dns-persist";
import auth from "./certd/auth";
import guide from "./certd/guide";
import vip from "./certd/vip";
// Note: @ is reserved in locale messages; use {'@'} when needed.
export default {
...common,
...navigation,
...dashboard,
...pipeline,
...history,
...monitor,
...certdomain,
...cname,
...access,
...open,
...mine,
...notification,
...addon,
...suite,
...project,
...syssettings,
...sysplugin,
...sysauthority,
...syscname,
...tutorial,
...cron,
...client,
common,
navigation,
dashboard,
pipeline,
history,
monitor,
certdomain,
cname,
access,
open,
mine,
notification,
addon,
suite,
project,
sys: {
settings,
plugin,
authority,
cname: cnameSettings,
},
tutorial,
cron,
client,
wallet,
nettest,
audit,
applyTemplate,
dnsPersist,
auth,
guide,
vip,
};
@@ -4,4 +4,11 @@ export default {
nameHelper: "Fill in as you like, useful to distinguish when multiple authorizations of the same type exist",
level: "Level",
system: "System",
select: "Select",
selectProvider: "Select Authorization Provider",
deleteConfirm: "If this authorization is already in use, pipelines may fail. Proceed with caution.",
name: "Name",
user: "User",
type: "Type",
selectType: "Please select a type",
};
@@ -0,0 +1,11 @@
export default {
setSuccess: "Settings saved",
editTitle: "Edit Certificate Application Template",
addTitle: "Add Certificate Application Template",
name: "Template Name",
default: "Default",
setDefault: "Set as Default",
disabled: "Disabled",
createTime: "Created At",
config: "Configuration",
};
@@ -0,0 +1,10 @@
export default {
createTime: "Operation Time",
type: "Operation Type",
action: "Action",
result: "Result",
success: "Success",
failed: "Failed",
remark: "Remark",
ipAddress: "IP Address",
};
@@ -1,58 +1,4 @@
export default {
welcomeBack: "Welcome Back",
pageTitle: "Plug-and-play Admin system",
pageDesc: "Efficient, versatile frontend template",
loginSuccess: "Login Successful",
loginSuccessDesc: "Welcome Back",
loginSubtitle: "Enter your account details to manage your projects",
selectAccount: "Quick Select Account",
username: "Username",
password: "Password",
usernameTip: "Please enter username",
passwordErrorTip: "Password is incorrect",
passwordTip: "Please enter password",
verifyRequiredTip: "Please complete the verification first",
rememberMe: "Remember Me",
createAnAccount: "Create an Account",
createAccount: "Create Account",
alreadyHaveAccount: "Already have an account?",
accountTip: "Don't have an account?",
signUp: "Sign Up",
signUpSubtitle: "Make managing your applications simple and fun",
confirmPassword: "Confirm Password",
confirmPasswordTip: "The passwords do not match",
agree: "I agree to",
privacyPolicy: "Privacy-policy",
terms: "Terms",
agreeTip: "Please agree to the Privacy Policy and Terms",
goToLogin: "Login instead",
passwordStrength: "Use 8 or more characters with a mix of letters, numbers & symbols",
forgetPassword: "Forget Password?",
forgetPasswordSubtitle: "Enter your email and we'll send you instructions to reset your password",
emailTip: "Please enter email",
emailValidErrorTip: "The email format you entered is incorrect",
sendResetLink: "Send Reset Link",
email: "Email",
qrcodeSubtitle: "Scan the QR code with your phone to login",
qrcodePrompt: "Click 'Confirm' after scanning to complete login",
qrcodeLogin: "QR Code Login",
codeSubtitle: "Enter your phone number to start managing your project",
code: "Security code",
codeTip: "Security code required {0} characters",
mobile: "Mobile",
mobileLogin: "Mobile Login",
mobileTip: "Please enter mobile number",
mobileErrortip: "The phone number format is incorrect",
sendCode: "Get Security code",
sendText: "Resend in {0}s",
thirdPartyLogin: "Or continue with",
loginAgainTitle: "Please Log In Again",
loginAgainSubTitle: "Your login session has expired. Please log in again to continue.",
layout: {
center: "Align Center",
alignLeft: "Align Left",
alignRight: "Align Right",
},
loginType: {
password: "Password Login",
sms: "Mobile Login",
@@ -110,4 +56,30 @@ export default {
userInfo: "User Info",
securitySettingTip: "2FA Setting",
securitySetting: "2FA Setting",
register: {
usernameTab: "Register with username",
emailTab: "Register with email",
mobileTab: "Register with mobile",
username: "Username",
email: "Email",
password: "Password",
confirmPassword: "Confirm Password",
captcha: "Captcha",
emailCode: "Email verification code",
mobileLogin: "Go to mobile login (login to register)",
inviteCode: "Invitation code",
inviteCodeOptional: "Invitation code (optional)",
submit: "Register",
login: "Log In",
noMethodEnabled: "No registration method is enabled",
usernameRequired: "Please enter your username",
emailRequired: "Please enter your email",
emailInvalid: "Please enter a valid email address",
passwordRequired: "Please enter your password",
confirmPasswordRequired: "Please confirm your password",
passwordMismatch: "The two passwords do not match",
smsCodeRequired: "Please enter the SMS verification code",
emailCodeRequired: "Please enter the email verification code",
captchaRequired: "Please complete the captcha",
},
};
@@ -1,5 +1,6 @@
export default {
domain: {
dnsPersistDescription: "Currently, only Google certificates support DNS persistent validation.",
domainManager: "Domain Manager",
domainDescription: "used to auto apply for certificate", //管理域名的校验方式,用于申请证书时自动选择验证方式
domain: "Domain",
@@ -1,20 +1,18 @@
export default {
clientManager: "Client Manager",
client: {
title: "Client Manager",
description: "View online status and managed site count of connected Certd clients. Clients report a heartbeat every 10 minutes and are marked offline if no heartbeat arrives for 30 minutes.",
plusRequired: "This feature requires the Pro edition",
machineName: "Machine",
clientId: "Client ID",
version: "Version",
os: "OS",
status: "Status",
online: "Online",
offline: "Offline",
siteCount: "Sites",
httpsSiteCount: "HTTPS Sites",
syncedSiteCount: "Synced",
failedSiteCount: "Failed",
lastHeartbeatAt: "Last Heartbeat",
},
title: "Client Manager",
description: "View online status and managed site count of connected Certd clients. Clients report a heartbeat every 10 minutes and are marked offline if no heartbeat arrives for 30 minutes.",
plusRequired: "This feature requires the Pro edition",
machineName: "Machine",
clientId: "Client ID",
version: "Version",
os: "OS",
status: "Status",
online: "Online",
offline: "Offline",
siteCount: "Sites",
httpsSiteCount: "HTTPS Sites",
syncedSiteCount: "Synced",
failedSiteCount: "Failed",
lastHeartbeatAt: "Last Heartbeat",
};
@@ -1,4 +1,6 @@
export default {
required: "Required",
no: "No",
usera: "User",
disabledSuccess: "Disabled successfully",
app: {
@@ -21,6 +23,14 @@ export default {
add: "Generate New Key",
edit: "Edit",
deleteSuccess: "Delete successful",
fastCrud: {
view: "View",
copy: "Copy",
edit: "Edit",
remove: "Delete",
addSuccess: "Added successfully",
saveSuccess: "Saved successfully",
},
saveSuccess: "Saved successfully",
cancel: "Cancel",
yes: "Yes",
@@ -1,50 +1,59 @@
export default {
dashboard: {
greeting: "Hello, {name}, welcome to 【{site}】",
latestVersion: "Latest version: {version}",
validUntil: "Valid until:",
tutorialTooltip: "Click to view detailed tutorial",
tutorialText: "Only 3 steps to automatically apply and deploy certificates",
alertMessage: "Certificates and credentials are sensitive. Do not use untrusted online Certd services or images. Always self-host and use official release channels:",
helpDoc: "Help Docs",
pipelineCount: "Number of Certificate Pipelines",
noPipeline: "You have no certificate pipelines yet",
enabledCount: "Enabled",
disabledCount: "Disabled",
certCount: "Number of Certificates",
noCert: "You have no certificates yet",
manageCert: "View Certificates",
siteMonitorCount: "Number of Monitored Sites",
siteAbnormalCount: "Abnormal",
siteNormalCount: "Normal",
manageSiteMonitor: "Manage Monitored Sites",
domainCount: "Number of Domains",
domainExpiringCount: "Expiring",
domainExpiredCount: "Expired",
domainNotExpiredCount: "Not Expired",
manageDomain: "Manage Domains",
certExpiringCount: "Soon-to-Expire",
certExpiredCount: "Expired",
certNoExpireCount: "Not Expired",
createNow: "Create Now",
managePipeline: "Manage Pipelines",
pipelineStatus: "Pipeline Status",
recentRun: "Recent Run Statistics",
runCount: "Run Count",
expiringCerts: "Soon-to-Expire Certificates",
totalGeneratedCertCount: "Total Certificates Generated",
singleDomainCertShortCount: "Single-domain",
multiDomainCertShortCount: "Multi-domain",
wildcardCertShortCount: "Wildcard",
singleDomainCertCount: "Single-domain Certificates Generated",
multiDomainCertCount: "Multi-domain Certificates Generated",
wildcardCertCount: "Wildcard Certificates Generated",
savedAmount: "Estimated savings",
savedAmountRule: "Estimated at one quarter of Tencent Cloud's annual certificate prices: single-domain ¥532, multi-domain ¥912, and wildcard ¥2147. Actual savings may vary.",
totalPipelineRuns: "Total Pipeline Runs",
supportedTasks: "Overview of Supported Deployment Tasks",
changeLog: "Change Log",
stableRelease: "Stable",
latestRelease: "Preview",
},
greeting: "Hello, {name}, welcome to 【{site}】",
latestVersion: "Latest version: {version}",
validUntil: "Valid until:",
tutorialTooltip: "Click to view detailed tutorial",
tutorialText: "Only 3 steps to automatically apply and deploy certificates",
alertMessage: "Certificates and credentials are sensitive. Do not use untrusted online Certd services or images. Always self-host and use official release channels:",
helpDoc: "Help Docs",
pipelineCount: "Number of Certificate Pipelines",
noPipeline: "You have no certificate pipelines yet",
enabledCount: "Enabled",
disabledCount: "Disabled",
certCount: "Number of Certificates",
noCert: "You have no certificates yet",
manageCert: "View Certificates",
siteMonitorCount: "Number of Monitored Sites",
siteAbnormalCount: "Abnormal",
siteNormalCount: "Normal",
manageSiteMonitor: "Manage Monitored Sites",
domainCount: "Number of Domains",
domainExpiringCount: "Expiring",
domainExpiredCount: "Expired",
domainNotExpiredCount: "Not Expired",
manageDomain: "Manage Domains",
certExpiringCount: "Soon-to-Expire",
certExpiredCount: "Expired",
certNoExpireCount: "Not Expired",
createNow: "Create Now",
managePipeline: "Manage Pipelines",
pipelineStatus: "Pipeline Status",
recentRun: "Recent Run Statistics",
runCount: "Run Count",
expiringCerts: "Soon-to-Expire Certificates",
totalGeneratedCertCount: "Total Certificates Generated",
singleDomainCertShortCount: "Single-domain",
multiDomainCertShortCount: "Multi-domain",
wildcardCertShortCount: "Wildcard",
singleDomainCertCount: "Single-domain Certificates Generated",
multiDomainCertCount: "Multi-domain Certificates Generated",
wildcardCertCount: "Wildcard Certificates Generated",
savedAmount: "Estimated savings",
savedAmountRule: "Estimated at one quarter of Tencent Cloud's annual certificate prices: single-domain ¥532, multi-domain ¥912, and wildcard ¥2147. Actual savings may vary.",
totalPipelineRuns: "Total Pipeline Runs",
supportedTasks: "Overview of Supported Deployment Tasks",
supportedTasksHelper: "This list is for display only. Create a pipeline to use these tasks.",
changeLog: "Change Log",
stableRelease: "Stable",
latestRelease: "Preview",
consoleTitle: "Console",
userTotal: "Total Users",
manageUsers: "Manage Users",
userGrowth: "User Growth",
newUsers: "New Users",
allPipelineTotal: "Total Pipelines",
managePipelines: "Manage Pipelines",
pipelineGrowth: "Pipeline Growth",
newPipelines: "New Pipelines",
recentRunTitle: "Recent Run Statistics",
};
@@ -0,0 +1,24 @@
export default {
pending: "Pending Setup",
created: "Created",
validating: "Validating",
valid: "Valid",
retry: "Retry",
deleteTxtTip: "Delete the TXT record at the provider",
accountUriMissing: "The ACME account authorization is missing accountUri. Please regenerate the account.",
verifySuccess: "Validation succeeded",
verifyFailed: "No matching TXT record found. Please try again later.",
submitted: "Validation submitted",
selectProviderAndAccess: "Select a DNS provider and authorization",
txtCreated: "TXT record created",
settingTitle: "Set DNS TXT Record",
manualAdd: "Add Manually",
autoAdd: "Add with Authorization",
manualTip: "Add the following TXT record in your DNS console, then click OK to validate immediately.",
autoTip: "Select a DNS provider and authorization. The system will create the TXT record and validate it in the background.",
mainDomain: "Main Domain",
txtHost: "TXT Host",
txtValue: "TXT Value",
provider: "DNS Provider",
access: "DNS Authorization",
};
@@ -1,4 +1,7 @@
import monitorSite from "./monitor-site";
export default {
...monitorSite,
certificateRepo: {
title: "Certificate Repository",
sub: "Certificates generated from pipeline",
@@ -1,4 +1,9 @@
export default {
home: "Home",
login: "Login",
register: "Register",
forgotPassword: "Forgot Password",
oauthCallback: "OAuth Callback",
framework: {
title: "Framework",
home: "Home",
@@ -13,10 +18,13 @@ export default {
accessManager: "Access Management",
dnsPersistRecord: "DNS Persist Records",
certApplyTemplate: "Certificate Apply Templates",
certApplyTemplateHelper: "Preset certificate application parameters. They are filled automatically when creating a pipeline (excluding domains and validation methods).",
subDomain: "Subdomain Delegation Settings",
pipelineGroup: "Pipeline Group Management",
pipelineGroupHelper: "Manage pipeline groups",
openKey: "Open API Key",
notification: "Notification Settings",
notificationHelper: "Manage notification configurations",
siteMonitorSetting: "Site Monitor Settings",
auditLog: "Audit Log",
userSecurity: "Security Settings",
@@ -25,6 +33,7 @@ export default {
mySuite: "My Suite",
suiteBuy: "Suite Purchase",
myTrade: "My Orders",
myWallet: "My Wallet",
inviteCommission: "Incentive Plan",
paymentReturn: "Payment Return",
client: "Certd Client",
@@ -48,7 +57,9 @@ export default {
userManager: "User Management",
userDataManager: "User Data Management",
pipelineManager: "User Pipeline Management",
pipelineManagerHelper: "Manage all users' pipelines",
siteMonitorManager: "User Certificate Monitor",
siteMonitorManagerHelper: "Manage all users' certificate monitors",
suiteManager: "Suite Management",
suiteSetting: "Suite Settings",
orderManager: "Order Management",
@@ -72,6 +83,8 @@ export default {
currentProject: "Current Project",
projectMemberManager: "Project Member",
auditLog: "Audit Log",
auditLogHelper: "View all users' operation records",
jobHistory: "Monitoring Execution History",
domainMonitorSetting: "Domain Monitor Settings",
},
};
@@ -0,0 +1,13 @@
export default {
title: "Network Test",
helper: "Test whether your server container network is working",
customDomain: "Custom Domain Test",
serverInfo: "Server Information",
refresh: "Refresh",
loading: "Loading...",
fetchFailed: "Failed to fetch server information",
noInfo: "No information",
localIp: "Local IP",
publicIp: "Public IP",
dnsServer: "DNS Server",
};
@@ -6,6 +6,10 @@ export default {
keyRemark: "Key Purpose",
keyRemarkHelper: "Describe the purpose of this key for easier identification",
keyRemarkMaxChars: "Maximum 512 characters",
returnCertPassword: "Return certificate password",
returnCertPasswordHelper: "When enabled, the certificate password is included in Open API certificate responses. Keep this key secure.",
yes: "Yes",
no: "No",
gen: {
text: "API Test",
title: "x-certd-token",
@@ -65,6 +65,145 @@ export default {
legoAcme: "Lego-ACME: Based on Lego, supports a wide range of DNS providers, suitable for users familiar with Lego",
aliyunOrder: "Aliyun-Order: Get certificate from Aliyun certificate order",
},
editor: {
editTask: "Edit Task",
editStep: "Edit Step",
installedPlugins: "Installed Plugins",
pluginMarket: "Plugin Market",
searchPluginMarket: "Search plugin market",
searchLocalPlugins: "Search local plugins",
loadingPluginMarket: "Loading plugin market...",
noPluginFound: "No plugins found",
triggerManually: "Trigger Manually",
triggerSource: "Trigger Source",
scheduledTrigger: "Trigger Source (Scheduled)",
webhookTrigger: "Trigger Source (Webhook)",
certExpireTime: "Certificate expiration time: ",
certExpired: "Certificate expired ",
viewCertificate: "View Certificate",
downloadCertificate: "Download Certificate",
nextExecutionTime: "Next execution time: ",
noTriggerSource: "No trigger source configured; it will not run automatically",
validityPeriod: "Validity period: ",
save: "Save",
cancel: "Cancel",
addStage: "New Stage",
addTask: "Add Task",
addAfterTask: "Add After-Task",
addNotification: "Add Notification",
notificationNotSet: "Notification not set",
history: "Execution History",
historyHint: "Click a task to view logs",
taskName: "Task Name",
taskSteps: "Task Steps",
addStep: "Add Step",
copy: "Copy",
paste: "Paste",
confirm: "Confirm",
required: "This field is required",
taskNeedsStep: "At least one step is required, or delete this task using the button beside the title",
step: "Step",
endStage: "End",
confirmTitle: "Confirm",
confirmManualRun: "Are you sure you want to trigger the run manually?",
taskLog: "Task Log",
noLogs: "No logs (this node was not triggered or has no log records for this run)",
aiAnalyze: "AI Analysis",
rerun: "Rerun",
downloadLogs: "Download Logs",
close: "Close",
batchEditSteps: "Batch Edit Steps",
selectAllSteps: "Select All Steps",
batchEnableSteps: "Batch Enable Steps",
batchDisableSteps: "Batch Disable Steps",
batchDeleteSteps: "Batch Delete Steps",
exitBatchEdit: "Exit Batch Edit",
stepsSerialHelper: "Steps run sequentially. If an earlier step fails, later steps will not run.",
current: "Current",
view: "View",
confirmCancel: "Confirm Cancellation",
confirmCancelTask: "Cancel this task?",
taskCanceled: "Task canceled successfully",
selectAllTasks: "Select all tasks",
batchEnableTasks: "Enable tasks in batch",
batchDisableTasks: "Disable tasks in batch",
batchDeleteTasks: "Delete tasks in batch",
exitBatchEditTasks: "Exit batch edit",
editStageTitle: "Edit stage title",
batchEditTasks: "Edit tasks in batch",
dragSort: "Drag to reorder",
forceRerun: "Force rerun this step",
resizeStage: "Drag to resize stage",
afterLabel: "After-task",
notificationLabel: "Notification",
unsavedLeave: "This pipeline is not saved. Leave anyway?",
newPipeline: "New Pipeline",
newTask: "New Task",
newStage: "New Stage",
stageSuffix: " Stage",
saveBeforeRunTitle: "Save before running the pipeline",
saveBeforeRunContent: "Save it first?",
runUnsupported: "Running is not supported yet",
addStageAndTask: "Please add a stage and task first",
prerequisiteMissing: "The prerequisite output step {param} for {step} does not exist or is disabled",
selectPlugin: "Select plugin",
searchPlugin: "Search plugins",
searchResults: "Search results",
plusPluginRequired: "This plugin requires Certd Professional",
immediateRun: "Run immediately",
immediateRunHelper: "Run the pipeline immediately after saving",
operationSuccess: "Operation successful",
regenerate: "Regenerate",
webhookHelper: "Supports POST and GET requests (each pipeline has a unique Webhook URL)",
regenerateWebhookTitle: "Regenerate the Webhook URL?",
regenerateWebhookContent: "The old Webhook URL will become invalid",
confirmDeleteTask: "Delete this task?",
confirmDeleteStep: "Delete this step?",
confirmDeleteSelectedTasks: "Delete the selected {count} tasks?",
confirmDeleteSelectedSteps: "Delete the selected {count} steps?",
stepCopied: "Step configuration copied. You can paste it in another task editor",
allStepsCopied: "All steps copied. You can paste them in another task editor",
copyFirst: "Please copy first",
pasted: "Pasted successfully",
enterName: "Please enter a name",
pluginTypeFirst: "Please select a type first",
runStrategy: "Run strategy",
runStrategyNormal: "Run normally (required for certificate tasks unless you want this task to run every time)",
runStrategySkip: "Skip after success (choose this for other tasks)",
runStrategyDefault: "Usually keep the default",
runStrategyNormalHelp: "Run normally: runs every time; certificate tasks need this",
runStrategySkipHelp: "Skip after success: skip after one successful run and run again when the certificate changes",
triggerWebhook: "Webhook Trigger",
triggerSchedule: "Scheduled Trigger",
choose: "Select",
noLogsShort: "No logs",
statusSuccess: "Success",
statusError: "Error",
statusSkip: "Skipped",
statusStart: "Running",
statusCanceled: "Canceled",
statusNone: "Not run",
statusDisabled: "Disabled",
statusNoDeployCount: "Insufficient runs",
pluginGroups: {
all: "All",
cert: "Certificate",
host: "Host",
cdn: "CDN",
panel: "Panel",
aliyun: "Alibaba Cloud",
huawei: "Huawei Cloud",
tencent: "Tencent Cloud",
volcengine: "Volcengine",
jdcloud: "JD Cloud",
ucloud: "UCloud",
baidu: "Baidu Cloud",
qiniu: "Qiniu Cloud",
aws: "Amazon Web Services",
other: "Other",
admin: "Administration",
},
},
pipelineForm: {
createTitle: "Create Certificate Pipeline",
moreParams: "More Parameters",
@@ -1,4 +1,50 @@
export default {
title: "Suite",
mySuite: "My Suite",
suiteBuy: "Suite Purchase",
myTrade: "My Orders",
inviteCommission: "Incentive Plan",
inviteSubtitle: "Invite friends and earn generous commissions",
promotionAgreement: "Promotion Agreement",
withdraw: "Withdraw",
withdrawAvailable: "Available to withdraw {amount}",
inviteCode: "Invitation Code",
orderTime: "Time",
inviteTime: "Invitation Time",
inviteeUsername: "Invited Username",
inviteLink: "Invitation Link",
myLevel: "My Level",
unset: "Not set",
commissionRate: "Commission Rate",
commissionAfterPayment: "Commission is calculated at this rate after a friend pays",
proportion: "Rate",
inviteSuccess: "Successful Invites",
incomeRecords: "Income Records",
enableFirst: "Please enable the incentive plan first",
enable: "Enable Incentive Plan",
disabled: "Incentive plan is not enabled",
totalIncome: "Total Income",
monthIncome: "This Month's Income",
promotionAmount: "Total Promotion Amount",
inviteeCount: "People Invited",
people: " people",
agreePromotion: "I have read and agree to the promotion agreement",
close: "Close",
postpone: "Later",
agreeAndEnable: "Agree and Enable",
agreeRequired: "Please check the agreement first",
enabledSuccess: "Incentive plan enabled",
purchaseSuccess: "Suite purchased successfully",
agreementPlaceholder: "Enter the promotion agreement users must accept before enabling the incentive plan",
activationExchange: "Redeem Activation Code",
activationCode: "Activation Code",
enterActivationCode: "Please enter the activation code",
enterCdkCode: "Please enter the CDK activation code",
activateSuccess: "Activated successfully",
exchangeFailed: "Redemption failed",
noSuite: "No suites available for purchase",
suiteHelperStack: "Note: Multiple suites and addons can be purchased, and their quantities are accumulated",
suiteHelperLatest: "Note: 1) Only the latest suite is active at a time; 2) Multiple addons can be purchased and take effect immediately; 3) Suite and addon quantities are accumulated",
order: {
confirmTitle: "Order Confirmation",
package: "Package",
@@ -1,4 +1,14 @@
export default {
aiDevTitle: "AI Plugin Development",
certPluginConfig: "Certificate Plugin Configuration",
saveSuccess: "Saved successfully",
commonGoogleAcme: "Common Google ACME Account",
commonZeroSslAcme: "Common ZeroSSL ACME Account",
commonLiteSslAcme: "Common LiteSSL ACME Account",
otherConfig: "Other Configuration",
certApplyDefaults: "Certificate Apply Plugin Defaults",
customCertApplyParams: "Custom certificate application plugin parameters",
save: "Save",
titlea: "Title",
pluginFile: "Plugin File",
selectPluginFile: "Select plugin file",
@@ -1,118 +1,134 @@
export default {
sys: {
setting: {
baseSetting: "Base Settings",
registerSetting: "Register Settings",
safeSetting: "Safe Settings",
paymentSetting: "Payment Settings",
captchaSetting: "Captcha Setting",
pipelineSetting: "Pipeline Settings",
oauthSetting: "Login Settings",
networkSetting: "Network Settings",
adminModeSetting: "Admin Mode Settings",
adminModeHelper: "enterprise mode : allow to create and manage pipelines, roles, users, etc.\n saas mode : only allow to create and manage pipelines",
enterpriseMode: "Enterprise Mode",
saasMode: "SaaS Mode",
modeIntroTitle: "Management Mode Introduction",
saasModeDescription: "SaaS mode: each user manages and independently uses their own pipelines and authorization resources.",
enterpriseModeDescription: "Enterprise mode: pipelines, certificates, and authorization resources are managed through projects for all internal users.",
switchModeNow: "Switch Mode Now",
suiteSetting: "Suite Settings",
orderManager: "Order Management",
headerMenuSetting: "Top Menu Settings",
sitePersonalization: "Site Personalization",
siteName: "Site Name",
slogan: "Subtitle / Slogan",
loginLogo: "Login Page Logo",
entityName: "Entity Name",
shownAtBottom: "Displayed at the bottom",
entityUrl: "Entity URL",
modeSaasHelper: "SaaS mode: each user manages and independently uses their own pipelines and authorization resources.",
modeEnterpriseHelper: "Enterprise mode: pipelines, certificates, and authorization resources are managed through projects for all internal users.",
modeMore: "More Management Mode Details",
modeFixedWarning: "Choose a suitable mode before use and avoid switching it frequently afterwards.",
modeMigrate: "After switching to enterprise mode, personal data created earlier will be hidden. You can migrate it to a project.",
modeCommWarning: "Enterprise mode is not recommended for the commercial edition unless you intend to use it internally.",
baseSetting: "Base Settings",
registerSetting: "Register Settings",
safeSetting: "Safe Settings",
paymentSetting: "Payment Settings",
captchaSetting: "Captcha Setting",
pipelineSetting: "Pipeline Settings",
oauthSetting: "Login Settings",
networkSetting: "Network Settings",
adminModeSetting: "Admin Mode Settings",
adminModeHelper: "enterprise mode : allow to create and manage pipelines, roles, users, etc.\n saas mode : only allow to create and manage pipelines",
enterpriseMode: "Enterprise Mode",
saasMode: "SaaS Mode",
showRunStrategy: "Show RunStrategy",
showRunStrategyHelper: "Allow modify the run strategy of the task",
homePageEnabled: "Enable Home Page",
showRunStrategy: "Show RunStrategy",
showRunStrategyHelper: "Allow modify the run strategy of the task",
homePageEnabled: "Enable Home Page",
captchaEnabled: "Enable Login Captcha",
captchaHelper: "Whether to enable captcha verification for login",
captchaType: "Captcha Setting",
captchaTest: "Captcha Test",
// 保存后再点击测试,请务必测试通过了,再开启登录验证码
captchaTestHelper: "Save and click test, please make sure the test is passed before enabling login captcha",
captchaEnabled: "Enable Login Captcha",
captchaHelper: "Whether to enable captcha verification for login",
captchaType: "Captcha Setting",
captchaTest: "Captcha Test",
// 保存后再点击测试,请务必测试通过了,再开启登录验证码
captchaTestHelper: "Save and click test, please make sure the test is passed before enabling login captcha",
pipelineValidTimeEnabled: "Enable Pipeline Valid Time",
pipelineValidTimeEnabledHelper: "Whether to enable the valid time of the pipeline",
certDomainAddToMonitorEnabled: "Add Domain to Certificate Monitor",
certDomainAddToMonitorEnabledHelper: "Whether to add the domain to the certificate monitor",
pipelineValidTimeEnabled: "Enable Pipeline Valid Time",
pipelineValidTimeEnabledHelper: "Whether to enable the valid time of the pipeline",
certDomainAddToMonitorEnabled: "Add Domain to Certificate Monitor",
certDomainAddToMonitorEnabledHelper: "Whether to add the domain to the certificate monitor",
defaultCertRenewDays: "Default Certificate Renew Days",
defaultCertRenewDaysHelper: "Default certificate renewal days, helpful for table list progress bar display",
defaultCertRenewDaysRecommend: "Recommend 15",
defaultCertRenewDays: "Default Certificate Renew Days",
defaultCertRenewDaysHelper: "Default certificate renewal days, helpful for table list progress bar display",
defaultCertRenewDaysRecommend: "Recommend 15",
pipelineMaxRunningCount: "Max Running Count",
pipelineMaxRunningCountHelper: "Max running count of the pipeline",
pipelineMaxRunningCountRecommend: "Recommend 5-15, default 10",
pipelineMaxRunningCount: "Max Running Count",
pipelineMaxRunningCountHelper: "Max running count of the pipeline",
pipelineMaxRunningCountRecommend: "Recommend 5-15, default 10",
acmeWalkFromAuthoritative: "Check TXT Record from Authoritative NS",
acmeWalkFromAuthoritativeHelper: "Apply certificate when whether to check the TXT record from authoritative NS server first",
acmeWalkFromAuthoritative: "Check TXT Record from Authoritative NS",
acmeWalkFromAuthoritativeHelper: "Apply certificate when whether to check the TXT record from authoritative NS server first",
customAcmeManage: "Custom ACME Management",
customAcmeManageHelper:
"Configure certificate authorities (built-in + custom ACME). Built-in providers cannot be modified or deleted. Custom ACME providers (intranet CA, enterprise CA or any RFC 8555 compatible ACME service) become selectable as certificate authorities in apply tasks and ACME account authorization",
customAcmeName: "Name",
customAcmeSslProvider: "SSL Provider",
customAcmeSslProviderHelper: "Unique identifier, e.g. myca; used to distinguish providers in pipeline and ACME account",
customAcmeReverseProxy: "Reverse Proxy",
customAcmeReverseProxyHelper:
"For example, for Let's Encrypt, configure the reverse proxy on your overseas server: \nproxy_pass https://acme-v02.api.letsencrypt.org/; \nthen fill in your reverse proxy server domain here, without http://",
customAcmeAdd: "Add Custom ACME",
customAcmeEdit: "Edit Custom ACME",
customAcmeNeedEab: "Need EAB",
customAcmeBuiltIn: "Built-in",
customAcmeTag: "Custom",
customAcmeDeleteConfirmTitle: "Delete Custom ACME",
customAcmeDeleteConfirmContent: "Deleting '{title}' may affect pipelines using it to apply certificates. Are you sure?",
customAcmeSaveCheck: "Name, sslProvider and Directory URL are required",
customAcmeSslProviderUnique: "The sslProvider identifier must be unique",
customAcmeManage: "Custom ACME Management",
customAcmeManageHelper:
"Configure certificate authorities (built-in + custom ACME). Built-in providers cannot be modified or deleted. Custom ACME providers (intranet CA, enterprise CA or any RFC 8555 compatible ACME service) become selectable as certificate authorities in apply tasks and ACME account authorization",
customAcmeName: "Name",
customAcmeSslProvider: "SSL Provider",
customAcmeSslProviderHelper: "Unique identifier, e.g. myca; used to distinguish providers in pipeline and ACME account",
customAcmeReverseProxy: "Reverse Proxy",
customAcmeReverseProxyHelper:
"For example, for Let's Encrypt, configure the reverse proxy on your overseas server: \nproxy_pass https://acme-v02.api.letsencrypt.org/; \nthen fill in your reverse proxy server domain here, without http://",
customAcmeAdd: "Add Custom ACME",
customAcmeEdit: "Edit Custom ACME",
customAcmeNeedEab: "Need EAB",
customAcmeBuiltIn: "Built-in",
customAcmeTag: "Custom",
customAcmeDeleteConfirmTitle: "Delete Custom ACME",
customAcmeDeleteConfirmContent: "Deleting '{title}' may affect pipelines using it to apply certificates. Are you sure?",
customAcmeSaveCheck: "Name, sslProvider and Directory URL are required",
customAcmeSslProviderUnique: "The sslProvider identifier must be unique",
fixedCertExpireDays: "Fixed Cert Expire Days",
fixedCertExpireDaysHelper: "Fixed cert expiration days, helpful for table list progress bar display",
fixedCertExpireDaysRecommend: "Recommend 90",
fixedCertExpireDays: "Fixed Cert Expire Days",
fixedCertExpireDaysHelper: "Fixed cert expiration days, helpful for table list progress bar display",
fixedCertExpireDaysRecommend: "Recommend 90",
enableOauth: "Enable OAuth2 Login",
oauthEnabledHelper: "Whether to enable OAuth2 login",
oauthProviders: "OAuth2 Login Providers",
oauthType: "OAuth2 Login Type",
oauthConfig: "OAuth2 Login Config",
oauthProviderSelectorPlaceholder: "Not Configured",
oauthCallback: "Callback URL",
oauthCallbackHelper: "Copy this URL to the callback address of the OAuth2 login provider",
oauthCallbackCopy: "Copy Callback URL",
oauthAutoRegister: "Auto Register User",
oauthAutoRegisterCheckedText: "Auto Register",
oauthAutoRegisterUnCheckedText: "User Select",
oauthAutoRegisterHelper: "Whether to auto register user when login",
oauthAutoRedirect: "Auto Redirect to OAuth2 Login",
oauthAutoRedirectHelper: "Whether to auto redirect to OAuth2 login when login (using the first enabled OAuth2 login type)",
oauthOnly: "OAuth2 Login Only",
oauthOnlyHelper: "Only allow OAuth2 login. Password login remains available for 10 minutes after server startup as an emergency window.",
enablePasskey: "Enable Passkey Login",
passkeyHostnameNotSame: "Passkey hostname must be the same as the main domain",
passkeyEnabledHelper:
"1、Site must enable https \n2、Domain name must not change, otherwise the registered passkey will be invalid \n3、Domain name must be the same as the main domain, otherwise the registered passkey will be invalid",
enableOauth: "Enable OAuth2 Login",
oauthEnabledHelper: "Whether to enable OAuth2 login",
oauthProviders: "OAuth2 Login Providers",
oauthType: "OAuth2 Login Type",
oauthConfig: "OAuth2 Login Config",
oauthProviderSelectorPlaceholder: "Not Configured",
oauthCallback: "Callback URL",
oauthCallbackHelper: "Copy this URL to the callback address of the OAuth2 login provider",
oauthCallbackCopy: "Copy Callback URL",
oauthAutoRegister: "Auto Register User",
oauthAutoRegisterCheckedText: "Auto Register",
oauthAutoRegisterUnCheckedText: "User Select",
oauthAutoRegisterHelper: "Whether to auto register user when login",
oauthAutoRedirect: "Auto Redirect to OAuth2 Login",
oauthAutoRedirectHelper: "Whether to auto redirect to OAuth2 login when login (using the first enabled OAuth2 login type)",
oauthOnly: "OAuth2 Login Only",
oauthOnlyHelper: "Only allow OAuth2 login. Password login remains available for 10 minutes after server startup as an emergency window.",
enablePasskey: "Enable Passkey Login",
passkeyHostnameNotSame: "Passkey hostname must be the same as the main domain",
passkeyEnabledHelper:
"1、Site must enable https \n2、Domain name must not change, otherwise the registered passkey will be invalid \n3、Domain name must be the same as the main domain, otherwise the registered passkey will be invalid",
email: {
templates: "Email Templates",
templateType: "Template Type",
templateProvider: "Template Config",
email: {
templates: "Email Templates",
templateType: "Template Type",
templateProvider: "Template Config",
templateSetting: "Email Template Setting",
serverSetting: "Email Server Setting",
sendTest: "Send Test",
templateSetting: "Email Template Setting",
serverSetting: "Email Server Setting",
sendTest: "Send Test",
templateProviderSelectorPlaceholder: "Not Configured",
},
notice: "System Notice",
noticeHelper: "System notice, will be displayed on the login page",
noticePlaceholder: "System notice",
customFooter: "Custom Footer",
customFooterHelper: "Custom site footer, displayed at the bottom of the page, support HTML format",
customFooterPlaceholder: "Custom footer content",
environmentVars: "Environment Variables",
environmentVarsHelper: "configure the runtime environment variables, one per line, format: KEY=VALUE",
commonHeaders: "Common Headers",
commonHeadersHelper: "Common headers automatically added to server-side HTTP requests, one per line, format: KEY=VALUE. Existing request headers with the same name are not overwritten.",
bindUrl: "Bind URL",
bindUrlHelper: "Bind URL, used as your site URL in notifications",
},
templateProviderSelectorPlaceholder: "Not Configured",
},
notice: "System Notice",
noticeHelper: "System notice, will be displayed on the login page",
noticePlaceholder: "System notice",
customFooter: "Custom Footer",
customFooterHelper: "Custom site footer, displayed at the bottom of the page, support HTML format",
customFooterPlaceholder: "Custom footer content",
environmentVars: "Environment Variables",
environmentVarsHelper: "configure the runtime environment variables, one per line, format: KEY=VALUE",
commonHeaders: "Common Headers",
commonHeadersHelper: "Common headers automatically added to server-side HTTP requests, one per line, format: KEY=VALUE. Existing request headers with the same name are not overwritten.",
bindUrl: "Bind URL",
bindUrlHelper: "Bind URL, used as your site URL in notifications",
icpRegistrationNumber: "ICP Registration Number",
icpPlaceholder: "Guangdong ICP xxxxxxx Number",
publicSecurityRegistrationNumber: "Public Security Registration Number",
@@ -1,4 +1,7 @@
import tutorialGuide from "./tutorial-guide";
export default {
...tutorialGuide,
steps: {
createPipeline: "Create Certificate Pipeline",
addTask: "Add Deployment Task",
@@ -0,0 +1,44 @@
export default {
title: "My Wallet",
withdraw: "Withdraw",
withdrawRecords: "Withdrawal Records",
balanceLogs: "Balance Details",
availableAmount: "Available Balance",
frozenAmount: "Frozen Balance",
totalIncomeAmount: "Total Income",
totalWithdrawAmount: "Total Withdrawals",
withdrawSetting: "Withdrawal Settings",
channel: "Withdrawal Channel",
alipay: "Alipay",
bank: "Bank Card",
selectChannel: "Please select a withdrawal channel",
realName: "Real Name",
enterRealName: "Please enter your real name",
account: "Receiving Account",
enterAccount: "Please enter the receiving account",
qrCode: "Receiving QR Code",
uploadQrCode: "Upload an Alipay receiving QR code image",
bankName: "Bank Name",
selectBank: "Please select a bank",
enterBankName: "Please enter the bank name",
saveSuccess: "Saved successfully",
beforeWithdrawTip: "Set up a withdrawal account before withdrawing.",
amount: "Withdrawal Amount",
yuan: "CNY",
enterAmount: "Please enter the withdrawal amount",
submitSuccess: "Withdrawal request submitted",
applyTime: "Application Time",
type: "Type",
income: "Income",
consume: "Balance Deduction",
withdrawFreeze: "Withdrawal Frozen",
withdrawSuccess: "Withdrawal Successful",
withdrawReject: "Withdrawal Returned",
changeAmount: "Amount Changed",
balanceAfter: "Balance After",
remark: "Remark",
pending: "Pending",
approved: "Approved",
rejected: "Rejected",
auditRemark: "Audit Remark",
};
@@ -1,21 +1,7 @@
import certd from "./certd";
import authentication from "./authentication";
import vip from "./vip";
import tutorial from "./tutorial";
import preferences from "./preferences";
import ui from "./ui";
import guide from "./guide";
import common from "./common";
import monitor from "./monitor";
import vben from "./vben";
//注意: @符号是保留字符,需要用{'@'}替换
export default {
certd,
authentication,
vip,
ui,
tutorial,
preferences,
guide,
common,
monitor,
...vben,
};
@@ -0,0 +1,56 @@
export default {
welcomeBack: "Welcome Back",
pageTitle: "Plug-and-play Admin system",
pageDesc: "Efficient, versatile frontend template",
loginSuccess: "Login Successful",
loginSuccessDesc: "Welcome Back",
loginSubtitle: "Enter your account details to manage your projects",
selectAccount: "Quick Select Account",
username: "Username",
password: "Password",
usernameTip: "Please enter username",
passwordErrorTip: "Password is incorrect",
passwordTip: "Please enter password",
verifyRequiredTip: "Please complete the verification first",
rememberMe: "Remember Me",
createAnAccount: "Create an Account",
createAccount: "Create Account",
alreadyHaveAccount: "Already have an account?",
accountTip: "Don't have an account?",
signUp: "Sign Up",
signUpSubtitle: "Make managing your applications simple and fun",
confirmPassword: "Confirm Password",
confirmPasswordTip: "The passwords do not match",
agree: "I agree to",
privacyPolicy: "Privacy-policy",
terms: "Terms",
agreeTip: "Please agree to the Privacy Policy and Terms",
goToLogin: "Login instead",
passwordStrength: "Use 8 or more characters with a mix of letters, numbers & symbols",
forgetPassword: "Forget Password?",
forgetPasswordSubtitle: "Enter your email and we'll send you instructions to reset your password",
emailTip: "Please enter email",
emailValidErrorTip: "The email format you entered is incorrect",
sendResetLink: "Send Reset Link",
email: "Email",
qrcodeSubtitle: "Scan the QR code with your phone to login",
qrcodePrompt: "Click 'Confirm' after scanning to complete login",
qrcodeLogin: "QR Code Login",
codeSubtitle: "Enter your phone number to start managing your project",
code: "Security code",
codeTip: "Security code required {0} characters",
mobile: "Mobile",
mobileLogin: "Mobile Login",
mobileTip: "Please enter mobile number",
mobileErrortip: "The phone number format is incorrect",
sendCode: "Get Security code",
sendText: "Resend in {0}s",
thirdPartyLogin: "Or continue with",
loginAgainTitle: "Please Log In Again",
loginAgainSubTitle: "Your login session has expired. Please log in again to continue.",
layout: {
center: "Align Center",
alignLeft: "Align Left",
alignRight: "Align Right",
},
};
@@ -0,0 +1,10 @@
import preferences from "./preferences";
import ui from "./ui";
import common from "./common";
import authentication from "./authentication";
export default {
preferences,
ui,
common,
authentication,
};
@@ -13,36 +13,54 @@ import notification from "./certd/notification";
import addon from "./certd/addon";
import suite from "./certd/suite";
import project from "./certd/project";
import syssettings from "./certd/sys-settings";
import sysplugin from "./certd/sys-plugin";
import sysauthority from "./certd/sys-authority";
import syscname from "./certd/sys-cname";
import settings from "./certd/sys-settings";
import plugin from "./certd/sys-plugin";
import authority from "./certd/sys-authority";
import cnameSettings from "./certd/sys-cname";
import tutorial from "./certd/tutorial";
import cron from "./certd/cron";
import client from "./certd/client";
import wallet from "./certd/wallet";
import nettest from "./certd/nettest";
import audit from "./certd/audit";
import applyTemplate from "./certd/apply-template";
import dnsPersist from "./certd/dns-persist";
import auth from "./certd/auth";
import guide from "./certd/guide";
import vip from "./certd/vip";
// Note: @ is reserved in locale messages; use {'@'} when needed.
export default {
...common,
...navigation,
...dashboard,
...pipeline,
...history,
...monitor,
...certdomain,
...cname,
...access,
...open,
...mine,
...notification,
...addon,
...suite,
...project,
...syssettings,
...sysplugin,
...sysauthority,
...syscname,
...tutorial,
...cron,
...client,
auth,
guide,
vip,
common,
navigation,
dashboard,
pipeline,
history,
monitor,
certdomain,
cname,
access,
open,
mine,
notification,
addon,
suite,
project,
sys: {
settings,
plugin,
authority,
cname: cnameSettings,
},
tutorial,
cron,
client,
wallet,
nettest,
audit,
applyTemplate,
dnsPersist,
};
@@ -4,4 +4,11 @@ export default {
nameHelper: "随便填,当多个相同类型的授权时,便于区分",
level: "级别",
system: "系统",
select: "选择",
selectProvider: "选择授权提供者",
deleteConfirm: "授权如果已经被使用,可能会导致流水线无法正常运行,请谨慎操作",
name: "名称",
user: "用户",
type: "类型",
selectType: "请选择类型",
};
@@ -0,0 +1,11 @@
export default {
setSuccess: "设置成功",
editTitle: "编辑证书申请参数模版",
addTitle: "新增证书申请参数模版",
name: "模版名称",
default: "默认",
setDefault: "设为默认",
disabled: "禁用",
createTime: "创建时间",
config: "配置",
};
@@ -0,0 +1,10 @@
export default {
createTime: "操作时间",
type: "操作类型",
action: "操作动作",
result: "结果",
success: "成功",
failed: "失败",
remark: "备注",
ipAddress: "IP地址",
};
@@ -1,58 +1,4 @@
export default {
welcomeBack: "欢迎回来",
pageTitle: "开箱即用的大型中后台管理系统",
pageDesc: "工程化、高性能、跨组件库的前端模版",
loginSuccess: "登录成功",
loginSuccessDesc: "欢迎回来",
loginSubtitle: "请输入您的帐户信息以开始管理您的项目",
selectAccount: "快速选择账号",
username: "账号",
password: "密码",
usernameTip: "请输入用户名",
passwordTip: "请输入密码",
verifyRequiredTip: "请先完成验证",
passwordErrorTip: "密码错误",
rememberMe: "记住账号",
createAnAccount: "创建一个账号",
createAccount: "创建账号",
alreadyHaveAccount: "已经有账号了?",
accountTip: "还没有账号?",
signUp: "注册",
signUpSubtitle: "让您的应用程序管理变得简单而有趣",
confirmPassword: "确认密码",
confirmPasswordTip: "两次输入的密码不一致",
agree: "我同意",
privacyPolicy: "隐私政策",
terms: "条款",
agreeTip: "请同意隐私政策和条款",
goToLogin: "去登录",
passwordStrength: "使用 8 个或更多字符,混合字母、数字和符号",
forgetPassword: "忘记密码?",
forgetPasswordSubtitle: "输入您的电子邮件,我们将向您发送重置密码的连接",
emailTip: "请输入邮箱",
emailValidErrorTip: "你输入的邮箱格式不正确",
sendResetLink: "发送重置链接",
email: "邮箱",
qrcodeSubtitle: "请用手机扫描二维码登录",
qrcodePrompt: "扫码后点击 '确认',即可完成登录",
qrcodeLogin: "扫码登录",
codeSubtitle: "请输入您的手机号码以开始管理您的项目",
code: "验证码",
codeTip: "请输入{0}位验证码",
mobile: "手机号码",
mobileTip: "请输入手机号",
mobileErrortip: "手机号码格式错误",
mobileLogin: "手机号登录",
sendCode: "获取验证码",
sendText: "{0}秒后重新获取",
thirdPartyLogin: "其他登录方式",
loginAgainTitle: "重新登录",
loginAgainSubTitle: "您的登录状态已过期,请重新登录以继续。",
layout: {
center: "居中",
alignLeft: "居左",
alignRight: "居右",
},
loginType: {
password: "密码登录",
sms: "手机号登录",
@@ -112,4 +58,30 @@ export default {
userInfo: "账号信息",
securitySettingTip: "2FA设置",
securitySetting: "2FA设置",
register: {
usernameTab: "用户名注册",
emailTab: "邮箱注册",
mobileTab: "手机号注册",
username: "用户名",
email: "邮箱",
password: "密码",
confirmPassword: "确认密码",
captcha: "验证码",
emailCode: "邮件验证码",
mobileLogin: "前往手机号登录(登录即注册)",
inviteCode: "邀请码",
inviteCodeOptional: "邀请码(选填)",
submit: "注册",
login: "登录",
noMethodEnabled: "没有启用任何一种注册方式",
usernameRequired: "请输入用户名",
emailRequired: "请输入邮箱",
emailInvalid: "请输入正确的邮箱",
passwordRequired: "请输入密码",
confirmPasswordRequired: "请确认密码",
passwordMismatch: "两次输入密码不一致",
smsCodeRequired: "请输入短信验证码",
emailCodeRequired: "请输入邮件验证码",
captchaRequired: "请通过验证码",
},
};
@@ -1,5 +1,6 @@
export default {
domain: {
dnsPersistDescription: "当前仅 Google 证书可以申请 DNS 持久验证。",
domainManager: "域名管理",
domainDescription: "流水线校验方式选择“自动选择”时此处配置才有用,支持自动导入;注意:这里只需要管理主域名即可,子域名不要填写(子域名托管和免费二级子域名除外)",
domain: "域名",
@@ -1,20 +1,18 @@
export default {
clientManager: "客户端管理",
client: {
title: "客户端管理",
description: "查看已接入的 Certd 客户端在线状态与管理的站点数量;客户端每 10 分钟上报一次心跳,超过 30 分钟未上报则标记为离线",
plusRequired: "此功能需要专业版",
machineName: "机器名",
clientId: "客户端ID",
version: "版本",
os: "系统",
status: "在线状态",
online: "在线",
offline: "离线",
siteCount: "站点数",
httpsSiteCount: "HTTPS站点",
syncedSiteCount: "已同步",
failedSiteCount: "异常",
lastHeartbeatAt: "上次心跳",
},
title: "客户端管理",
description: "查看已接入的 Certd 客户端在线状态与管理的站点数量;客户端每 10 分钟上报一次心跳,超过 30 分钟未上报则标记为离线",
plusRequired: "此功能需要专业版",
machineName: "机器名",
clientId: "客户端ID",
version: "版本",
os: "系统",
status: "在线状态",
online: "在线",
offline: "离线",
siteCount: "站点数",
httpsSiteCount: "HTTPS站点",
syncedSiteCount: "已同步",
failedSiteCount: "异常",
lastHeartbeatAt: "上次心跳",
};
@@ -1,4 +1,6 @@
export default {
required: "必填项",
no: "否",
usera: "用户",
disabledSuccess: "关闭成功",
app: {
@@ -25,6 +27,14 @@ export default {
add: "生成新的Key",
edit: "编辑",
deleteSuccess: "删除成功",
fastCrud: {
view: "查看",
copy: "复制",
edit: "编辑",
remove: "删除",
addSuccess: "添加成功",
saveSuccess: "保存成功",
},
saveSuccess: "保存成功",
cancel: "取消",
yes: "是",
@@ -1,51 +1,60 @@
export default {
dashboard: {
greeting: "您好,{name},欢迎使用 【{site}】",
latestVersion: "最新版本: {version}",
validUntil: "账户有效期:",
tutorialTooltip: "点击查看详细教程",
tutorialText: "仅需3步,全自动申请部署证书",
alertMessage: "证书和授权为敏感信息,不要使用来历不明的在线Certd服务和镜像,以免泄露;请务必私有化部署使用,认准官方版本发布渠道:",
helpDoc: "帮助文档",
pipelineCount: "证书流水线数量",
enabledCount: "已启用",
disabledCount: "已禁用",
noPipeline: "您还没有证书流水线",
certCount: "证书数量",
certExpiringCount: "即将过期",
certExpiredCount: "已过期",
certNoExpireCount: "未过期",
noCert: "还没有证书",
manageCert: "查看证书",
siteMonitorCount: "监控站点数量",
siteAbnormalCount: "异常",
siteNormalCount: "正常",
manageSiteMonitor: "管理监控站点",
domainCount: "域名数量",
domainExpiringCount: "即将到期",
domainExpiredCount: "已过期",
domainNotExpiredCount: "未到期",
manageDomain: "管理域名",
greeting: "您好,{name},欢迎使用 【{site}】",
latestVersion: "最新版本: {version}",
validUntil: "账户有效期:",
tutorialTooltip: "点击查看详细教程",
tutorialText: "仅需3步,全自动申请部署证书",
alertMessage: "证书和授权为敏感信息,不要使用来历不明的在线Certd服务和镜像,以免泄露;请务必私有化部署使用,认准官方版本发布渠道:",
helpDoc: "帮助文档",
pipelineCount: "证书流水线数量",
enabledCount: "已启用",
disabledCount: "已禁用",
noPipeline: "您还没有证书流水线",
certCount: "证书数量",
certExpiringCount: "即将过期",
certExpiredCount: "已过期",
certNoExpireCount: "未过期",
noCert: "还没有证书",
manageCert: "查看证书",
siteMonitorCount: "监控站点数量",
siteAbnormalCount: "异常",
siteNormalCount: "正常",
manageSiteMonitor: "管理监控站点",
domainCount: "域名数量",
domainExpiringCount: "即将到期",
domainExpiredCount: "已过期",
domainNotExpiredCount: "未到期",
manageDomain: "管理域名",
createNow: "立即创建",
managePipeline: "管理流水线",
pipelineStatus: "流水线状态",
recentRun: "最近运行统计",
runCount: "运行次数",
expiringCerts: "最快到期证书",
totalGeneratedCertCount: "累计生成证书数量",
singleDomainCertShortCount: "单域名",
multiDomainCertShortCount: "多域名",
wildcardCertShortCount: "泛域名",
singleDomainCertCount: "累计单域名证书数量",
multiDomainCertCount: "累计多域名证书数量",
wildcardCertCount: "累计泛域名证书数量",
savedAmount: "已为您累计节省",
savedAmountRule: "按腾讯云证书平台一年期单价的 1/4 进行估算。实际节省金额仅供参考。(腾讯云单域名证书 532 元,多域名证书 912 元,泛域名证书 2147 元)",
totalPipelineRuns: "累计流水线运行次数",
supportedTasks: "已支持的部署任务总览",
changeLog: "更新日志",
stableRelease: "稳定版",
latestRelease: "预览版",
},
createNow: "立即创建",
managePipeline: "管理流水线",
pipelineStatus: "流水线状态",
recentRun: "最近运行统计",
runCount: "运行次数",
expiringCerts: "最快到期证书",
totalGeneratedCertCount: "累计生成证书数量",
singleDomainCertShortCount: "单域名",
multiDomainCertShortCount: "多域名",
wildcardCertShortCount: "泛域名",
singleDomainCertCount: "累计单域名证书数量",
multiDomainCertCount: "累计多域名证书数量",
wildcardCertCount: "累计泛域名证书数量",
savedAmount: "已为您累计节省",
savedAmountRule: "按腾讯云证书平台一年期单价的 1/4 进行估算。实际节省金额仅供参考。(腾讯云单域名证书 532 元,多域名证书 912 元,泛域名证书 2147 元)",
totalPipelineRuns: "累计流水线运行次数",
supportedTasks: "已支持的部署任务总览",
supportedTasksHelper: "列表仅做展示,请创建流水线来使用它们",
changeLog: "更新日志",
stableRelease: "稳定版",
latestRelease: "预览版",
consoleTitle: "控制台",
userTotal: "用户总数",
manageUsers: "管理用户",
userGrowth: "用户增长趋势",
newUsers: "新增用户",
allPipelineTotal: "全站流水线总数",
managePipelines: "管理流水线",
pipelineGrowth: "流水线增长趋势",
newPipelines: "新增流水线",
recentRunTitle: "最近运行统计",
};
@@ -0,0 +1,24 @@
export default {
pending: "待设置",
created: "已创建",
validating: "校验中",
valid: "有效",
retry: "请重试",
deleteTxtTip: "请到供应商删除TXT记录",
accountUriMissing: "ACME账号授权缺少accountUri,请重新生成账号",
verifySuccess: "校验成功",
verifyFailed: "未找到匹配的TXT记录,请稍后重试",
submitted: "已提交校验",
selectProviderAndAccess: "请选择DNS服务商和授权",
txtCreated: "TXT记录已创建",
settingTitle: "设置DNS TXT记录",
manualAdd: "手动添加",
autoAdd: "选择授权添加",
manualTip: "请到DNS解析控制台添加以下TXT记录,添加后点击确定会立即校验。",
autoTip: "请选择DNS服务商和授权,系统会创建TXT记录,后续校验由后台完成。",
mainDomain: "主域名",
txtHost: "TXT主机名",
txtValue: "TXT值",
provider: "DNS服务商",
access: "DNS授权",
};
@@ -1,4 +1,7 @@
import monitorSite from "./monitor-site";
export default {
...monitorSite,
certificateRepo: {
title: "证书仓库",
sub: "从流水线生成的证书",
@@ -1,4 +1,9 @@
export default {
home: "首页",
login: "登录",
register: "注册",
forgotPassword: "找回密码",
oauthCallback: "第三方登录回调",
framework: {
title: "框架",
home: "首页",
@@ -13,10 +18,13 @@ export default {
accessManager: "授权管理",
dnsPersistRecord: "DNS持久验证记录",
certApplyTemplate: "证书申请参数模版",
certApplyTemplateHelper: "预设证书申请参数,创建证书流水线时自动帮你填写参数。(不包含域名和校验方式)",
subDomain: "子域名托管设置",
pipelineGroup: "流水线分组管理",
pipelineGroupHelper: "管理流水线分组",
openKey: "开放接口密钥",
notification: "通知设置",
notificationHelper: "管理通知配置",
siteMonitorSetting: "站点监控设置",
auditLog: "操作日志",
userSecurity: "认证安全设置",
@@ -49,7 +57,9 @@ export default {
userManager: "用户管理",
userDataManager: "用户数据管理",
pipelineManager: "用户流水线管理",
pipelineManagerHelper: "管理所有用户的流水线",
siteMonitorManager: "用户证书监控管理",
siteMonitorManagerHelper: "管理所有用户的证书监控",
suiteManager: "套餐管理",
suiteSetting: "套餐设置",
orderManager: "订单管理",
@@ -72,6 +82,7 @@ export default {
currentProject: "当前项目",
projectMemberManager: "项目成员管理",
auditLog: "审计日志",
auditLogHelper: "查看所有用户的操作记录",
domainMonitorSetting: "域名监控设置",
jobHistory: "监控执行记录",
},
@@ -0,0 +1,13 @@
export default {
title: "网络测试",
helper: "测试您的服务器容器网络连接是否正常",
customDomain: "自定义域名测试",
serverInfo: "服务端信息",
refresh: "刷新",
loading: "加载中...",
fetchFailed: "获取服务器信息失败",
noInfo: "暂无信息",
localIp: "本地IP",
publicIp: "外网IP",
dnsServer: "DNS服务器",
};
@@ -6,6 +6,10 @@ export default {
keyRemark: "密钥用途",
keyRemarkHelper: "说明该密钥的用途,便于区分和查找",
keyRemarkMaxChars: "最大512个字符",
returnCertPassword: "返回证书密码",
returnCertPasswordHelper: "开启后,开放接口获取证书时会在响应中返回证书密码,请妥善保管该密钥。",
yes: "是",
no: "否",
gen: {
text: "接口测试",
title: "x-certd-token",
@@ -65,6 +65,146 @@ export default {
legoAcme: "Lego-ACME:基于Lego实现,支持海量DNS提供商,熟悉LEGO的用户可以使用",
aliyunOrder: "Aliyun-Order:从阿里云证书订单中获取证书更新",
},
editor: {
editTask: "编辑任务",
editStep: "编辑步骤",
installedPlugins: "已安装插件",
pluginMarket: "插件市场",
searchPluginMarket: "搜索插件市场",
searchLocalPlugins: "搜索本地插件",
loadingPluginMarket: "正在加载插件市场...",
noPluginFound: "没有找到插件",
triggerManually: "手动触发",
triggerSource: "触发源",
scheduledTrigger: "触发源(定时)",
webhookTrigger: "触发源(Webhook)",
certExpireTime: "证书过期时间:",
certExpired: "证书已过期",
viewCertificate: "查看证书",
downloadCertificate: "下载证书",
nextExecutionTime: "下次执行时间:",
noTriggerSource: "未设置触发源,不会自动执行",
validityPeriod: "有效期:",
save: "保存",
cancel: "取消",
addStage: "新阶段",
addTask: "添加任务",
addAfterTask: "添加后置任务",
addNotification: "添加通知",
notificationNotSet: "通知未设置",
history: "运行历史",
historyHint: "点任务可查看日志",
taskName: "任务名称",
taskSteps: "任务步骤",
addStep: "添加步骤",
copy: "复制",
paste: "粘贴",
confirm: "确定",
required: "此项必填",
taskNeedsStep: "至少需要一个步骤,或者你可以点击标题右边删除按钮删除此任务",
step: "步骤",
endStage: "结束",
confirmTitle: "确认",
confirmManualRun: "确定要手动触发运行吗?",
taskLog: "任务日志",
noLogs: "暂无日志(该节点本次运行未触发或没有日志记录)",
aiAnalyze: "AI分析",
rerun: "重新运行",
downloadLogs: "下载日志",
close: "关闭",
batchEditSteps: "批量编辑步骤",
selectAllSteps: "全选步骤",
batchEnableSteps: "批量启用步骤",
batchDisableSteps: "批量禁用步骤",
batchDeleteSteps: "批量删除步骤",
exitBatchEdit: "退出批量编辑",
stepsSerialHelper: "任务步骤会串行执行,如果前面步骤失败,后面的步骤不会运行",
current: "当前",
view: "查看",
confirmCancel: "确认取消",
confirmCancelTask: "确认取消该任务吗?",
taskCanceled: "任务取消成功",
selectAllTasks: "全选任务",
batchEnableTasks: "批量启用任务",
batchDisableTasks: "批量禁用任务",
batchDeleteTasks: "批量删除任务",
exitBatchEditTasks: "退出批量编辑",
editStageTitle: "编辑阶段标题",
batchEditTasks: "批量编辑任务",
dragSort: "拖动排序",
forceRerun: "强制重新执行此步骤",
resizeStage: "拖动调整阶段宽度",
afterLabel: "后置",
notificationLabel: "通知",
unsavedLeave: "流水线还未保存,确定要离开吗?",
newPipeline: "新管道流程",
newTask: "新任务",
newStage: "新阶段",
stageSuffix: "阶段",
saveBeforeRunTitle: "需要保存才能运行管道",
saveBeforeRunContent: "是否先保存",
runUnsupported: "暂不支持运行",
addStageAndTask: "请先添加阶段和任务",
prerequisiteMissing: "{step}的前置输出步骤{param}不存在或已被禁用",
selectPlugin: "选择插件",
searchPlugin: "搜索插件",
noPluginFound: "没有找到插件",
searchResults: "搜索结果",
plusPluginRequired: "此插件需要开通Certd专业版才能使用",
immediateRun: "立即运行",
immediateRunHelper: "保存后是否立即触发运行流水线",
operationSuccess: "操作成功",
regenerate: "重新生成",
webhookHelper: "支持POST和GET请求(同一个流水线的Webhook地址是唯一的)",
regenerateWebhookTitle: "确认重新生成Webhook URL吗?",
regenerateWebhookContent: "重新生成后,旧的Webhook地址将失效",
confirmDeleteTask: "确定要删除此任务吗?",
confirmDeleteStep: "确定要删除此步骤吗?",
confirmDeleteSelectedTasks: "确定要删除选中的{count}个任务吗?",
confirmDeleteSelectedSteps: "确定要删除选中的{count}个步骤吗?",
stepCopied: "步骤配置复制成功,您可以到其他任务编辑页面进行粘贴",
allStepsCopied: "本任务的所有步骤复制成功,您可以到其他任务编辑页面进行粘贴",
copyFirst: "请先复制",
pasted: "粘贴成功",
enterName: "请输入名称",
pluginTypeFirst: "请先选择类型",
runStrategy: "运行策略",
runStrategyNormal: "正常运行(仅证书申请任务需要选它,除非你需要这个任务不跳过,每次都运行)",
runStrategySkip: "成功后跳过(其他任务请选择它)",
runStrategyDefault: "一般保持默认即可",
runStrategyNormalHelp: "正常运行:每次都运行,证书任务需要每次都运行",
runStrategySkipHelp: "成功后跳过:该任务成功一次之后跳过,不重复执行(证书变化之后才会再次运行)",
triggerWebhook: "Webhook触发",
triggerSchedule: "定时触发",
choose: "选择",
noLogsShort: "没有日志",
statusSuccess: "成功",
statusError: "错误",
statusSkip: "跳过",
statusStart: "运行中",
statusCanceled: "已取消",
statusNone: "未运行",
statusDisabled: "禁用",
statusNoDeployCount: "次数不足",
pluginGroups: {
all: "全部",
cert: "证书申请",
host: "主机",
cdn: "CDN",
panel: "面板",
aliyun: "阿里云",
huawei: "华为云",
tencent: "腾讯云",
volcengine: "火山引擎",
jdcloud: "京东云",
ucloud: "UCloud",
baidu: "百度云",
qiniu: "七牛云",
aws: "亚马逊云",
other: "其他",
admin: "管理",
},
},
pipelineForm: {
createTitle: "创建证书流水线",
moreParams: "更多参数",
@@ -1,4 +1,50 @@
export default {
title: "套餐",
mySuite: "我的套餐",
suiteBuy: "套餐购买",
myTrade: "我的订单",
inviteCommission: "激励计划",
inviteSubtitle: "邀请好友,获取丰厚佣金奖励",
promotionAgreement: "推广协议",
withdraw: "提现",
withdrawAvailable: "可提现 {amount}",
inviteCode: "邀请码",
orderTime: "时间",
inviteTime: "邀请时间",
inviteeUsername: "被邀请用户名",
inviteLink: "邀请链接",
myLevel: "我的等级",
unset: "未设置",
commissionRate: "返佣比例",
commissionAfterPayment: "好友付费后按此比例计算佣金",
proportion: "比例",
inviteSuccess: "邀请成功",
incomeRecords: "收益记录",
enableFirst: "请先开通激励计划",
enable: "开通激励计划",
disabled: "激励计划未开启",
totalIncome: "累计收益",
monthIncome: "本月收益",
promotionAmount: "累计推广金额",
inviteeCount: "已推广人数",
people: "人",
agreePromotion: "我已阅读并同意推广协议",
close: "关闭",
postpone: "暂不开通",
agreeAndEnable: "同意并开通",
agreeRequired: "请先勾选同意推广协议",
enabledSuccess: "激励计划已开通",
purchaseSuccess: "套餐购买成功",
agreementPlaceholder: "请输入用户开通激励计划前需要确认的推广协议内容",
activationExchange: "激活码兑换",
activationCode: "激活码",
enterActivationCode: "请输入激活码",
enterCdkCode: "请输入 CDK 激活码",
activateSuccess: "激活成功",
exchangeFailed: "兑换失败",
noSuite: "暂无套餐可购买",
suiteHelperStack: "说明:可以购买多个套餐和加量包,套餐和加量包内的数量可以叠加",
suiteHelperLatest: "说明:① 同一时间只有最新购买的一个套餐生效;② 可以购买多个加量包,加量包立即生效;③ 套餐和加量包内的数量可以叠加",
order: {
confirmTitle: "订单确认",
package: "套餐",
@@ -1,4 +1,14 @@
export default {
aiDevTitle: "AI 开发插件",
certPluginConfig: "证书插件配置",
saveSuccess: "保存成功",
commonGoogleAcme: "公共Google ACME账号",
commonZeroSslAcme: "公共ZeroSSL ACME账号",
commonLiteSslAcme: "公共litessl ACME账号",
otherConfig: "其他配置",
certApplyDefaults: "证书申请插件默认值设置",
customCertApplyParams: "自定义证书申请插件参数",
save: "保存",
titlea: "中文名称",
pluginFile: "插件文件",
selectPluginFile: "选择插件文件",
@@ -1,113 +1,129 @@
export default {
sys: {
setting: {
baseSetting: "基本设置",
registerSetting: "注册设置",
safeSetting: "安全设置",
paymentSetting: "支付设置",
captchaSetting: "验证码设置",
pipelineSetting: "流水线设置",
oauthSetting: "第三方登录",
networkSetting: "网络设置",
adminModeSetting: "管理模式",
adminModeHelper: "企业管理模式: 企业内部使用,通过项目来隔离权限,流水线、授权数据属于项目。\nsaas模式:供外部用户注册使用,各个用户之间数据隔离,流水线、授权数据属于用户。",
modeIntroTitle: "管理模式介绍",
saasModeDescription: "SaaS模式:每个用户管理自己的流水线和授权资源,每个用户独立使用。",
enterpriseModeDescription: "企业模式:通过项目合作管理流水线证书和授权资源,所有用户视为企业内部员工。",
switchModeNow: "立即前往切换模式",
suiteSetting: "套餐设置",
orderManager: "订单管理",
headerMenuSetting: "顶部菜单配置",
sitePersonalization: "站点个性化设置",
siteName: "站点名称",
slogan: "副标题/口号",
loginLogo: "登录页Logo",
entityName: "你的主体名称",
shownAtBottom: "将会显示在底部",
entityUrl: "你的主体URL",
modeSaasHelper: "SaaS模式:每个用户管理自己的流水线和授权资源,独立使用。",
modeEnterpriseHelper: "企业模式:通过项目合作管理流水线证书和授权资源,所有用户视为企业内部员工。",
modeMore: "更多管理模式介绍",
modeFixedWarning: "建议在开始使用时固定一个合适的模式,之后就不要随意切换了。",
modeMigrate: "设置为企业模式之后,之前创建的个人数据不会显示,您可以选择将个人数据迁移到项目",
modeCommWarning: "商业版不建议设置为企业模式,除非你确定要转成企业内部使用",
baseSetting: "基本设置",
registerSetting: "注册设置",
safeSetting: "安全设置",
paymentSetting: "支付设置",
captchaSetting: "验证码设置",
pipelineSetting: "流水线设置",
oauthSetting: "第三方登录",
networkSetting: "网络设置",
adminModeSetting: "管理模式",
adminModeHelper: "企业管理模式: 企业内部使用,通过项目来隔离权限,流水线、授权数据属于项目。\nsaas模式:供外部用户注册使用,各个用户之间数据隔离,流水线、授权数据属于用户。",
adminMode: "管理模式",
enterpriseMode: "企业模式",
saasMode: "SaaS模式",
adminMode: "管理模式",
enterpriseMode: "企业模式",
saasMode: "SaaS模式",
showRunStrategy: "显示运行策略选择",
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
homePageEnabled: "启用首页",
showRunStrategy: "显示运行策略选择",
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
homePageEnabled: "启用首页",
captchaEnabled: "启用登录验证码",
captchaHelper: "登录时是否启用验证码",
captchaType: "验证码配置",
captchaTest: "测试验证码",
captchaTestHelper: "保存后再点击测试,请务必测试通过了,再开启登录验证码",
captchaEnabled: "启用登录验证码",
captchaHelper: "登录时是否启用验证码",
captchaType: "验证码配置",
captchaTest: "测试验证码",
captchaTestHelper: "保存后再点击测试,请务必测试通过了,再开启登录验证码",
pipelineValidTimeEnabled: "启用流水线有效期",
pipelineValidTimeEnabledHelper: "是否启用流水线有效期",
certDomainAddToMonitorEnabled: "证书域名添加到证书监控",
certDomainAddToMonitorEnabledHelper: "创建证书流水线时是否可以选择将域名添加到证书监控",
pipelineValidTimeEnabled: "启用流水线有效期",
pipelineValidTimeEnabledHelper: "是否启用流水线有效期",
certDomainAddToMonitorEnabled: "证书域名添加到证书监控",
certDomainAddToMonitorEnabledHelper: "创建证书流水线时是否可以选择将域名添加到证书监控",
defaultCertRenewDays: "默认到期前更新天数",
defaultCertRenewDaysHelper: "创建证书流水线时,默认的证书到期前更新天数",
defaultCertRenewDaysRecommend: "默认值15",
defaultCertRenewDays: "默认到期前更新天数",
defaultCertRenewDaysHelper: "创建证书流水线时,默认的证书到期前更新天数",
defaultCertRenewDaysRecommend: "默认值15",
pipelineMaxRunningCount: "同时最大运行流水线数量",
pipelineMaxRunningCountHelper: "同一个用户同时运行的最大流水线数量,避免同时触发太多导致ACME账户被限制",
pipelineMaxRunningCountRecommend: "推荐5-15,默认10",
acmeWalkFromAuthoritative: "从权威NS检查TXT记录",
acmeWalkFromAuthoritativeHelper: "申请证书时,是否从权威NS服务器检查TXT记录,如果影响申请证书,可以关闭",
pipelineMaxRunningCount: "同时最大运行流水线数量",
pipelineMaxRunningCountHelper: "同一个用户同时运行的最大流水线数量,避免同时触发太多导致ACME账户被限制",
pipelineMaxRunningCountRecommend: "推荐5-15,默认10",
acmeWalkFromAuthoritative: "从权威NS检查TXT记录",
acmeWalkFromAuthoritativeHelper: "申请证书时,是否从权威NS服务器检查TXT记录,如果影响申请证书,可以关闭",
customAcmeManage: "自定义ACME管理",
customAcmeManageHelper: "配置证书颁发机构(内置 + 自定义ACME)。内置颁发机构不允许修改和删除;自定义ACME适用于内网CA、企业CA等符合RFC 8555标准的ACME服务,配置后可在证书申请任务和ACME账号授权的颁发机构中选用",
customAcmeName: "颁发机构名称",
customAcmeSslProvider: "颁发机构标识",
customAcmeSslProviderHelper: "唯一标识,如 myca;创建流水线和ACME账号时用它来区分颁发机构,不能重复,创建后不能修改",
customAcmeReverseProxy: "反向代理地址",
customAcmeReverseProxyHelper: "例如:对于letsencrypt 你在海外服务器配置反代:\nproxy_pass https://acme-v02.api.letsencrypt.org/; \n然后在这里填写你的反代服务器的域名,不要带http://",
customAcmeAdd: "添加自定义ACME",
customAcmeEdit: "编辑自定义ACME",
customAcmeNeedEab: "需要EAB",
customAcmeBuiltIn: "内置",
customAcmeTag: "自定义",
customAcmeDeleteConfirmTitle: "删除自定义ACME",
customAcmeDeleteConfirmContent: "删除「{title}」可能影响使用它的流水线申请证书,确认是否删除?",
customAcmeSaveCheck: "自定义ACME的名称、标识、Directory URL均为必填",
customAcmeSslProviderUnique: "自定义ACME的标识(sslProvider)不能重复",
customAcmeManage: "自定义ACME管理",
customAcmeManageHelper: "配置证书颁发机构(内置 + 自定义ACME)。内置颁发机构不允许修改和删除;自定义ACME适用于内网CA、企业CA等符合RFC 8555标准的ACME服务,配置后可在证书申请任务和ACME账号授权的颁发机构中选用",
customAcmeName: "颁发机构名称",
customAcmeSslProvider: "颁发机构标识",
customAcmeSslProviderHelper: "唯一标识,如 myca;创建流水线和ACME账号时用它来区分颁发机构,不能重复,创建后不能修改",
customAcmeReverseProxy: "反向代理地址",
customAcmeReverseProxyHelper: "例如:对于letsencrypt 你在海外服务器配置反代:\nproxy_pass https://acme-v02.api.letsencrypt.org/; \n然后在这里填写你的反代服务器的域名,不要带http://",
customAcmeAdd: "添加自定义ACME",
customAcmeEdit: "编辑自定义ACME",
customAcmeNeedEab: "需要EAB",
customAcmeBuiltIn: "内置",
customAcmeTag: "自定义",
customAcmeDeleteConfirmTitle: "删除自定义ACME",
customAcmeDeleteConfirmContent: "删除「{title}」可能影响使用它的流水线申请证书,确认是否删除?",
customAcmeSaveCheck: "自定义ACME的名称、标识、Directory URL均为必填",
customAcmeSslProviderUnique: "自定义ACME的标识(sslProvider)不能重复",
fixedCertExpireDays: "固定证书有效期天数",
fixedCertExpireDaysHelper: "固定证书有效期天数,有助于列表进度条整齐显示",
fixedCertExpireDaysRecommend: "推荐90",
fixedCertExpireDays: "固定证书有效期天数",
fixedCertExpireDaysHelper: "固定证书有效期天数,有助于列表进度条整齐显示",
fixedCertExpireDaysRecommend: "推荐90",
enableOauth: "启用第三方登录",
oauthEnabledHelper: "是否启用第三方登录",
oauthProviders: "第三方登录提供商",
oauthType: "第三方登录类型",
oauthConfig: "第三方登录配置",
oauthProviderSelectorPlaceholder: "未配置",
oauthCallback: "回调地址",
oauthCallbackHelper: "复制回调地址,配置到对应提供商的回调地址中",
oauthCallbackCopy: "复制回调地址",
oauthAutoRegister: "自动注册用户",
oauthAutoRegisterHelper: "当第三方账户未绑定本站账号时,是否自动注册用户,默认由用户选择",
oauthAutoRegisterCheckedText: "自动注册",
oauthAutoRegisterUnCheckedText: "用户选择",
oauthAutoRedirect: "自动跳转第三方登录",
oauthAutoRedirectHelper: "是否自动跳转第三方登录(使用第一个已启用的第三方登录类型)\n注意:请务必先测试第三方登录功能正常后再开启。",
oauthOnly: "仅使用第三方登录",
oauthOnlyHelper: "是否仅使用第三方登录,关闭密码登录\n注意:请务必先测试第三方登录功能正常后再开启\n无法登录急救方法:服务重启后前10分钟内可通过 http://你的certd地址/#/login?oauthOnly=false, 使用密码登录处理配置问题",
enablePasskey: "启用Passkey登录",
passkeyHostnameNotSame: "当前域名与主绑定域名不同",
passkeyEnabledHelper: "1、站点必须启用https \n2、passkey的rpId以主绑定域名为准,当前主域名:{0} \n3、站点域名不能变,否则会导致已注册的passkey失效。",
email: {
templates: "邮件模板",
templateType: "模板类型",
templateProvider: "模板配置",
enableOauth: "启用第三方登录",
oauthEnabledHelper: "是否启用第三方登录",
oauthProviders: "第三方登录提供商",
oauthType: "第三方登录类型",
oauthConfig: "第三方登录配置",
oauthProviderSelectorPlaceholder: "未配置",
oauthCallback: "回调地址",
oauthCallbackHelper: "复制回调地址,配置到对应提供商的回调地址中",
oauthCallbackCopy: "复制回调地址",
oauthAutoRegister: "自动注册用户",
oauthAutoRegisterHelper: "当第三方账户未绑定本站账号时,是否自动注册用户,默认由用户选择",
oauthAutoRegisterCheckedText: "自动注册",
oauthAutoRegisterUnCheckedText: "用户选择",
oauthAutoRedirect: "自动跳转第三方登录",
oauthAutoRedirectHelper: "是否自动跳转第三方登录(使用第一个已启用的第三方登录类型)\n注意:请务必先测试第三方登录功能正常后再开启。",
oauthOnly: "仅使用第三方登录",
oauthOnlyHelper: "是否仅使用第三方登录,关闭密码登录\n注意:请务必先测试第三方登录功能正常后再开启\n无法登录急救方法:服务重启后前10分钟内可通过 http://你的certd地址/#/login?oauthOnly=false, 使用密码登录处理配置问题",
enablePasskey: "启用Passkey登录",
passkeyHostnameNotSame: "当前域名与主绑定域名不同",
passkeyEnabledHelper: "1、站点必须启用https \n2、passkey的rpId以主绑定域名为准,当前主域名:{0} \n3、站点域名不能变,否则会导致已注册的passkey失效。",
email: {
templates: "邮件模板",
templateType: "模板类型",
templateProvider: "模板配置",
templateSetting: "邮件模板设置",
serverSetting: "邮件服务器设置",
sendTest: "发送测试",
templateSetting: "邮件模板设置",
serverSetting: "邮件服务器设置",
sendTest: "发送测试",
templateProviderSelectorPlaceholder: "未配置",
},
notice: "系统公告",
noticeHelper: "系统公告,将在首页显示",
noticePlaceholder: "系统公告",
customFooter: "自定义页脚",
customFooterHelper: "自定义站点页脚,将在页面底部显示,支持HTML格式",
customFooterPlaceholder: "自定义页脚内容",
environmentVars: "环境变量",
environmentVarsHelper: "配置运行时环境变量,每行一个,格式:KEY=VALUE",
commonHeaders: "公共请求头",
commonHeadersHelper: "服务端发起 HTTP 请求时自动附加的公共请求头,每行一个,格式:KEY=VALUE;请求中已设置同名 Header 时不会覆盖\n注意: 不要将token等敏感内容放在此处,仅限个人和公司内部使用,商业版不要设置",
bindUrl: "绑定URL",
bindUrlHelper: "绑定URL,在各类通知中显示你的站点URL",
},
templateProviderSelectorPlaceholder: "未配置",
},
notice: "系统公告",
noticeHelper: "系统公告,将在首页显示",
noticePlaceholder: "系统公告",
customFooter: "自定义页脚",
customFooterHelper: "自定义站点页脚,将在页面底部显示,支持HTML格式",
customFooterPlaceholder: "自定义页脚内容",
environmentVars: "环境变量",
environmentVarsHelper: "配置运行时环境变量,每行一个,格式:KEY=VALUE",
commonHeaders: "公共请求头",
commonHeadersHelper: "服务端发起 HTTP 请求时自动附加的公共请求头,每行一个,格式:KEY=VALUE;请求中已设置同名 Header 时不会覆盖\n注意: 不要将token等敏感内容放在此处,仅限个人和公司内部使用,商业版不要设置",
bindUrl: "绑定URL",
bindUrlHelper: "绑定URL,在各类通知中显示你的站点URL",
icpRegistrationNumber: "ICP备案号",
icpPlaceholder: "粤ICP备xxxxxxx号",
publicSecurityRegistrationNumber: "网安备案号",
@@ -1,4 +1,7 @@
import tutorialGuide from "./tutorial-guide";
export default {
...tutorialGuide,
steps: {
createPipeline: "创建证书流水线",
addTask: "添加部署任务",
@@ -0,0 +1,44 @@
export default {
title: "我的钱包",
withdraw: "申请提现",
withdrawRecords: "提现记录",
balanceLogs: "余额明细",
availableAmount: "可用余额",
frozenAmount: "冻结余额",
totalIncomeAmount: "累计收入",
totalWithdrawAmount: "累计提现",
withdrawSetting: "提现设置",
channel: "提现渠道",
alipay: "支付宝",
bank: "银行卡",
selectChannel: "请选择提现渠道",
realName: "真实姓名",
enterRealName: "请输入真实姓名",
account: "收款账号",
enterAccount: "请输入收款账号",
qrCode: "收款二维码",
uploadQrCode: "上传支付宝收款二维码图片",
bankName: "开户银行",
selectBank: "请选择开户银行",
enterBankName: "请输入开户银行",
saveSuccess: "保存成功",
beforeWithdrawTip: "提现前需要先设置提现账号。",
amount: "提现金额",
yuan: "元",
enterAmount: "请输入提现金额",
submitSuccess: "提现申请已提交",
applyTime: "申请时间",
type: "类型",
income: "收益入账",
consume: "余额抵扣",
withdrawFreeze: "提现冻结",
withdrawSuccess: "提现成功",
withdrawReject: "提现退回",
changeAmount: "变动金额",
balanceAfter: "变动后余额",
remark: "备注",
pending: "待审核",
approved: "已通过",
rejected: "已拒绝",
auditRemark: "审核备注",
};
@@ -1,21 +1,7 @@
import certd from "./certd";
import authentication from "./authentication";
import vip from "./vip";
import tutorial from "./tutorial";
import preferences from "./preferences";
import ui from "./ui";
import guide from "./guide";
import common from "./common";
import monitor from "./monitor";
import vben from "./vben";
//注意: @符号是保留字符,需要用{'@'}替换
export default {
certd,
authentication,
vip,
ui,
tutorial,
preferences,
guide,
common,
monitor,
...vben,
};
@@ -0,0 +1,56 @@
export default {
welcomeBack: "欢迎回来",
pageTitle: "开箱即用的大型中后台管理系统",
pageDesc: "工程化、高性能、跨组件库的前端模版",
loginSuccess: "登录成功",
loginSuccessDesc: "欢迎回来",
loginSubtitle: "请输入您的帐户信息以开始管理您的项目",
selectAccount: "快速选择账号",
username: "账号",
password: "密码",
usernameTip: "请输入用户名",
passwordTip: "请输入密码",
verifyRequiredTip: "请先完成验证",
passwordErrorTip: "密码错误",
rememberMe: "记住账号",
createAnAccount: "创建一个账号",
createAccount: "创建账号",
alreadyHaveAccount: "已经有账号了?",
accountTip: "还没有账号?",
signUp: "注册",
signUpSubtitle: "让您的应用程序管理变得简单而有趣",
confirmPassword: "确认密码",
confirmPasswordTip: "两次输入的密码不一致",
agree: "我同意",
privacyPolicy: "隐私政策",
terms: "条款",
agreeTip: "请同意隐私政策和条款",
goToLogin: "去登录",
passwordStrength: "使用 8 个或更多字符,混合字母、数字和符号",
forgetPassword: "忘记密码?",
forgetPasswordSubtitle: "输入您的电子邮件,我们将向您发送重置密码的连接",
emailTip: "请输入邮箱",
emailValidErrorTip: "你输入的邮箱格式不正确",
sendResetLink: "发送重置链接",
email: "邮箱",
qrcodeSubtitle: "请用手机扫描二维码登录",
qrcodePrompt: "扫码后点击 '确认',即可完成登录",
qrcodeLogin: "扫码登录",
codeSubtitle: "请输入您的手机号码以开始管理您的项目",
code: "验证码",
codeTip: "请输入{0}位验证码",
mobile: "手机号码",
mobileTip: "请输入手机号",
mobileErrortip: "手机号码格式错误",
mobileLogin: "手机号登录",
sendCode: "获取验证码",
sendText: "{0}秒后重新获取",
thirdPartyLogin: "其他登录方式",
loginAgainTitle: "重新登录",
loginAgainSubTitle: "您的登录状态已过期,请重新登录以继续。",
layout: {
center: "居中",
alignLeft: "居左",
alignRight: "居右",
},
};
@@ -0,0 +1,10 @@
import preferences from "./preferences";
import ui from "./ui";
import common from "./common";
import authentication from "./authentication";
export default {
preferences,
ui,
common,
authentication,
};
@@ -13,6 +13,7 @@ import { App } from "vue";
import { notification } from "ant-design-vue";
import { usePreferences } from "/@/vben/preferences";
import { LocalStorage } from "/@/utils/util.storage";
import i18n from "/@/locales/i18n";
import { FsEditorCode } from "@fast-crud/editor-code";
import "@fast-crud/editor-code/dist/style.css";
@@ -53,6 +54,7 @@ const tableSaver = new ColumnSizeSaver("table");
function install(app: App, options: any = {}) {
app.use(UiAntdv);
const t = i18n.global.t;
//设置日志级别
setLogger({ level: "info" });
@@ -177,10 +179,10 @@ function install(app: App, options: any = {}) {
rowHandle: {
fixed: "right",
buttons: {
view: { type: "link", text: null, icon: "ion:eye-outline", tooltip: { title: "查看" } },
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline", tooltip: { title: "复制" } },
edit: { type: "link", text: null, icon: "ion:create-outline", tooltip: { title: "编辑" } },
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline", tooltip: { title: "删除" } },
view: { type: "link", text: null, icon: "ion:eye-outline", tooltip: { title: t("certd.common.fastCrud.view") } },
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline", tooltip: { title: t("certd.common.fastCrud.copy") } },
edit: { type: "link", text: null, icon: "ion:create-outline", tooltip: { title: t("certd.common.fastCrud.edit") } },
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline", tooltip: { title: t("certd.common.fastCrud.remove") } },
},
dropdown: {
more: {
@@ -236,9 +238,9 @@ function install(app: App, options: any = {}) {
},
async afterSubmit({ mode }) {
if (mode === "add") {
notification.success({ message: "添加成功" });
notification.success({ message: t("certd.common.fastCrud.addSuccess") });
} else if (mode === "edit") {
notification.success({ message: "保存成功" });
notification.success({ message: t("certd.common.fastCrud.saveSuccess") });
}
},
wrapperCol: {
@@ -12,7 +12,7 @@ const dynamicRouteFiles = import.meta.glob("./modules/**/*.ts*", {
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
export const frameworkResource = [
{
title: "certd.framework.title",
title: "certd.navigation.framework.title",
name: "root",
path: "/",
redirect: "/index",
@@ -23,7 +23,7 @@ export const frameworkResource = [
},
children: [
{
title: "certd.framework.home",
title: "certd.navigation.framework.home",
name: "index",
path: "/index",
component: "/framework/home/index.vue",
@@ -3,7 +3,7 @@ import { useSettingStore } from "/@/store/settings";
export const certdResources = [
{
title: "certd.title",
title: "certd.navigation.title",
name: "CertdRoot",
path: "/cert",
redirect: "/cert/pipeline",
@@ -14,7 +14,7 @@ export const certdResources = [
},
children: [
{
title: "certd.sysResources.myProjectManager",
title: "certd.navigation.sysResources.myProjectManager",
name: "MyProjectManager",
path: "/cert/project",
component: "/certd/project/index.vue",
@@ -30,7 +30,7 @@ export const certdResources = [
},
},
{
title: "certd.sysResources.projectJoin",
title: "certd.navigation.sysResources.projectJoin",
name: "ProjectJoin",
path: "/cert/project/join",
component: "/certd/project/join.vue",
@@ -42,7 +42,7 @@ export const certdResources = [
},
},
{
title: "certd.pipeline",
title: "certd.navigation.pipeline",
name: "PipelineManager",
path: "/cert/pipeline",
component: "/certd/pipeline/index.vue",
@@ -53,7 +53,7 @@ export const certdResources = [
},
},
{
title: "certd.pipelineEdit",
title: "certd.navigation.pipelineEdit",
name: "PipelineEdit",
path: "/cert/pipeline/detail",
component: "/certd/pipeline/detail.vue",
@@ -63,7 +63,7 @@ export const certdResources = [
},
},
{
title: "certd.history",
title: "certd.navigation.history",
name: "PipelineHistory",
path: "/cert/history",
component: "/certd/history/index.vue",
@@ -74,7 +74,7 @@ export const certdResources = [
},
},
{
title: "certd.template.title",
title: "certd.pipeline.template.title",
name: "PipelineTemplate",
path: "/cert/pipeline/template",
component: "/certd/pipeline/template/index.vue",
@@ -86,7 +86,7 @@ export const certdResources = [
},
},
{
title: "certd.template.edit",
title: "certd.pipeline.template.edit",
name: "PipelineTemplateEdit",
path: "/cert/pipeline/template/edit",
component: "/certd/pipeline/template/edit.vue",
@@ -96,7 +96,7 @@ export const certdResources = [
},
},
{
title: "certd.template.importCreate",
title: "certd.pipeline.template.importCreate",
name: "PipelineTemplateImport",
path: "/cert/pipeline/template/import",
component: "/certd/pipeline/template/import/index.vue",
@@ -106,7 +106,7 @@ export const certdResources = [
},
},
{
title: "certd.certStore",
title: "certd.navigation.certStore",
name: "CertStore",
path: "/cert/monitor/cert",
component: "/certd/monitor/cert/index.vue",
@@ -118,7 +118,7 @@ export const certdResources = [
},
},
{
title: "certd.siteMonitor",
title: "certd.navigation.siteMonitor",
name: "SiteCertMonitor",
path: "/cert/monitor/site",
component: "/certd/monitor/site/index.vue",
@@ -129,7 +129,7 @@ export const certdResources = [
},
},
{
title: "certd.clientManager",
title: "certd.client.clientManager",
name: "ClientManager",
path: "/cert/client",
component: "/certd/client/index.vue",
@@ -140,7 +140,7 @@ export const certdResources = [
},
},
{
title: "certd.sysResources.currentProject",
title: "certd.navigation.sysResources.currentProject",
name: "ProjectMemberManager",
path: "/cert/project/detail",
component: "/certd/project/detail/index.vue",
@@ -155,7 +155,7 @@ export const certdResources = [
},
},
{
title: "certd.settings",
title: "certd.navigation.settings",
name: "MineSetting",
path: "/cert/setting",
redirect: "/cert/access",
@@ -166,7 +166,7 @@ export const certdResources = [
},
children: [
{
title: "certd.accessManager",
title: "certd.navigation.accessManager",
name: "AccessManager",
path: "/cert/access",
component: "/certd/access/index.vue",
@@ -177,7 +177,7 @@ export const certdResources = [
},
},
{
title: "certd.domain.domainManager",
title: "certd.certdomain.domain.domainManager",
name: "DomainManager",
path: "/cert/cert/domain",
component: "/certd/cert/domain/index.vue",
@@ -188,7 +188,7 @@ export const certdResources = [
},
},
{
title: "certd.cnameRecord",
title: "certd.cname.cnameRecord",
name: "CnameRecord",
path: "/cert/cname/record",
component: "/certd/cname/record/index.vue",
@@ -199,7 +199,7 @@ export const certdResources = [
},
},
{
title: "certd.dnsPersistRecord",
title: "certd.navigation.dnsPersistRecord",
name: "DnsPersistRecord",
path: "/cert/cert/dns-persist",
component: "/certd/cert/dns-persist/index.vue",
@@ -210,7 +210,7 @@ export const certdResources = [
},
},
{
title: "certd.certApplyTemplate",
title: "certd.navigation.certApplyTemplate",
name: "CertApplyTemplate",
path: "/cert/cert/apply-template",
component: "/certd/cert/apply-template/index.vue",
@@ -221,7 +221,7 @@ export const certdResources = [
},
},
{
title: "certd.subDomain",
title: "certd.navigation.subDomain",
name: "SubDomain",
path: "/cert/pipeline/subDomain",
component: "/certd/pipeline/sub-domain/index.vue",
@@ -232,7 +232,7 @@ export const certdResources = [
},
},
{
title: "certd.pipelineGroup",
title: "certd.navigation.pipelineGroup",
name: "PipelineGroupManager",
path: "/cert/pipeline/group",
component: "/certd/pipeline/group/index.vue",
@@ -243,7 +243,7 @@ export const certdResources = [
},
},
{
title: "certd.openKey",
title: "certd.navigation.openKey",
name: "OpenKey",
path: "/cert/open/openkey",
component: "/certd/open/openkey/index.vue",
@@ -254,7 +254,7 @@ export const certdResources = [
},
},
{
title: "certd.notification",
title: "certd.navigation.notification",
name: "NotificationManager",
path: "/cert/notification",
component: "/certd/notification/index.vue",
@@ -265,7 +265,7 @@ export const certdResources = [
},
},
{
title: "certd.siteMonitorSetting",
title: "certd.navigation.siteMonitorSetting",
name: "SiteMonitorSetting",
path: "/cert/monitor/setting",
component: "/certd/monitor/site/setting/index.vue",
@@ -276,7 +276,7 @@ export const certdResources = [
},
},
{
title: "certd.sysResources.domainMonitorSetting",
title: "certd.navigation.sysResources.domainMonitorSetting",
name: "DomainMonitorSetting",
path: "/cert/cert/domain/setting",
component: "/certd/cert/domain/setting/index.vue",
@@ -287,7 +287,7 @@ export const certdResources = [
},
},
{
title: "certd.sysResources.jobHistory",
title: "certd.navigation.sysResources.jobHistory",
name: "JobHistory",
path: "/cert/monitor/history",
component: "/certd/monitor/history/index.vue",
@@ -299,7 +299,7 @@ export const certdResources = [
},
},
{
title: "certd.auditLog",
title: "certd.navigation.auditLog",
name: "AuditLog",
path: "/cert/audit",
component: "/certd/audit/index.vue",
@@ -315,7 +315,7 @@ export const certdResources = [
},
},
{
title: "certd.userSecurity",
title: "certd.navigation.userSecurity",
name: "UserSecurity",
path: "/cert/mine/security",
component: "/certd/mine/security/index.vue",
@@ -326,7 +326,7 @@ export const certdResources = [
},
},
{
title: "certd.userGrant",
title: "certd.navigation.userGrant",
name: "UserGrantSetting",
path: "/cert/mine/grant",
component: "/certd/mine/grant/index.vue",
@@ -341,7 +341,7 @@ export const certdResources = [
},
},
{
title: "certd.userProfile",
title: "certd.navigation.userProfile",
name: "UserProfile",
path: "/cert/mine/user-profile",
component: "/certd/mine/user-profile.vue",
@@ -354,7 +354,7 @@ export const certdResources = [
],
},
{
title: "certd.suite",
title: "certd.common.suite",
name: "SuiteProduct",
path: "/cert/suite",
redirect: "/cert/suite/mine",
@@ -368,7 +368,7 @@ export const certdResources = [
},
children: [
{
title: "certd.mySuite",
title: "certd.navigation.mySuite",
name: "MySuite",
path: "/cert/suite/mine",
component: "/certd/suite/mine/index.vue",
@@ -383,7 +383,7 @@ export const certdResources = [
},
},
{
title: "certd.suiteBuy",
title: "certd.navigation.suiteBuy",
name: "SuiteProductBuy",
path: "/cert/suite/buy",
component: "/certd/suite/buy.vue",
@@ -397,7 +397,7 @@ export const certdResources = [
},
},
{
title: "certd.myTrade",
title: "certd.navigation.myTrade",
name: "MyTrade",
path: "/cert/trade",
component: "/certd/trade/index.vue",
@@ -412,7 +412,7 @@ export const certdResources = [
},
},
{
title: "certd.inviteCommission",
title: "certd.navigation.inviteCommission",
name: "InviteCommission",
path: "/cert/invite",
component: "/certd/invite/index.vue",
@@ -427,7 +427,7 @@ export const certdResources = [
},
},
{
title: "certd.myWallet",
title: "certd.navigation.myWallet",
name: "MyWallet",
path: "/cert/wallet",
component: "/certd/wallet/index.vue",
@@ -442,7 +442,7 @@ export const certdResources = [
},
},
{
title: "certd.paymentReturn",
title: "certd.navigation.paymentReturn",
name: "PaymentReturn",
path: "/cert/payment/return/:type",
component: "/certd/payment/return.vue",
@@ -8,7 +8,7 @@ function isInviteLevelEnabled() {
export const sysResources = [
{
title: "certd.sysResources.sysRoot",
title: "certd.navigation.sysResources.sysRoot",
name: "SysRoot",
path: "/sys",
redirect: "/sys/settings",
@@ -20,7 +20,7 @@ export const sysResources = [
},
children: [
{
title: "certd.sysResources.sysConsole",
title: "certd.navigation.sysResources.sysConsole",
name: "SysConsole",
path: "/sys/console",
component: "/sys/console/index.vue",
@@ -36,7 +36,7 @@ export const sysResources = [
},
{
title: "certd.sysResources.sysSettings",
title: "certd.navigation.sysResources.sysSettings",
name: "SysSettings",
path: "/sys/settings",
component: "/sys/settings/index.vue",
@@ -47,7 +47,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.projectManager",
title: "certd.navigation.sysResources.projectManager",
name: "ProjectManager",
path: "/sys/enterprise/project",
component: "/sys/enterprise/project/index.vue",
@@ -60,7 +60,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.projectDetail",
title: "certd.navigation.sysResources.projectDetail",
name: "ProjectDetail",
path: "/sys/enterprise/project/detail",
component: "/sys/enterprise/project/detail/index.vue",
@@ -73,7 +73,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.cnameSetting",
title: "certd.navigation.sysResources.cnameSetting",
name: "CnameSetting",
path: "/sys/cname/provider",
component: "/sys/cname/provider/index.vue",
@@ -85,7 +85,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.emailSetting",
title: "certd.navigation.sysResources.emailSetting",
name: "EmailSetting",
path: "/sys/settings/email",
component: "/sys/settings/email/index.vue",
@@ -96,7 +96,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.siteSetting",
title: "certd.navigation.sysResources.siteSetting",
name: "SiteSetting",
path: "/sys/site",
component: "/sys/site/index.vue",
@@ -111,7 +111,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.headerMenus",
title: "certd.navigation.sysResources.headerMenus",
name: "SettingsHeaderMenus",
path: "/sys/settings/header-menus",
component: "/sys/settings/header-menus/index.vue",
@@ -127,7 +127,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.sysAccess",
title: "certd.navigation.sysResources.sysAccess",
name: "SysAccessManager",
path: "/sys/access",
component: "/sys/access/index.vue",
@@ -143,7 +143,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.sysPlugin",
title: "certd.navigation.sysResources.sysPlugin",
name: "SysPlugin",
path: "/sys/plugin",
component: "/sys/plugin/index.vue",
@@ -155,7 +155,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.sysPluginConfig",
title: "certd.navigation.sysResources.sysPluginConfig",
name: "SysPluginConfig",
path: "/sys/plugin/config",
component: "/sys/plugin/config-common.vue",
@@ -170,7 +170,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.accountBind",
title: "certd.navigation.sysResources.accountBind",
name: "AccountBind",
path: "/sys/account",
component: "/sys/account/index.vue",
@@ -182,7 +182,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.permissionManager",
title: "certd.navigation.sysResources.permissionManager",
name: "PermissionManager",
path: "/sys/authority/permission",
component: "/sys/authority/permission/index.vue",
@@ -194,7 +194,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.roleManager",
title: "certd.navigation.sysResources.roleManager",
name: "RoleManager",
path: "/sys/authority/role",
component: "/sys/authority/role/index.vue",
@@ -206,7 +206,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.userManager",
title: "certd.navigation.sysResources.userManager",
name: "UserManager",
path: "/sys/authority/user",
component: "/sys/authority/user/index.vue",
@@ -218,7 +218,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.userDataManager",
title: "certd.navigation.sysResources.userDataManager",
name: "UserDataManager",
path: "/sys/user-data",
redirect: "/sys/pipeline",
@@ -230,7 +230,7 @@ export const sysResources = [
},
children: [
{
title: "certd.sysResources.pipelineManager",
title: "certd.navigation.sysResources.pipelineManager",
name: "SysPipelineManager",
path: "/sys/pipeline",
component: "/sys/pipeline/index.vue",
@@ -242,7 +242,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.siteMonitorManager",
title: "certd.navigation.sysResources.siteMonitorManager",
name: "SysSiteMonitorManager",
path: "/sys/monitor/site",
component: "/sys/monitor/site/index.vue",
@@ -256,7 +256,7 @@ export const sysResources = [
],
},
{
title: "certd.sysResources.suiteManager",
title: "certd.navigation.sysResources.suiteManager",
name: "SuiteManager",
path: "/sys/suite",
redirect: "/sys/suite/setting",
@@ -272,7 +272,7 @@ export const sysResources = [
},
children: [
{
title: "certd.sysResources.suiteSetting",
title: "certd.navigation.sysResources.suiteSetting",
name: "SuiteSetting",
path: "/sys/suite/setting",
component: "/sys/suite/setting/index.vue",
@@ -287,7 +287,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.orderManager",
title: "certd.navigation.sysResources.orderManager",
name: "OrderManager",
path: "/sys/suite/trade",
component: "/sys/suite/trade/index.vue",
@@ -303,7 +303,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.userSuites",
title: "certd.navigation.sysResources.userSuites",
name: "UserSuites",
path: "/sys/suite/user-suite",
component: "/sys/suite/user-suite/index.vue",
@@ -318,7 +318,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.balanceManager",
title: "certd.navigation.sysResources.balanceManager",
name: "SysWallet",
path: "/sys/suite/wallet",
component: "/sys/suite/wallet/index.vue",
@@ -334,7 +334,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.balanceLog",
title: "certd.navigation.sysResources.balanceLog",
name: "SysWalletLog",
path: "/sys/suite/wallet-log",
component: "/sys/suite/wallet/log/index.vue",
@@ -346,7 +346,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.inviteCommissionSetting",
title: "certd.navigation.sysResources.inviteCommissionSetting",
name: "SysInviteCommissionSetting",
path: "/sys/suite/invite/setting",
component: "/sys/suite/invite/setting.vue",
@@ -362,7 +362,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.inviteLevel",
title: "certd.navigation.sysResources.inviteLevel",
name: "SysInviteLevel",
path: "/sys/suite/invite/level",
component: "/sys/suite/invite/level.vue",
@@ -377,7 +377,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.inviteUserLevel",
title: "certd.navigation.sysResources.inviteUserLevel",
name: "SysInviteUserLevel",
path: "/sys/suite/invite/user-level",
component: "/sys/suite/invite/user-level.vue",
@@ -392,7 +392,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.inviteWithdraw",
title: "certd.navigation.sysResources.inviteWithdraw",
name: "SysInviteWithdraw",
path: "/sys/suite/invite/withdraw",
component: "/sys/suite/invite/withdraw.vue",
@@ -408,7 +408,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.activationCodeManager",
title: "certd.navigation.sysResources.activationCodeManager",
name: "SysProductActivationCode",
path: "/sys/suite/activation-code",
component: "/sys/suite/activation-code/index.vue",
@@ -426,7 +426,7 @@ export const sysResources = [
],
},
{
title: "certd.sysResources.auditLog",
title: "certd.navigation.sysResources.auditLog",
name: "SysAuditLog",
path: "/sys/enterprise/audit",
component: "/sys/enterprise/audit/index.vue",
@@ -442,7 +442,7 @@ export const sysResources = [
},
},
{
title: "certd.sysResources.netTest",
title: "certd.navigation.sysResources.netTest",
name: "NetTest",
path: "/sys/nettest",
component: "/sys/nettest/index.vue",
@@ -4,7 +4,7 @@ const errorPage = [{ path: "/:pathMatch(.*)*", name: "not-found", component: Err
export const outsideResource = [
{
meta: {
title: "首页",
title: "navigation.home",
isMenu: false,
},
name: "landing",
@@ -19,7 +19,7 @@ export const outsideResource = [
children: [
{
meta: {
title: "登录",
title: "navigation.login",
},
name: "login",
path: "/login",
@@ -27,7 +27,7 @@ export const outsideResource = [
},
{
meta: {
title: "注册",
title: "navigation.register",
},
name: "register",
path: "/register",
@@ -35,7 +35,7 @@ export const outsideResource = [
},
{
meta: {
title: "找回密码",
title: "navigation.forgotPassword",
},
name: "forgotPassword",
path: "/forgotPassword",
@@ -43,7 +43,7 @@ export const outsideResource = [
},
{
meta: {
title: "第三方登录回调",
title: "navigation.oauthCallback",
},
name: "oauthCallback",
path: "/oauth/callback/:type",
@@ -1,5 +1,5 @@
import { DynamicType, FormItemProps, useMerge } from "@fast-crud/fast-crud";
import { merge, set } from "lodash-es";
import { cloneDeep, merge, set } from "lodash-es";
import { defineStore } from "pinia";
import * as api from "./api.plugin";
import { i18n } from "/src/locales/i18n";
@@ -8,6 +8,24 @@ interface PluginState {
originGroup?: PluginGroups;
}
export function resolvePluginLocale(plugin: any, locale = i18n.global.locale.value) {
const resolved = cloneDeep(plugin || {});
if (locale === "en-US") {
const english = resolved.i18n?.["en-US"] || resolved.metadata?.i18n?.["en-US"];
if (english) {
const translatedFields = ["title", "desc", "group", "input", "output", "shortcut"];
const translated: Record<string, any> = {};
for (const field of translatedFields) {
if (english[field] !== undefined) {
translated[field] = english[field];
}
}
merge(resolved, translated);
}
}
return resolved;
}
export function fillPluginDefine(plugin: any) {
const columns = plugin.input;
for (const key in columns) {
@@ -96,16 +114,20 @@ export class PluginGroups {
const { merge } = useMerge();
const all: PluginGroup = {
key: "all",
title: this.t("certd.all"),
title: this.t("certd.common.all"),
order: 0,
plugins: [],
icon: "material-symbols:border-all-rounded",
};
for (const key in groups) {
const localizedPlugins = [];
for (const plugin of groups[key].plugins) {
fillPluginDefine(plugin);
const localizedPlugin = resolvePluginLocale(plugin);
fillPluginDefine(localizedPlugin);
localizedPlugins.push(localizedPlugin);
}
all.plugins.push(...groups[key].plugins);
groups[key] = { ...groups[key], plugins: localizedPlugins };
all.plugins.push(...localizedPlugins);
}
this.groups = {
all,

Some files were not shown because too many files have changed in this diff Show More