Feat: i18n code

This commit is contained in:
unitwk 2023-12-26 19:53:51 +08:00
parent 5bf3e7bac9
commit fa2aa095a8
17 changed files with 125 additions and 87 deletions

View File

@ -8,11 +8,11 @@ function readCategoryConfig(configCategory: string, callback: (config: any) => b
try {
const config = JSON.parse(StorageSubsystem.readFile(configPath));
if (callback(config)) {
logger.info(t("已将旧版本配置升级为新版本配置:"), configPath);
logger.info(t("TXT_CODE_6b2a9cab"), configPath);
StorageSubsystem.writeFile(configPath, JSON.stringify(config, null, 4));
}
} catch (error) {
logger.error(t("[配置升级机制] 解析配置文件错误,已自动忽略:"), error);
logger.error(t("TXT_CODE_fb75aba9"), error);
}
}
}

View File

@ -27,7 +27,7 @@ const parsedConfig = jsonToMap(props.config);
<template #body>
<a-typography>
<a-typography-title :level="5">
{{ data ? t("配置文件说明") : t("TXT_CODE_2ce953da") }}
{{ data ? t("TXT_CODE_958fd70c") : t("TXT_CODE_2ce953da") }}
</a-typography-title>
<a-typography-paragraph v-if="data">
{{ data?.desc }}

View File

@ -23,20 +23,14 @@ defineExpose({ validate });
<template>
<a-form ref="formRef" layout="vertical" :model="form">
<a-form-item name="softwarePath" :label="t('需要启动的程序')" required>
<a-input
v-model:value="form.softwarePath"
:placeholder="t('列如server.exeapp.exe或使用绝对路径等')"
/>
<a-form-item name="softwarePath" :label="t('TXT_CODE_c7b1b8d0')" required>
<a-input v-model:value="form.softwarePath" :placeholder="t('TXT_CODE_a2a0e054')" />
</a-form-item>
<a-form-item name="params" :label="t('额外参数')">
<a-input
v-model:value="form.params"
:placeholder="t('选填,根据你的启动程序按需填写,如:-server -XXX -ZZZ 等')"
/>
<a-form-item name="params" :label="t('TXT_CODE_b9442311')">
<a-input v-model:value="form.params" :placeholder="t('TXT_CODE_2a379a13')" />
<div class="mt-6">
<a-typography-text type="secondary">
{{ t("额外参数会自动拼接到软件路径的末尾。") }}
{{ t("TXT_CODE_d705a2bd") }}
</a-typography-text>
</div>
</a-form-item>

View File

@ -28,45 +28,36 @@ defineExpose({ validate });
<template>
<a-form ref="formRef" layout="vertical" :model="form">
<a-form-item name="jarName" :label="t('服务端软件文件名')" required>
<a-input
v-model:value="form.jarName"
:placeholder="t('一般为 .jar 文件,列如 paper.jar 等')"
/>
<a-form-item name="jarName" :label="t('TXT_CODE_58508fb7')" required>
<a-input v-model:value="form.jarName" :placeholder="t('TXT_CODE_84f760fa')" />
</a-form-item>
<a-row :gutter="[24, 24]">
<a-col :span="12">
<a-form-item name="maxMemory" :label="t('最大内存')">
<a-input v-model:value="form.maxMemory" :placeholder="t('选填,-Xmx 参数1024M')" />
<a-form-item name="maxMemory" :label="t('TXT_CODE_dd238854')">
<a-input v-model:value="form.maxMemory" :placeholder="t('TXT_CODE_d7fa3be3')" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item name="minMemory" :label="t('初始内存')">
<a-input v-model:value="form.minMemory" :placeholder="t('选填,-Xms 参数1024M')" />
<a-form-item name="minMemory" :label="t('TXT_CODE_e050b3be')">
<a-input v-model:value="form.minMemory" :placeholder="t('TXT_CODE_57c1b0a3')" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item name="javaPath" :label="t('Java 路径')">
<a-input
v-model:value="form.javaPath"
:placeholder="t('选填,请输入 Java 绝对路径,不填默认取环境变量')"
/>
<a-form-item name="javaPath" :label="t('TXT_CODE_43422ed3')">
<a-input v-model:value="form.javaPath" :placeholder="t('TXT_CODE_7f9b6758')" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item name="additional" :label="t('附加参数')">
<a-input v-model:value="form.additional" :placeholder="t('选填,在 -jar 之前的参数')" />
<a-form-item name="additional" :label="t('TXT_CODE_4efba567')">
<a-input v-model:value="form.additional" :placeholder="t('TXT_CODE_f79563ef')" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item name="suffix" :label="t('后缀参数')">
<a-input
v-model:value="form.suffix"
:placeholder="t('选填Java 程序之后的附加参数,如 -nogui 等,多个参数用空格分隔')"
/>
<a-form-item name="suffix" :label="t('TXT_CODE_85770d4a')">
<a-input v-model:value="form.suffix" :placeholder="t('TXT_CODE_6e3da823')" />
</a-form-item>
</a-col>
</a-row>

View File

@ -34,22 +34,22 @@ const formRef = ref();
const tabFormComponent: Record<string, { component: Component; title: string; form: any }> = {
[TYPE_MINECRAFT_JAVA]: {
component: MinecraftJavaForm,
title: t("Java 版 Minecraft 服务器"),
title: t("TXT_CODE_95583336"),
form: minecraftJava
},
[TYPE_MINECRAFT_BEDROCK]: {
component: AnyAppFormComponent,
title: t("Bedrock 版 Minecraft 服务器"),
title: t("TXT_CODE_28116f29"),
form: anyAppForm
},
[TYPE_STEAM_SERVER_UNIVERSAL]: {
component: AnyAppFormComponent,
title: t("Steam 游戏服务器"),
title: t("TXT_CODE_dd8d27ce"),
form: anyAppForm
},
[TYPE_UNIVERSAL]: {
component: AnyAppFormComponent,
title: t("任何程序"),
title: t("TXT_CODE_10693964"),
form: anyAppForm
}
};
@ -63,7 +63,7 @@ const submit = async () => {
try {
await formRef.value.validate();
} catch (error) {
return reportError(t("请完善表单中的必填项!"));
return reportError(t("TXT_CODE_d6c5a7f8"));
}
const command = buildCmd();
@ -80,7 +80,7 @@ const handleNext = () => {
const actions = [
{
icon: BuildFilled,
title: t("Minecraft 游戏服务器"),
title: t("TXT_CODE_f2deb1d0"),
click: () => {
setGameType(QUICKSTART_ACTION_TYPE.Minecraft);
handleNext();
@ -88,7 +88,7 @@ const actions = [
},
{
icon: SwitcherFilled,
title: t("Steam 游戏服务器"),
title: t("TXT_CODE_dd8d27ce"),
click: () => {
setGameType(QUICKSTART_ACTION_TYPE.SteamGameServer);
handleNext();
@ -96,7 +96,7 @@ const actions = [
},
{
icon: DropboxSquareFilled,
title: t("任何控制台程序"),
title: t("TXT_CODE_4600deb7"),
click: () => {
setGameType(QUICKSTART_ACTION_TYPE.AnyApp);
handleNext();
@ -111,8 +111,8 @@ const actions = [
centered
width="800px"
:mask-closable="false"
:title="t('命令助手')"
:ok-text="t('确定')"
:title="t('TXT_CODE_2728d0d4')"
:ok-text="t('TXT_CODE_d507abff')"
:cancel-text="t('TXT_CODE_a0451c97')"
:ok-button-props="{ disabled: step !== STEP.SELECT_SOFTWARE }"
@ok="submit"
@ -122,7 +122,7 @@ const actions = [
<div v-if="step === STEP.SELECT_TYPE">
<a-row :gutter="[0, 12]">
<a-typography-text>
{{ t("请选择你的服务器程序类别") }}
{{ t("TXT_CODE_18df7f10") }}
</a-typography-text>
<fade-up-animation>
<action-button
@ -147,12 +147,13 @@ const actions = [
</div>
<div v-else-if="gameType === QUICKSTART_ACTION_TYPE.SteamGameServer">
<a-tabs v-model:activeKey="appType">
<a-tab-pane :key="TYPE_STEAM_SERVER_UNIVERSAL" :tab="t('Steam 游戏服务器')"> </a-tab-pane>
<a-tab-pane :key="TYPE_STEAM_SERVER_UNIVERSAL" :tab="t('TXT_CODE_dd8d27ce')">
</a-tab-pane>
</a-tabs>
</div>
<div v-else-if="gameType != null">
<a-tabs v-model:activeKey="appType">
<a-tab-pane :key="TYPE_UNIVERSAL" :tab="t('全部类型')">D</a-tab-pane>
<a-tab-pane :key="TYPE_UNIVERSAL" :tab="t('TXT_CODE_feab659d')">D</a-tab-pane>
</a-tabs>
</div>
<component

View File

@ -46,7 +46,7 @@ const columns = computed<AntColumnsType[]>(() => {
align: "center",
key: "operation",
dataIndex: "operation",
title: t("操作")
title: t("TXT_CODE_fe731dfc")
}
];
}
@ -67,7 +67,7 @@ const columns = computed<AntColumnsType[]>(() => {
align: "center",
key: "operation",
dataIndex: "operation",
title: t("操作")
title: t("TXT_CODE_fe731dfc")
}
];
});
@ -94,7 +94,7 @@ const operation = (type: "add" | "del", index = 0) => {
width="600px"
:mask-closable="false"
:title="props.title"
:ok-text="t('确定')"
:ok-text="t('TXT_CODE_d507abff')"
:cancel-text="t('TXT_CODE_a0451c97')"
@ok="submit"
@cancel="cancel"
@ -102,7 +102,7 @@ const operation = (type: "add" | "del", index = 0) => {
<div class="dialog-overflow-container">
<div class="flex justify-end mb-20">
<a-button :icon="h(PlusCircleOutlined)" @click="operation('add')">
{{ t("新增配置") }}
{{ t("TXT_CODE_dfc17a0c") }}
</a-button>
</div>
<a-form ref="formInstance" :model="dataSource" name="validate_other">
@ -132,7 +132,7 @@ const operation = (type: "add" | "del", index = 0) => {
>
<a-input
v-model:value="record[String(column.dataIndex)]"
:placeholder="t('请输入内容')"
:placeholder="t('TXT_CODE_4ea93630')"
/>
</a-form-item>
</template>

View File

@ -27,22 +27,22 @@ export async function usePortEditDialog(data: PortConfigItem[] = []) {
return (
(await useMountComponent({
data,
title: t("容器端口映射配置"),
title: t("TXT_CODE_c4435af9"),
columns: [
{
align: "center",
dataIndex: "host",
title: t("主机端口")
title: t("TXT_CODE_534db0b2")
},
{
align: "center",
dataIndex: "container",
title: t("容器端口")
title: t("TXT_CODE_b729d2e")
},
{
align: "center",
dataIndex: "protocol",
title: t("协议")
title: t("TXT_CODE_ad1c674c")
}
] as AntColumnsType[]
}).mount<PortConfigItem[]>(KvOptionsDialogVue)) || []
@ -53,17 +53,17 @@ export async function useVolumeEditDialog(data: DockerConfigItem[] = []) {
return (
(await useMountComponent({
data,
title: t("挂载目录到容器"),
title: t("TXT_CODE_820ebc92"),
columns: [
{
align: "center",
dataIndex: "host",
title: t("主机目录")
title: t("TXT_CODE_681aaeb9")
},
{
align: "center",
dataIndex: "container",
title: t("容器目录")
title: t("TXT_CODE_30258325")
}
] as AntColumnsType[]
}).mount<DockerConfigItem[]>(KvOptionsDialogVue)) || []

View File

@ -2,12 +2,12 @@ import { t } from "@/lang/i18n";
import { message } from "ant-design-vue";
export function emptyValueValidator(value: string | number) {
if (String(value).trim() === "") throw new Error(t("字段不可为空"));
if (String(value).trim() === "") throw new Error(t("TXT_CODE_cb08d342"));
return Promise.resolve();
}
export function isNumberValidator(value: any) {
if (!value || isNaN(Number(value))) throw new Error("字段必须是数字");
if (!value || isNaN(Number(value))) throw new Error(t("字段必须是数字"));
return Promise.resolve();
}
@ -27,10 +27,10 @@ export function getValidatorErrorMsg(error: any, def: string = "") {
export function reportValidatorError(error: any) {
console.error("Function reportValidatorError():", error);
message.error(getValidatorErrorMsg(error, t("操作失败")));
message.error(getValidatorErrorMsg(error, t("TXT_CODE_6a365d01")));
}
export function reportError(error: any = {}) {
console.error("Function reportError():", error);
message.error(getValidatorErrorMsg(error, t("操作失败")));
message.error(getValidatorErrorMsg(error, t("TXT_CODE_6a365d01")));
}

View File

@ -335,7 +335,7 @@ onMounted(async () => {
<a-form-item v-if="!isAddMode" label="APIKEY">
<a-typography-paragraph v-if="!formData.apiKey">
{{ t("此用户没有开启 APIKEY 功能。") }}
{{ t("TXT_CODE_6c274bdc") }}
</a-typography-paragraph>
<a-input v-else v-model:value="formData.apiKey" :readonly="true" />
</a-form-item>
@ -452,7 +452,7 @@ onMounted(async () => {
{{ t("TXT_CODE_4d934e3a") }}
</a-menu-item>
<a-popconfirm
:title="t('你确定要删除这个用户吗?')"
:title="t('TXT_CODE_e99ab99a')"
@confirm="handleDeleteUser(record)"
>
<a-menu-item key="3">

View File

@ -116,15 +116,15 @@ onMounted(async () => {
<BetweenMenus>
<template #left>
<a-button class="mr-8" @click="toConfigOverview">
{{ t("返回") }}
{{ t("TXT_CODE_c14b2ea3") }}
</a-button>
</template>
<template #right>
<a-button type="primary" :loading="updateConfigFileLoading" class="mr-8" @click="save">
{{ t("保存") }}
{{ t("TXT_CODE_abfe9512") }}
</a-button>
<a-button :loading="getConfigFileLoading" class="mr-8" @click="refresh">
{{ t("刷新") }}
{{ t("TXT_CODE_b76d94e0") }}
</a-button>
<a-button type="dashed" @click="toEditRawFile">
{{ t("TXT_CODE_1f61e5a3") }}

View File

@ -296,7 +296,7 @@ const innerTerminalType = viewType === "inner";
<li @click="clearTerminal()">
<a-tooltip placement="top">
<template #title>
<span>{{ t("清空终端输出内容") }}</span>
<span>{{ t("TXT_CODE_b1e2e1b4") }}</span>
</template>
<delete-outlined />
</a-tooltip>

View File

@ -147,7 +147,7 @@ const submit = async () => {
return message.success(t("TXT_CODE_d3de39b4"));
} catch (error: any) {
console.error(error);
return reportError(error.message ?? t("保存失败,请检查配置项"));
return reportError(error.message ?? t("TXT_CODE_9911ac11"));
}
};
@ -400,12 +400,12 @@ defineExpose({
<a-typography-title :level="5">{{ t("TXT_CODE_cf88c936") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("通过映射让容器进程使用主机的真实端口") }}
{{ t("TXT_CODE_1a37f514") }}
</a-typography-text>
</a-typography-paragraph>
<a-input-group compact>
<a-button type="default" @click="() => handleEditDockerConfig('port')">
{{ t("编辑") }}
{{ t("TXT_CODE_ad207008") }}
</a-button>
</a-input-group>
</a-form-item>
@ -415,12 +415,12 @@ defineExpose({
<a-typography-title :level="5">{{ t("TXT_CODE_3e68ca00") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("挂载额外路径到容器中") }}
{{ t("TXT_CODE_828ea87f") }}
</a-typography-text>
</a-typography-paragraph>
<a-input-group compact>
<a-button type="default" @click="() => handleEditDockerConfig('volume')">
{{ t("编辑") }}
{{ t("TXT_CODE_ad207008") }}
</a-button>
</a-input-group>
</a-form-item>

View File

@ -63,7 +63,7 @@ const dialog = reactive({
try {
dialog.loading = true;
await deleteNode(dialog.uuid);
message.success(t("已删除"));
message.success(t("TXT_CODE_a00e84d7"));
} catch (error: any) {
message.success(error.message ?? error);
}
@ -77,10 +77,10 @@ const dialog = reactive({
} else {
await addNode(dialog.data);
}
message.success(t("已保存"));
message.success(t("TXT_CODE_e74d658c"));
dialog.close();
} catch (error: any) {
reportError(error.message ?? t("请完善表单内容"));
reportError(error.message ?? t("TXT_CODE_5245bd11"));
}
},
hidden: () => {

View File

@ -57,9 +57,9 @@ const tryConnectNode = async (uuid: string, showMsg = true) => {
uuid: uuid
}
});
if (showMsg) message.success(t("操作成功"));
if (showMsg) message.success(t("TXT_CODE_7f0c746d"));
} catch (error) {
reportError(t("操作失败"));
reportError(t("TXT_CODE_6a365d01"));
}
};
@ -150,7 +150,7 @@ const nodeOperations = computed(() =>
condition: () => item.value!.available
},
{
title: t("重新连接"),
title: t("TXT_CODE_f8b28901"),
icon: ReloadOutlined,
click: async (node: ComputedNodeInfo) => {
await tryConnectNode(node.uuid);

View File

@ -131,7 +131,7 @@ const columns = computed(() => {
minWidth: 200,
condition: () => !screen.isPhone.value,
customRender: (row: { text: string | number }) => {
if (Number(row.text) === 0) return t("无限期");
if (Number(row.text) === 0) return t("TXT_CODE_8dfd8b17");
if (!isNaN(Number(row.text))) return dayjs(Number(row.text)).format("YYYY-MM-DD HH:mm:ss");
return row.text;
}
@ -165,7 +165,7 @@ const columns = computed(() => {
<BetweenMenus>
<template #left>
<a-typography-title class="mb-0" :level="4">
{{ t("用户所有实例") }}
{{ t("TXT_CODE_76d20724") }}
</a-typography-title>
</template>
<template #right>
@ -173,7 +173,7 @@ const columns = computed(() => {
{{ t("TXT_CODE_b76d94e0") }}
</a-button>
<a-button type="primary" @click="assignApp">
{{ t("分配实例") }}
{{ t("TXT_CODE_9393b484") }}
</a-button>
</template>
</BetweenMenus>

View File

@ -1672,5 +1672,57 @@
"TXT_CODE_b0aa2db9": "已关闭!",
"TXT_CODE_eb579d63": "用户资源管理",
"TXT_CODE_1f925226": "登录页面",
"TXT_CODE_463375d2": "关于本页面"
"TXT_CODE_463375d2": "关于本页面",
"TXT_CODE_6b2a9cab": "已将旧版本配置升级为新版本配置:",
"TXT_CODE_fb75aba9": "[配置升级机制] 解析配置文件错误,已自动忽略:",
"TXT_CODE_c7b1b8d0": "需要启动的程序",
"TXT_CODE_a2a0e054": "列如server.exeapp.exe或使用绝对路径等",
"TXT_CODE_b9442311": "额外参数",
"TXT_CODE_2a379a13": "选填,根据你的启动程序按需填写,如:-server -XXX -ZZZ 等",
"TXT_CODE_d705a2bd": "额外参数会自动拼接到软件路径的末尾。",
"TXT_CODE_95583336": "Java 版 Minecraft 服务器",
"TXT_CODE_28116f29": "Bedrock 版 Minecraft 服务器",
"TXT_CODE_10693964": "任何程序",
"TXT_CODE_d6c5a7f8": "请完善表单中的必填项!",
"TXT_CODE_f2deb1d0": "Minecraft 游戏服务器",
"TXT_CODE_4600deb7": "任何控制台程序",
"TXT_CODE_18df7f10": "请选择你的服务器程序类别",
"TXT_CODE_feab659d": "全部类型",
"TXT_CODE_58508fb7": "服务端软件文件名",
"TXT_CODE_84f760fa": "一般为 .jar 文件,列如 paper.jar 等",
"TXT_CODE_dd238854": "最大内存",
"TXT_CODE_d7fa3be3": "选填,-Xmx 参数1024M",
"TXT_CODE_e050b3be": "初始内存",
"TXT_CODE_57c1b0a3": "选填,-Xms 参数1024M",
"TXT_CODE_43422ed3": "Java 路径",
"TXT_CODE_7f9b6758": "选填,请输入 Java 绝对路径,不填默认取环境变量",
"TXT_CODE_4efba567": "附加参数",
"TXT_CODE_f79563ef": "选填,在 -jar 之前的参数",
"TXT_CODE_85770d4a": "后缀参数",
"TXT_CODE_6e3da823": "选填Java 程序之后的附加参数,如 -nogui 等,多个参数用空格分隔",
"TXT_CODE_c4435af9": "容器端口映射配置",
"TXT_CODE_534db0b2": "主机端口",
"TXT_CODE_b729d2e": "容器端口",
"TXT_CODE_ad1c674c": "协议",
"TXT_CODE_820ebc92": "挂载目录到容器",
"TXT_CODE_681aaeb9": "主机目录",
"TXT_CODE_30258325": "容器目录",
"TXT_CODE_dfc17a0c": "新增配置",
"TXT_CODE_958fd70c": "配置文件说明",
"TXT_CODE_cb08d342": "字段不可为空",
"TXT_CODE_6a365d01": "操作失败",
"TXT_CODE_9911ac11": "保存失败,请检查配置项",
"TXT_CODE_1a37f514": "通过映射让容器进程使用主机的真实端口",
"TXT_CODE_828ea87f": "挂载额外路径到容器中",
"TXT_CODE_b1e2e1b4": "清空终端输出内容",
"TXT_CODE_a00e84d7": "已删除",
"TXT_CODE_e74d658c": "已保存",
"TXT_CODE_5245bd11": "请完善表单内容",
"TXT_CODE_7f0c746d": "操作成功",
"TXT_CODE_f8b28901": "重新连接",
"TXT_CODE_8dfd8b17": "无限期",
"TXT_CODE_76d20724": "用户所有实例",
"TXT_CODE_9393b484": "分配实例",
"TXT_CODE_6c274bdc": "此用户没有开启 APIKEY 功能。",
"TXT_CODE_e99ab99a": "你确定要删除这个用户吗?"
}

View File

@ -8,11 +8,11 @@ function readCategoryConfig(configCategory: string, callback: (config: any) => b
try {
const config = JSON.parse(StorageSubsystem.readFile(configPath));
if (callback(config)) {
logger.info(t("已将旧版本配置升级为新版本配置:"), configPath);
logger.info(t("TXT_CODE_6b2a9cab"), configPath);
StorageSubsystem.writeFile(configPath, JSON.stringify(config, null, 4));
}
} catch (error) {
logger.error(t("[配置升级机制] 解析配置文件错误,已自动忽略:"), error);
logger.error(t("TXT_CODE_fb75aba9"), error);
}
}
}