diff --git a/CHANGELOG-BETA.md b/CHANGELOG-BETA.md index a847c39f2..ea9b02857 100644 --- a/CHANGELOG-BETA.md +++ b/CHANGELOG-BETA.md @@ -10,6 +10,7 @@ ### ⚠️ 注意 +- 前端国际化翻译程度:90% - 后端已翻译语言可以度:80%(部分异步执行日志等目前未支持) 后端日志国际化需要新增或者修改 `jpom.system.lang` 配置项 diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java index 3d35950c0..e5b5a297c 100644 --- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java +++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java @@ -29,6 +29,7 @@ import cn.keepbx.jpom.plugins.IPlugin; import lombok.Lombok; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.ProjectConfig; import org.dromara.jpom.configuration.ProjectLogConfig; import org.dromara.jpom.exception.IllegalArgument2Exception; @@ -158,7 +159,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander { } Map env = projectInfoService.getEnv(nodeProjectInfoModel.getWorkspaceId()); // 执行命令 - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { File file = projectInfoService.resolveLibFile(nodeProjectInfoModel); if (SystemUtil.getOsInfo().isWindows()) { @@ -288,7 +289,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander { // webhook 通知 Opt.ofBlankAble(nodeProjectInfoModel.token()) .ifPresent(s -> - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { String result = this.webHooks(s, nodeProjectInfoModel, type, other); Optional.ofNullable(result).ifPresent(s1 -> log.debug(I18nMessageUtil.get("i18n.trigger_result.364e"), nodeProjectInfoModel.getId(), type, s1)); @@ -307,7 +308,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander { Boolean fileChangeReload = run.getFileChangeReload(); if (fileChangeReload != null && fileChangeReload) { // 需要执行重载事件 - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { CommandOpResult reload = this.reload(nodeProjectInfoModel, originalModel); log.info(I18nMessageUtil.get("i18n.trigger_project_reload_event.a7dc"), reload); diff --git a/modules/agent/src/main/java/org/dromara/jpom/service/ProjectFileBackupService.java b/modules/agent/src/main/java/org/dromara/jpom/service/ProjectFileBackupService.java index 7a6ca421b..b4e9a641c 100644 --- a/modules/agent/src/main/java/org/dromara/jpom/service/ProjectFileBackupService.java +++ b/modules/agent/src/main/java/org/dromara/jpom/service/ProjectFileBackupService.java @@ -23,6 +23,7 @@ import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.JpomApplication; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.AgentConfig; import org.dromara.jpom.configuration.ProjectConfig; import org.dromara.jpom.model.data.DslYmlDto; @@ -187,7 +188,7 @@ public class ProjectFileBackupService { File projectPath = projectInfoService.resolveLibFile(infoModel); DslYmlDto dslYmlDto = infoModel.dslConfig(); // 考虑到大文件对比,比较耗时。需要异步对比文件 - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { //String useBackupPath = resolveBackupPath(dslYmlDto); File backupItemPath = this.pathProjectBackup(infoModel, backupId); diff --git a/modules/agent/src/main/java/org/dromara/jpom/socket/AgentWebSocketConsoleHandle.java b/modules/agent/src/main/java/org/dromara/jpom/socket/AgentWebSocketConsoleHandle.java index 1f6a6f591..b8e50cf7c 100644 --- a/modules/agent/src/main/java/org/dromara/jpom/socket/AgentWebSocketConsoleHandle.java +++ b/modules/agent/src/main/java/org/dromara/jpom/socket/AgentWebSocketConsoleHandle.java @@ -12,7 +12,6 @@ package org.dromara.jpom.socket; import cn.hutool.core.convert.Convert; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.io.FileUtil; -import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; import cn.keepbx.jpom.model.JsonMessage; import com.alibaba.fastjson2.JSONObject; @@ -21,6 +20,7 @@ import org.dromara.jpom.common.Const; import org.dromara.jpom.common.commander.CommandOpResult; import org.dromara.jpom.common.commander.ProjectCommander; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.AgentConfig; import org.dromara.jpom.configuration.ProjectLogConfig; import org.dromara.jpom.model.RunMode; @@ -246,7 +246,7 @@ public class AgentWebSocketConsoleHandle extends BaseAgentWebSocketHandle { if (!FileUtil.isFile(file)) { return new JsonMessage<>(404, I18nMessageUtil.get("i18n.file_not_found.d952")); } - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { boolean first = Convert.toBool(reqJson.getString("first"), false); int head = reqJson.getIntValue("head"); diff --git a/modules/common/src/main/java/org/dromara/jpom/common/JpomApplicationEvent.java b/modules/common/src/main/java/org/dromara/jpom/common/JpomApplicationEvent.java index 3e07f691e..a71d99208 100644 --- a/modules/common/src/main/java/org/dromara/jpom/common/JpomApplicationEvent.java +++ b/modules/common/src/main/java/org/dromara/jpom/common/JpomApplicationEvent.java @@ -225,7 +225,7 @@ public class JpomApplicationEvent implements ApplicationListener { int startCron = iCron.startCron(); if (startCron > 0) { - log.debug("{} scheduling has been started:{}", name, startCron); + log.debug("{} 定时任务已经自动启动:{}", name, startCron); } }); Map asyncLoadMap = SpringUtil.getApplicationContext().getBeansOfType(IAsyncLoad.class); diff --git a/modules/common/src/main/java/org/dromara/jpom/common/LocaleConfig.java b/modules/common/src/main/java/org/dromara/jpom/common/LocaleConfig.java index 2553b9162..55fb9f4c9 100644 --- a/modules/common/src/main/java/org/dromara/jpom/common/LocaleConfig.java +++ b/modules/common/src/main/java/org/dromara/jpom/common/LocaleConfig.java @@ -22,7 +22,6 @@ public class LocaleConfig { @Bean public ResourceBundleMessageSource messageSource() { - //Locale.setDefault(Locale.CHINA); ResourceBundleMessageSource source = new ResourceBundleMessageSource(); //设置国际化文件存储路径 resources目录下 source.setBasenames("i18n/messages"); diff --git a/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nMessageUtil.java b/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nMessageUtil.java index 3180d021c..5d9587383 100644 --- a/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nMessageUtil.java +++ b/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nMessageUtil.java @@ -50,8 +50,17 @@ public class I18nMessageUtil { LANGUAGE_OBTAIN.add(LANGUAGE::get); // http 请求获取 LANGUAGE_OBTAIN.add(I18nMessageUtil::getLanguageByRequest); - // 系统配置获取 + // Jpom 配置获取 LANGUAGE_OBTAIN.add(() -> SystemUtil.get("JPOM_LANG")); + // 系统语言 + LANGUAGE_OBTAIN.add(() -> { + Locale locale = Locale.getDefault(); + String country = locale.getCountry(); + if (StrUtil.equals("zh", country)) { + return "zh-CN"; + } + return "en-US"; + }); } /** @@ -84,18 +93,6 @@ public class I18nMessageUtil { return null; } - /** - * 获取语言 - * - * @param request 请求 - * @return 合法的语言 - */ - public static String parseLanguage(HttpServletRequest request) { - String language = ServletUtil.getHeader(request, Header.ACCEPT_LANGUAGE.getValue(), CharsetUtil.CHARSET_UTF_8); - language = StrUtil.emptyToDefault(language, "zh-cn"); - return normalLanguage(language); - } - /** * 语言格式化 * @@ -115,6 +112,22 @@ public class I18nMessageUtil { } } + /** + * 尝试获取语言 + * + * @return 语言 + */ + public static String tryGetLanguage() { + String language = null; + for (Supplier supplier : LANGUAGE_OBTAIN) { + language = supplier.get(); + if (language != null) { + break; + } + } + return language; + } + /** * 根据key信息获取对应语言的内容 * @@ -125,13 +138,7 @@ public class I18nMessageUtil { if (StrUtil.isEmpty(key)) { return StrUtil.EMPTY; } - String language = null; - for (Supplier supplier : LANGUAGE_OBTAIN) { - language = supplier.get(); - if (language != null) { - break; - } - } + String language = tryGetLanguage(); language = normalLanguage(language); Locale locale; switch (language) { diff --git a/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nThreadUtil.java b/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nThreadUtil.java new file mode 100644 index 000000000..ff3ba284d --- /dev/null +++ b/modules/common/src/main/java/org/dromara/jpom/common/i18n/I18nThreadUtil.java @@ -0,0 +1,27 @@ +package org.dromara.jpom.common.i18n; + +import cn.hutool.core.thread.ThreadUtil; + +/** + * @author bwcx_jzy1 + * @since 2024/6/15 + */ +public class I18nThreadUtil { + + /** + * 线程执行(获取父级线程语言) + * + * @param runnable runnable + */ + public static void execute(Runnable runnable) { + String language = I18nMessageUtil.tryGetLanguage(); + ThreadUtil.execute(() -> { + try { + I18nMessageUtil.setLanguage(language); + runnable.run(); + } finally { + I18nMessageUtil.clearLanguage(); + } + }); + } +} diff --git a/modules/server/src/main/java/org/dromara/jpom/build/BuildExecuteManage.java b/modules/server/src/main/java/org/dromara/jpom/build/BuildExecuteManage.java index 98859400f..e9df5aba5 100644 --- a/modules/server/src/main/java/org/dromara/jpom/build/BuildExecuteManage.java +++ b/modules/server/src/main/java/org/dromara/jpom/build/BuildExecuteManage.java @@ -32,6 +32,7 @@ import org.dromara.jpom.JpomApplication; import org.dromara.jpom.common.BaseServerController; import org.dromara.jpom.common.ServerConst; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.BuildExtConfig; import org.dromara.jpom.exception.LogRecorderCloseException; import org.dromara.jpom.func.assets.server.MachineDockerServer; @@ -905,7 +906,7 @@ public class BuildExecuteManage implements Runnable { Opt.ofBlankAble(buildInfoModel.getWebhook()) .ifPresent(s -> - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { IPlugin plugin = PluginFactory.getPlugin("webhook"); map.put("JPOM_WEBHOOK_EVENT", DefaultWebhookPluginImpl.WebhookEvent.BUILD); diff --git a/modules/server/src/main/java/org/dromara/jpom/controller/IndexControl.java b/modules/server/src/main/java/org/dromara/jpom/controller/IndexControl.java index 1f53ad2a7..c6c930cc2 100644 --- a/modules/server/src/main/java/org/dromara/jpom/controller/IndexControl.java +++ b/modules/server/src/main/java/org/dromara/jpom/controller/IndexControl.java @@ -286,7 +286,7 @@ public class IndexControl extends BaseServerController { UserModel userModel = getUserModel(); String workspaceId = nodeService.getCheckUserWorkspace(request); JSONObject config = systemParametersServer.getConfigDefNewInstance(StrUtil.format("menus_config_{}", workspaceId), JSONObject.class); - String language = I18nMessageUtil.parseLanguage(request); + String language = I18nMessageUtil.tryGetLanguage(); // 菜单 InputStream inputStream = ResourceUtil.getStream("classpath:/menus/" + language + "/index.json"); JSONArray showArray = config.getJSONArray("serverMenuKeys"); @@ -328,7 +328,7 @@ public class IndexControl extends BaseServerController { @SystemPermission public IJsonMessage> systemMenusData(HttpServletRequest request) { UserModel userModel = getUserModel(); - String language = I18nMessageUtil.parseLanguage(request); + String language = I18nMessageUtil.tryGetLanguage(); // 菜单 InputStream inputStream = ResourceUtil.getStream("classpath:/menus/" + language + "/system.json"); String json = IoUtil.read(inputStream, CharsetUtil.CHARSET_UTF_8); diff --git a/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerImagesController.java b/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerImagesController.java index 11d0368fb..56308f9ab 100644 --- a/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerImagesController.java +++ b/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerImagesController.java @@ -22,6 +22,7 @@ import cn.keepbx.jpom.plugins.IPlugin; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.common.validator.ValidatorItem; import org.dromara.jpom.common.validator.ValidatorRule; import org.dromara.jpom.permission.Feature; @@ -136,7 +137,7 @@ public abstract class BaseDockerImagesController extends BaseDockerController { logRecorder.system("start pull {}", repository); Consumer logConsumer = logRecorder::info; parameter.put("logConsumer", logConsumer); - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { plugin.execute("pullImage", parameter); logRecorder.system("pull end"); diff --git a/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerSwarmServiceController.java b/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerSwarmServiceController.java index 5ca949204..0f0931443 100644 --- a/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerSwarmServiceController.java +++ b/modules/server/src/main/java/org/dromara/jpom/controller/docker/base/BaseDockerSwarmServiceController.java @@ -26,6 +26,7 @@ import cn.keepbx.jpom.plugins.IPlugin; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.common.validator.ValidatorItem; import org.dromara.jpom.common.validator.ValidatorRule; import org.dromara.jpom.permission.Feature; @@ -167,7 +168,7 @@ public abstract class BaseDockerSwarmServiceController extends BaseDockerControl parameter.put("timestamps", timestamps); // 操作id parameter.put("uuid", uuid); - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { plugin.execute(StrUtil.equalsIgnoreCase(type, "service") ? "logService" : "logTask", parameter); logRecorder.system("pull end"); diff --git a/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingWhitelistController.java b/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingWhitelistController.java index 4b3e71ad7..6cfaaad1c 100644 --- a/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingWhitelistController.java +++ b/modules/server/src/main/java/org/dromara/jpom/controller/outgiving/OutGivingWhitelistController.java @@ -19,6 +19,7 @@ import cn.keepbx.jpom.model.JsonMessage; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.BaseServerController; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.func.files.service.StaticFileStorageService; import org.dromara.jpom.model.data.AgentWhitelist; import org.dromara.jpom.model.data.ServerWhitelist; @@ -140,7 +141,7 @@ public class OutGivingWhitelistController extends BaseServerController { String resultData = AgentWhitelist.convertToLine(list); // 重新检查静态目录任务状态 - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { staticFileStorageService.startLoad(); } catch (Exception e) { diff --git a/modules/server/src/main/java/org/dromara/jpom/controller/system/WorkspaceController.java b/modules/server/src/main/java/org/dromara/jpom/controller/system/WorkspaceController.java index b805b2fc4..470d3c348 100644 --- a/modules/server/src/main/java/org/dromara/jpom/controller/system/WorkspaceController.java +++ b/modules/server/src/main/java/org/dromara/jpom/controller/system/WorkspaceController.java @@ -279,7 +279,7 @@ public class WorkspaceController extends BaseServerController { JSONObject config = systemParametersServer.getConfigDefNewInstance(StrUtil.format("menus_config_{}", workspaceId), JSONObject.class); //"classpath:/menus/index.json" //"classpath:/menus/node-index.json" - String language = I18nMessageUtil.parseLanguage(request); + String language = I18nMessageUtil.tryGetLanguage(); config.put("serverMenus", this.readMenusJson("classpath:/menus/" + language + "/index.json")); return JsonMessage.success("", config); } diff --git a/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileReleaseTaskService.java b/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileReleaseTaskService.java index 8efab5420..4fdd99aab 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileReleaseTaskService.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileReleaseTaskService.java @@ -33,6 +33,7 @@ import org.dromara.jpom.common.ServerConst; import org.dromara.jpom.common.forward.NodeForward; import org.dromara.jpom.common.forward.NodeUrl; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.BuildExtConfig; import org.dromara.jpom.func.assets.model.MachineSshModel; import org.dromara.jpom.func.files.model.FileReleaseTaskLogModel; @@ -272,7 +273,7 @@ public class FileReleaseTaskService extends BaseWorkspaceService { + I18nThreadUtil.execute(() -> { try { strictSyncFinisher.start(); if (cancelTag.containsKey(taskId)) { diff --git a/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileStorageService.java b/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileStorageService.java index 4e150f947..34c871e7b 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileStorageService.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/files/service/FileStorageService.java @@ -16,7 +16,6 @@ import cn.hutool.core.date.SystemClock; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.StreamProgress; import cn.hutool.core.io.unit.DataSize; -import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; @@ -28,6 +27,7 @@ import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.JpomApplication; import org.dromara.jpom.common.ServerConst; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.BuildExtConfig; import org.dromara.jpom.func.files.model.FileStorageModel; import org.dromara.jpom.service.IStatusRecover; @@ -99,7 +99,7 @@ public class FileStorageService extends BaseGlobalOrWorkspaceService { + I18nThreadUtil.execute(() -> { try { File tempPath = configBean.getTempPath(); File file = FileUtil.file(tempPath, "file-storage-download", uuid); diff --git a/modules/server/src/main/java/org/dromara/jpom/func/system/controller/CacheManageController.java b/modules/server/src/main/java/org/dromara/jpom/func/system/controller/CacheManageController.java index 4545adc9a..d43dd426e 100644 --- a/modules/server/src/main/java/org/dromara/jpom/func/system/controller/CacheManageController.java +++ b/modules/server/src/main/java/org/dromara/jpom/func/system/controller/CacheManageController.java @@ -28,6 +28,7 @@ import org.dromara.jpom.common.BaseServerController; import org.dromara.jpom.common.JpomManifest; import org.dromara.jpom.common.forward.NodeUrl; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.common.validator.ValidatorItem; import org.dromara.jpom.common.validator.ValidatorRule; import org.dromara.jpom.configuration.ClusterConfig; @@ -197,7 +198,7 @@ public class CacheManageController extends BaseServerController implements ICach @GetMapping(value = "async-refresh-cache", produces = MediaType.APPLICATION_JSON_VALUE) public IJsonMessage refresh() { Assert.state(!this.refreshCacheIng, I18nMessageUtil.get("i18n.refreshing_cache.c969")); - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { this.refreshCacheIng = true; this.executeTask(); diff --git a/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java b/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java index c7b538b14..4744e221a 100644 --- a/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java +++ b/modules/server/src/main/java/org/dromara/jpom/outgiving/OutGivingRun.java @@ -31,6 +31,7 @@ import org.dromara.jpom.common.Const; import org.dromara.jpom.common.forward.NodeForward; import org.dromara.jpom.common.forward.NodeUrl; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.model.AfterOpt; import org.dromara.jpom.model.data.NodeModel; import org.dromara.jpom.model.log.OutGivingLog; @@ -343,7 +344,7 @@ public class OutGivingRun { Opt.ofBlankAble(outGivingModel2.getWebhook()) .orElse(null)) .ifPresent(webhook -> - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { // outGivingId、outGivingName、status、statusMsg、executeTime Map map = new HashMap<>(10); map.put("outGivingId", outGivingId); diff --git a/modules/server/src/main/java/org/dromara/jpom/service/dblog/DbUserOperateLogService.java b/modules/server/src/main/java/org/dromara/jpom/service/dblog/DbUserOperateLogService.java index 56c668665..b719c3db2 100644 --- a/modules/server/src/main/java/org/dromara/jpom/service/dblog/DbUserOperateLogService.java +++ b/modules/server/src/main/java/org/dromara/jpom/service/dblog/DbUserOperateLogService.java @@ -19,6 +19,7 @@ import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.extra.spring.SpringUtil; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.model.PageResultDto; import org.dromara.jpom.model.data.MonitorModel; import org.dromara.jpom.model.data.MonitorUserOptModel; @@ -203,7 +204,7 @@ public class DbUserOperateLogService extends BaseWorkspaceService { + I18nThreadUtil.execute(() -> { try { NotifyUtil.send(notify1, I18nMessageUtil.get("i18n.user_operation_alarm.15b9"), context); } catch (Exception e) { @@ -216,7 +217,7 @@ public class DbUserOperateLogService extends BaseWorkspaceService { + I18nThreadUtil.execute(() -> { try { NotifyUtil.send(notify1, I18nMessageUtil.get("i18n.user_operation_alarm.15b9"), context); } catch (Exception e) { @@ -228,7 +229,7 @@ public class DbUserOperateLogService extends BaseWorkspaceService { + I18nThreadUtil.execute(() -> { try { NotifyUtil.send(notify1, I18nMessageUtil.get("i18n.user_operation_alarm.15b9"), context); } catch (Exception e) { @@ -249,7 +250,7 @@ public class DbUserOperateLogService extends BaseWorkspaceService { + I18nThreadUtil.execute(() -> { // 更新用户名和工作空间名 try { UserOperateLogV1 update = new UserOperateLogV1(); diff --git a/modules/server/src/main/java/org/dromara/jpom/service/node/ssh/SshCommandService.java b/modules/server/src/main/java/org/dromara/jpom/service/node/ssh/SshCommandService.java index 8063ece7e..604e2ef47 100644 --- a/modules/server/src/main/java/org/dromara/jpom/service/node/ssh/SshCommandService.java +++ b/modules/server/src/main/java/org/dromara/jpom/service/node/ssh/SshCommandService.java @@ -21,6 +21,7 @@ import com.jcraft.jsch.Session; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.BaseServerController; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.cron.CronUtils; import org.dromara.jpom.func.assets.model.MachineSshModel; import org.dromara.jpom.model.EnvironmentMapBuilder; @@ -197,7 +198,7 @@ public class SshCommandService extends BaseWorkspaceService implem for (String sshId : sshIds) { this.executeItem(syncFinisher, commandModel, params, sshId, batchId, triggerExecType, envMap); } - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { syncFinisher.start(); } catch (Exception e) { diff --git a/modules/server/src/main/java/org/dromara/jpom/socket/handler/DockerLogHandler.java b/modules/server/src/main/java/org/dromara/jpom/socket/handler/DockerLogHandler.java index aed61707a..abcaa1a93 100644 --- a/modules/server/src/main/java/org/dromara/jpom/socket/handler/DockerLogHandler.java +++ b/modules/server/src/main/java/org/dromara/jpom/socket/handler/DockerLogHandler.java @@ -23,6 +23,7 @@ import cn.keepbx.jpom.plugins.IPlugin; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.func.assets.model.MachineDockerModel; import org.dromara.jpom.func.assets.server.MachineDockerServer; import org.dromara.jpom.model.user.UserModel; @@ -113,7 +114,7 @@ public class DockerLogHandler extends BaseProxyHandler { map.put("charset", CharsetUtil.CHARSET_UTF_8); map.put("consumer", consumer); map.put("timestamps", json.getBoolean("timestamps")); - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { attributes.put("thread", Thread.currentThread()); IPlugin plugin = PluginFactory.getPlugin(DockerInfoService.DOCKER_PLUGIN_NAME); try { diff --git a/modules/server/src/main/java/org/dromara/jpom/socket/handler/NodeUpdateHandler.java b/modules/server/src/main/java/org/dromara/jpom/socket/handler/NodeUpdateHandler.java index a571705f5..d09c74981 100644 --- a/modules/server/src/main/java/org/dromara/jpom/socket/handler/NodeUpdateHandler.java +++ b/modules/server/src/main/java/org/dromara/jpom/socket/handler/NodeUpdateHandler.java @@ -26,6 +26,7 @@ import org.dromara.jpom.common.JpomManifest; import org.dromara.jpom.common.forward.NodeForward; import org.dromara.jpom.common.forward.NodeUrl; import org.dromara.jpom.common.i18n.I18nMessageUtil; +import org.dromara.jpom.common.i18n.I18nThreadUtil; import org.dromara.jpom.configuration.NodeConfig; import org.dromara.jpom.func.assets.model.MachineNodeModel; import org.dromara.jpom.func.assets.server.MachineNodeServer; @@ -117,7 +118,7 @@ public class NodeUpdateHandler extends BaseProxyHandler { return proxySession; }); // 连接节点 - ThreadUtil.execute(() -> { + I18nThreadUtil.execute(() -> { try { if (!nodeClient.isConnected()) { nodeClient.reconnectBlocking(); diff --git a/web-vue/src/components/codeEditor/index.vue b/web-vue/src/components/codeEditor/index.vue index bd568ea0c..ee78e695c 100644 --- a/web-vue/src/components/codeEditor/index.vue +++ b/web-vue/src/components/codeEditor/index.vue @@ -62,15 +62,13 @@ diff --git a/web-vue/src/d.ts/components.d.ts b/web-vue/src/d.ts/components.d.ts index 46440b8b7..47443ce44 100644 --- a/web-vue/src/d.ts/components.d.ts +++ b/web-vue/src/d.ts/components.d.ts @@ -92,6 +92,7 @@ declare module 'vue' { AUpload: typeof import('ant-design-vue/es')['Upload'] BarsOutlined: typeof import('@ant-design/icons-vue')['BarsOutlined'] BlockOutlined: typeof import('@ant-design/icons-vue')['BlockOutlined'] + CheckCircleFilled: typeof import('@ant-design/icons-vue')['CheckCircleFilled'] CheckCircleOutlined: typeof import('@ant-design/icons-vue')['CheckCircleOutlined'] CloudDownloadOutlined: typeof import('@ant-design/icons-vue')['CloudDownloadOutlined'] CloudOutlined: typeof import('@ant-design/icons-vue')['CloudOutlined'] @@ -160,6 +161,7 @@ declare module 'vue' { SolutionOutlined: typeof import('@ant-design/icons-vue')['SolutionOutlined'] SortAscendingOutlined: typeof import('@ant-design/icons-vue')['SortAscendingOutlined'] SortDescendingOutlined: typeof import('@ant-design/icons-vue')['SortDescendingOutlined'] + StopFilled: typeof import('@ant-design/icons-vue')['StopFilled'] StopOutlined: typeof import('@ant-design/icons-vue')['StopOutlined'] SwapOutlined: typeof import('@ant-design/icons-vue')['SwapOutlined'] SwitcherOutlined: typeof import('@ant-design/icons-vue')['SwitcherOutlined'] diff --git a/web-vue/src/i18n/locales/en_us.json b/web-vue/src/i18n/locales/en_us.json index 1f2ac4654..12df70269 100644 --- a/web-vue/src/i18n/locales/en_us.json +++ b/web-vue/src/i18n/locales/en_us.json @@ -1913,7 +1913,8 @@ "4fc329c6": "Please enter an email address", "b29d1268": "The cluster address has not been configured yet, and the cluster cannot be switched", "ee23f800": "A verification code is required. It will take effect after confirmation of binding", - "b34c9126": "Are you sure you want to disable two-step verification? Disabling it will affect the security of your account, and existing mfa keys will be invalidated" + "b34c9126": "Are you sure you want to disable two-step verification? Disabling it will affect the security of your account, and existing mfa keys will be invalidated", + "8263b5e7": "After switching languages, the page will automatically refresh, and any opened tab menus (tabs) will be cleared together" }, "user-log": { "3ce54760": "Function", @@ -4599,7 +4600,14 @@ "5cb430c4": "Light Eclipse", "e26f389a": "Dark 2 Blackboard", "10adc4a3": "Light color idea", - "4ea93630": "Please enter the content" + "4ea93630": "Please enter the content", + "77c1e63d": "Start Search", + "4f85e42e": "Find Next", + "e9f2ef9a": "Find Previous", + "6a91de60": "replace", + "d720ba75": "replace all", + "6bcfa0bc": "Continuous search (dialog box will not automatically close, press Enter to find next, press Shift Enter to find previous)", + "e2621574": "Jump to row" } }, "compositionTransfer": { @@ -4920,6 +4928,37 @@ "e7ba3a8": "Parsing files, preparing to upload", "997a109d": "File upload ID generation failed:", "b6c41759": "Parsing file failed:" + }, + "const-i18n": { + "1397b7fa": "Cancel timing and no longer execute on schedule (supports! Prefix disabling scheduled execution, such as:! 0 0/1 * *?)", + "f397fdb9": "Minute level", + "19a1647f": "1 minute", + "edee406c": "5 minutes", + "eff3c3f": "10 minutes", + "4cda3b42": "30 minutes", + "5057c1d0": "Hour level", + "f00f01ca": "Every hour", + "f661cf9a": "Day level", + "597995d3": "At midnight and noon", + "c9219cc4": "At midnight", + "c2d566f2": "Second level (seconds level is not enabled by default and needs to be modified in the configuration file: [system. timerMatchSecond])", + "a5ef245b": "Once every 5 seconds", + "222fa259": "Once every 10 seconds", + "7a431b98": "Once every 30 seconds", + "3d7f1632": "[Recommendation] WeChat Mini Program Search for Number Shield OTP", + "ee0d1cb6": "[Recommended] Tencent Authentication CodeSimple and user-friendly", + "316edf4e": "AuthyRich features specially designed for two-step verification codes ", + "571efa83": "Google AuthenticatorSimple and easy to use, but does not support key export backupAndroid", + "4c20714f": "Microsoft AuthenticatorRecommendation for using Microsoft Family Bucket", + "c0f69a6e": "1PasswordPowerful and secure password management paid application", + "ba767044": "#ScriptId can be the script file name in the project path or the script template ID in the system", + "42cca3ee": "#Execute in the specified directory:/ The project directory/root/specific directory defaults to {'${jpom-agent_data_path} '}/script_run_cache", + "5b2ef0bb": "#Number of backup files retained", + "c4682b3f": "#Restrict backup of specified file suffixes (supports regularization)", + "1f958da6": "#Project file backup path", + "ae41f11b": "#Is the log backup function enabled", + "95d754a0": "#ScriptId can reference scripts in the script library (G {'@'} xxx), where xxx is the script tag in the script library, provided that the corresponding script is extracted and synchronized to the corresponding machine node", + "9daba997": "test" } }, "App": { diff --git a/web-vue/src/i18n/locales/zh_cn.json b/web-vue/src/i18n/locales/zh_cn.json index e9438ebab..0ebce41a8 100644 --- a/web-vue/src/i18n/locales/zh_cn.json +++ b/web-vue/src/i18n/locales/zh_cn.json @@ -1913,7 +1913,8 @@ "4fc329c6": "请输入邮箱地址", "b29d1268": "还未配置集群地址,不能切换集群", "ee23f800": "需要输入验证码,确认绑定后才生效奥", - "b34c9126": "确定要关闭两步验证吗?关闭后账号安全性将受到影响,关闭后已经存在的 mfa key 将失效" + "b34c9126": "确定要关闭两步验证吗?关闭后账号安全性将受到影响,关闭后已经存在的 mfa key 将失效", + "8263b5e7": "切换语言后页面将自动刷新,已经打开的标签菜单(选项卡)将一并清空" }, "user-log": { "3ce54760": "操作功能", @@ -4599,7 +4600,14 @@ "5cb430c4": "浅色 eclipse", "e26f389a": "深色2 blackboard", "10adc4a3": "浅色 idea", - "4ea93630": "请输入内容" + "4ea93630": "请输入内容", + "77c1e63d": " 开始搜索", + "4f85e42e": " 查找下一个", + "e9f2ef9a": " 查找上一个", + "6a91de60": " 替换", + "d720ba75": " 全部替换", + "6bcfa0bc": " 持续搜索(对话框不会自动关闭,按 Enter 查找下一个,按 Shift-Enter 查找上一个)", + "e2621574": " 跳至行" } }, "compositionTransfer": { @@ -4914,6 +4922,37 @@ "acabc771": "秒", "4a28d11c": "毫秒" }, + "const-i18n": { + "1397b7fa": "取消定时,不再定时执行(支持 ! 前缀禁用定时执行,如:!0 0/1 * * * ?)", + "f397fdb9": "分钟级别", + "19a1647f": "1分钟", + "edee406c": "5分钟", + "eff3c3f": "10分钟", + "4cda3b42": "30分钟", + "5057c1d0": "小时级别", + "f00f01ca": "每小时", + "f661cf9a": "天级别", + "597995d3": "凌晨0点和中午12点", + "c9219cc4": "凌晨0点", + "c2d566f2": "秒级别(默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])", + "a5ef245b": "5秒一次", + "222fa259": "10秒一次", + "7a431b98": "30秒一次", + "3d7f1632": "【推荐】微信小程序搜索 数盾OTP", + "ee0d1cb6": "【推荐】腾讯身份验证码 简单好用 Android", + "316edf4e": "Authy 功能丰富 专为两步验证码 iOS/Android/Windows/Mac/Linux   Chrome 扩展", + "571efa83": "Google Authenticator 简单易用,但不支持密钥导出备份 iOS Android", + "4c20714f": "Microsoft Authenticator 使用微软全家桶的推荐 iOS/Android", + "c0f69a6e": "1Password 强大安全的密码管理付费应用iOS/Android/Windows/Mac/Linux/ChromeOS", + "ba767044": "# scriptId 可以是项目路径下脚本文件名或者系统中的脚本模版ID", + "42cca3ee": "# 在指定目录执行: ./ 项目目录 /root/ 特定目录 默认在 {'${jpom_agent_data_path}'}/script_run_cache ", + "5b2ef0bb": "# 备份文件保留个数", + "c4682b3f": "# 限制备份指定文件后缀(支持正则)", + "1f958da6": "# 项目文件备份路径", + "ae41f11b": "# 是否开启日志备份功能", + "95d754a0": "# scriptId 可以引用脚本库中的脚本(G{'@'}xxx)其中 xxx 为脚本库中的脚本标记,前提需要提取将对应脚本同步至对应机器节点", + "9daba997": "测试" + }, "upload-pieces": { "ea2d7f82": "文件不能为空", "f3b7ae3a": "您的浏览器版本太低,不支持该功能", diff --git a/web-vue/src/pages/layout/user-header.vue b/web-vue/src/pages/layout/user-header.vue index f05d368df..b317e481f 100644 --- a/web-vue/src/pages/layout/user-header.vue +++ b/web-vue/src/pages/layout/user-header.vue @@ -483,11 +483,12 @@ - - - {{ item.label }} - - + + + {{ + item.label + }} + diff --git a/web-vue/src/utils/const-i18n.ts b/web-vue/src/utils/const-i18n.ts index 2117ca5bc..66de2466d 100644 --- a/web-vue/src/utils/const-i18n.ts +++ b/web-vue/src/utils/const-i18n.ts @@ -4,23 +4,24 @@ import { t } from '@/i18n' * mfa app 应用举例 */ export const MFA_APP_TIP_ARRAY = [ - t('utils.const.3d7f1632'), - t('utils.const.ee0d1cb6'), - t('utils.const.316edf4e'), - t('utils.const.571efa83'), - t('utils.const.4c20714f'), - t('utils.const.c0f69a6e') + t('utils.const-i18n.3d7f1632'), + t('utils.const-i18n.ee0d1cb6'), + t('utils.const-i18n.316edf4e'), + t('utils.const-i18n.571efa83'), + t('utils.const-i18n.4c20714f'), + t('utils.const-i18n.c0f69a6e') ] /** * 项目 DSL 示例 */ export const PROJECT_DSL_DEFATUL = - t('utils.const.ba767044') + + t('utils.const-i18n.ba767044') + '\n' + - t('utils.const.95d754a0') + + t('utils.const-i18n.95d754a0') + '\n' + - t('utils.const.59e55b4') + + 'description:' + + t('utils.const-i18n.9daba997') + '\n' + 'run:\r\n' + ' start:\r\n' + @@ -55,17 +56,17 @@ export const PROJECT_DSL_DEFATUL = '# scriptEnv:\r\n' + '# "boot_active": test\r\n' + '# fileChangeReload: true\r\n' + - t('utils.const.42cca3ee') + + t('utils.const-i18n.42cca3ee') + '# execPath: ./\r\n' + 'file:\r\n' + - t('utils.const.5b2ef0bb') + + t('utils.const-i18n.5b2ef0bb') + '# backupCount: 5\r\n' + - t('utils.const.c4682b3f') + + t('utils.const-i18n.c4682b3f') + "# backupSuffix: [ '.jar','.html','^.+\\.(?i)(txt)$' ]\r\n" + - t('utils.const.1f958da6') + + t('utils.const-i18n.1f958da6') + '# backupPath: /data/jpom_backup\r\n' + 'config:\r\n' + - t('utils.const.ae41f11b') + + t('utils.const-i18n.ae41f11b') + '# autoBackToFile: true\r\n' + '\r\n' @@ -76,7 +77,7 @@ export const PROJECT_DSL_DEFATUL = */ export const CRON_DATA_SOURCE = [ { - title: t('utils.const.1397b7fa'), + title: t('utils.const-i18n.1397b7fa'), options: [ { title: '', @@ -85,61 +86,61 @@ export const CRON_DATA_SOURCE = [ ] }, { - title: t('utils.const.f397fdb9'), + title: t('utils.const-i18n.f397fdb9'), options: [ { - title: t('utils.const.19a1647f'), + title: t('utils.const-i18n.19a1647f'), value: '0 0/1 * * * ?' }, { - title: t('utils.const.edee406c'), + title: t('utils.const-i18n.edee406c'), value: '0 0/5 * * * ?' }, { - title: t('utils.const.eff3c3f'), + title: t('utils.const-i18n.eff3c3f'), value: '0 0/10 * * * ?' }, { - title: t('utils.const.4cda3b42'), + title: t('utils.const-i18n.4cda3b42'), value: '0 0/30 * * * ?' } ] }, { - title: t('utils.const.5057c1d0'), + title: t('utils.const-i18n.5057c1d0'), options: [ { - title: t('utils.const.f00f01ca'), + title: t('utils.const-i18n.f00f01ca'), value: '0 0 0/1 * * ?' } ] }, { - title: t('utils.const.f661cf9a'), + title: t('utils.const-i18n.f661cf9a'), options: [ { - title: t('utils.const.597995d3'), + title: t('utils.const-i18n.597995d3'), value: '0 0 0,12 * * ?' }, { - title: t('utils.const.c9219cc4'), + title: t('utils.const-i18n.c9219cc4'), value: '0 0 0 * * ?' } ] }, { - title: t('utils.const.c2d566f2'), + title: t('utils.const-i18n.c2d566f2'), options: [ { - title: t('utils.const.a5ef245b'), + title: t('utils.const-i18n.a5ef245b'), value: '0/5 * * * * ?' }, { - title: t('utils.const.222fa259'), + title: t('utils.const-i18n.222fa259'), value: '0/10 * * * * ?' }, { - title: t('utils.const.7a431b98'), + title: t('utils.const-i18n.7a431b98'), value: '0/30 * * * * ?' } ]