Bläddra i källkod

[monitor] 监控类型名称i18n国际化支持

tomsun28 4 år sedan
förälder
incheckning
5b86e9f48e

+ 6 - 0
common/src/main/java/com/usthe/common/entity/job/Job.java

@@ -46,6 +46,12 @@ public class Job {
      */
     private String app;
     /**
+     * 监控类型的国际化名称
+     * zh-CN: PING连通性
+     * en-US: PING CONNECT
+     */
+    private Map<String, String> name;
+    /**
      * 任务派发开始时间戳
      */
     private long timestamp;

+ 46 - 0
manager/src/main/java/com/usthe/manager/controller/I18nController.java

@@ -0,0 +1,46 @@
+package com.usthe.manager.controller;
+
+import com.usthe.common.entity.dto.Message;
+import com.usthe.manager.pojo.entity.ParamDefine;
+import com.usthe.manager.service.AppService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+
+/**
+ * 国际化I18N
+ * @author tom
+ * @date 2021/12/4 21:40
+ */
+@Api(tags = "I18N国际化资源API")
+@RestController
+@RequestMapping(path = "/i18n", produces = {APPLICATION_JSON_VALUE})
+public class I18nController {
+
+    @Autowired
+    private AppService appService;
+
+    @GetMapping("/{lang}")
+    @ApiOperation(value = "查询总的i18n资源", notes = "查询总的i18n国际化文本资源")
+    public ResponseEntity<Message<Map<String, String>>> queryI18n(
+            @ApiParam(value = "语言类型", example = "zh-CN", defaultValue = "zh-CN")
+            @PathVariable(name = "lang", required = false) String lang) {
+        if (lang == null || "".equals(lang)) {
+            lang = "zh-CN";
+        }
+        lang = lang.equalsIgnoreCase("zh-cn")? "zh-CN" : lang;
+        lang = lang.equalsIgnoreCase("en-us")? "en-US" : lang;
+        Map<String, String> i18nResource = appService.getI18nResources(lang);
+        return ResponseEntity.ok(new Message<>(i18nResource));
+    }
+}

+ 8 - 0
manager/src/main/java/com/usthe/manager/service/AppService.java

@@ -4,6 +4,7 @@ import com.usthe.common.entity.job.Job;
 import com.usthe.manager.pojo.entity.ParamDefine;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 监控类型管理接口
@@ -26,4 +27,11 @@ public interface AppService {
      * @throws IllegalArgumentException 当不存在即不支持对应名称的监控类型时抛出
      */
     Job getAppDefine(String app) throws IllegalArgumentException;
+
+    /**
+     * 获取定义的监控I18N资源
+     * @param lang 语言类型
+     * @return I18N资源
+     */
+    Map<String, String> getI18nResources(String lang);
 }

+ 19 - 0
manager/src/main/java/com/usthe/manager/service/impl/AppServiceImpl.java

@@ -6,6 +6,7 @@ import com.usthe.manager.pojo.dto.ParamDefineDto;
 import com.usthe.manager.pojo.entity.ParamDefine;
 import com.usthe.manager.service.AppService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.common.protocol.types.Field;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Service;
@@ -17,6 +18,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.URL;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -58,6 +60,23 @@ public class AppServiceImpl implements AppService, CommandLineRunner {
     }
 
     @Override
+    public Map<String, String> getI18nResources(String lang) {
+        Map<String, String> i18nMap = new HashMap<>(32);
+        for (Job job : appDefines.values()) {
+            // todo 暂时只国际化监控类型名称  后面需要支持指标名称
+            Map<String, String> name = job.getName();
+            if (name != null && !name.isEmpty()) {
+                String i18nName = name.get(lang);
+                if (i18nName == null) {
+                    i18nName = name.values().stream().findFirst().get();
+                }
+                i18nMap.put("monitor.app." + job.getApp(), i18nName);
+            }
+        }
+        return i18nMap;
+    }
+
+    @Override
     public void run(String... args) throws Exception {
         // 读取app定义配置加载到内存中 define/app/*.yml
         Yaml yaml = new Yaml();

+ 4 - 1
manager/src/main/resources/define/app/A-example.yml

@@ -1,5 +1,8 @@
-# 监控应用类型名称(与文件名保持一致) eg: linux windows tomcat mysql aws...
+# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
 app: exapmle
+name:
+  zh-CN: 模拟应用类型
+  en-US: EXAMPLE APP
 # 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
 # 强制固定必须参数 - host
 configmap:

+ 3 - 0
manager/src/main/resources/define/app/api.yml

@@ -1,5 +1,8 @@
 # 监控应用类型名称(与文件名保持一致) eg: linux windows tomcat mysql aws...
 app: api
+name:
+  zh-CN: HTTP API
+  en-US: HTTP API
 # 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
 # 强制固定必须参数 - host
 configmap:

+ 3 - 0
manager/src/main/resources/define/app/ping.yml

@@ -1,5 +1,8 @@
 # 监控应用类型名称(与文件名保持一致) eg: linux windows tomcat mysql aws...
 app: ping
+name:
+  zh-CN: PING连通性
+  en-US: PING CONNECT
 # 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
 # 强制固定必须参数 - host
 configmap:

+ 3 - 0
manager/src/main/resources/define/app/telnet.yml

@@ -1,4 +1,7 @@
 app: telnet
+name:
+  zh-CN: TELNET端口可用性
+  en-US: PORT TELNET
 configmap:
   - key: host
     type: 1

+ 3 - 3
manager/src/main/resources/define/app/website.yml

@@ -1,7 +1,7 @@
-# 监控应用类型名称(与文件名保持一致) eg: linux windows tomcat mysql aws...
 app: website
-# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
-# 强制固定必须参数 - host
+name:
+  zh-CN: 网站监测
+  en-US: WEBSITE MONITOR
 configmap:
   - key: host
     type: 1

+ 23 - 12
web-app/src/app/core/i18n/i18n.service.ts

@@ -1,24 +1,26 @@
 // 请参考:https://ng-alain.com/docs/i18n
-import { Platform } from '@angular/cdk/platform';
-import { registerLocaleData } from '@angular/common';
+import {Platform} from '@angular/cdk/platform';
+import {registerLocaleData} from '@angular/common';
 import ngEn from '@angular/common/locales/en';
 import ngZh from '@angular/common/locales/zh';
 import ngZhTw from '@angular/common/locales/zh-Hant';
-import { Injectable } from '@angular/core';
+import {Injectable} from '@angular/core';
 import {
+  _HttpClient,
+  AlainI18nBaseService,
   DelonLocaleService,
   en_US as delonEnUS,
   SettingsService,
   zh_CN as delonZhCn,
-  zh_TW as delonZhTw,
-  _HttpClient,
-  AlainI18nBaseService
+  zh_TW as delonZhTw
 } from '@delon/theme';
-import { AlainConfigService } from '@delon/util/config';
-import { enUS as dfEn, zhCN as dfZhCn, zhTW as dfZhTw } from 'date-fns/locale';
-import { NzSafeAny } from 'ng-zorro-antd/core/types';
-import { en_US as zorroEnUS, NzI18nService, zh_CN as zorroZhCN, zh_TW as zorroZhTW } from 'ng-zorro-antd/i18n';
-import { Observable } from 'rxjs';
+import {AlainConfigService} from '@delon/util/config';
+import {enUS as dfEn, zhCN as dfZhCn, zhTW as dfZhTw} from 'date-fns/locale';
+import {NzSafeAny} from 'ng-zorro-antd/core/types';
+import {en_US as zorroEnUS, NzI18nService, zh_CN as zorroZhCN, zh_TW as zorroZhTW} from 'ng-zorro-antd/i18n';
+import {Observable, zip} from 'rxjs';
+import {map} from "rxjs/operators";
+import {Message} from "../../pojo/Message";
 
 interface LangConfigData {
   abbr: string;
@@ -92,7 +94,16 @@ export class I18NService extends AlainI18nBaseService {
   }
 
   loadLangData(lang: string): Observable<NzSafeAny> {
-    return this.http.get(`http://localhost:4200/assets/tmp/i18n/${lang}.json`);
+    return zip(this.http.get(`http://localhost:4200/assets/tmp/i18n/${lang}.json`),this.http.get(`/i18n/${lang}`))
+      .pipe(
+        map(([langLocalData, langRemoteData]: [Record<string, string>, Message<any>]) => {
+          let remote:Record<string, string> = langRemoteData.data;
+          Object.keys(remote).forEach(key => {
+            langLocalData[key] = remote[key];
+          });
+          return langLocalData;
+        })
+      )
   }
 
   use(lang: string, data: Record<string, unknown>): void {

+ 1 - 1
web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.html

@@ -13,7 +13,7 @@
   </nz-breadcrumb-item>
   <nz-breadcrumb-item>
     <i nz-icon nzType="edit"></i>
-    <span>修改 {{monitor.app}} 监控</span>
+    <span>修改 {{'monitor.app.' + monitor.app | i18n}} 监控</span>
   </nz-breadcrumb-item>
 </nz-breadcrumb>
 <nz-divider></nz-divider>

+ 3 - 3
web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html

@@ -7,7 +7,7 @@
   </nz-breadcrumb-item>
   <nz-breadcrumb-item>
     <i nz-icon nzType="monitor"></i>
-    <span>{{app?app.toUpperCase() : ""}} 监控列表</span>
+    <span>{{'monitor.app.' + app | i18n}} 监控列表</span>
   </nz-breadcrumb-item>
 </nz-breadcrumb>
 <nz-divider></nz-divider>
@@ -15,7 +15,7 @@
 <button nz-button nzType="primary">
   <a routerLink="/monitors/new" [queryParams]="{app: app}">
     <i nz-icon nzType="appstore-add" nzTheme="outline"></i>
-    新增 {{app}}
+    新增 {{'monitor.app.' + app | i18n}}
   </a>
 </button>
 <button nz-button nzType="primary" (click)="onEditMonitor()" >
@@ -85,7 +85,7 @@
     <td nzAlign="center">
       <nz-tag nzColor="processing">
         <i nz-icon nzType="cloud"></i>
-        <span>{{ data.app }}</span>
+        <span>{{ 'monitor.app.' + data.app | i18n }}</span>
       </nz-tag>
     </td>
     <td nzAlign="center">{{ data.gmtUpdate? data.gmtUpdate : data.gmtCreate }}</td>

+ 1 - 1
web-app/src/app/routes/monitor/monitor-new/monitor-new.component.html

@@ -13,7 +13,7 @@
   </nz-breadcrumb-item>
   <nz-breadcrumb-item>
     <i nz-icon nzType="plus-circle"></i>
-    <span>新增 {{monitor.app}} 监控</span>
+    <span>新增 {{'monitor.app.' + monitor.app | i18n}} 监控</span>
   </nz-breadcrumb-item>
 </nz-breadcrumb>
 <nz-divider></nz-divider>

+ 12 - 109
web-app/src/assets/tmp/i18n/zh-CN.json

@@ -1,7 +1,12 @@
 {
   "menu": {
     "main": "主导航",
+    "lang": "语言",
     "dashboard": "仪表盘",
+    "search.placeholder": "搜索监控:名称、IP等",
+    "fullscreen": "全屏",
+    "fullscreen.exit": "退出全屏",
+    "clear.local.storage": "清理本地缓存",
     "monitor": {
       "": "监控",
       "service": "应用服务监控",
@@ -9,6 +14,13 @@
       "os": "操作系统监控",
       "mid": "中间件监控"
     },
+    "account": {
+      "": "个人页",
+      "center": "个人中心",
+      "settings": "个人设置",
+      "trigger": "触发错误",
+      "logout": "退出登录"
+    },
     "alert": {
       "": "告警",
       "center": "告警中心",
@@ -38,115 +50,6 @@
       "redis": "Redis"
     }
   },
-  "menu.search.placeholder": "搜索监控:名称、IP等",
-  "menu.fullscreen": "全屏",
-  "menu.fullscreen.exit": "退出全屏",
-  "menu.clear.local.storage": "清理本地缓存",
-  "menu.lang": "语言",
-  "menu.shortcut": "快捷菜单",
-  "menu.widgets": "小部件",
-  "menu.alain": "Alain",
-  "menu.style": "样式",
-  "menu.style.typography": "字体排印",
-  "menu.style.gridmasonry": "瀑布流",
-  "menu.style.colors": "色彩",
-  "menu.delon": "Delon 类库",
-  "menu.delon.form": "动态表单",
-  "menu.delon.table": "简易表格",
-  "menu.delon.util": "工具集",
-  "menu.delon.print": "打印",
-  "menu.delon.guard": "路由守卫",
-  "menu.delon.cache": "字典缓存",
-  "menu.delon.qr": "二维码",
-  "menu.delon.acl": "基于角色访问控制",
-  "menu.delon.downfile": "下载文件",
-  "menu.delon.xlsx": "Excel操作",
-  "menu.delon.zip": "本地解压缩",
-  "menu.pro": "Antd Pro",
-  "menu.form": "表单页",
-  "menu.form.basicform": "基础表单",
-  "menu.form.stepform": "分步表单",
-  "menu.form.stepform.info": "分步表单(填写转账信息)",
-  "menu.form.stepform.confirm": "分步表单(确认转账信息)",
-  "menu.form.stepform.result": "分步表单(完成)",
-  "menu.form.advancedform": "高级表单",
-  "menu.list": "列表页",
-  "menu.list.searchtable": "查询表格",
-  "menu.list.basiclist": "标准列表",
-  "menu.list.cardlist": "卡片列表",
-  "menu.list.searchlist": "搜索列表",
-  "menu.list.searchlist.articles": "搜索列表(文章)",
-  "menu.list.searchlist.projects": "搜索列表(项目)",
-  "menu.list.searchlist.applications": "搜索列表(应用)",
-  "menu.profile": "详情页",
-  "menu.profile.basic": "基础详情页",
-  "menu.profile.advanced": "高级详情页",
-  "menu.result": "结果页",
-  "menu.result.success": "成功页",
-  "menu.result.fail": "失败页",
-  "menu.exception": "异常页",
-  "menu.exception.not-permission": "403",
-  "menu.exception.not-find": "404",
-  "menu.exception.server-error": "500",
-  "menu.account": "个人页",
-  "menu.account.center": "个人中心",
-  "menu.account.settings": "个人设置",
-  "menu.account.trigger": "触发错误",
-  "menu.account.logout": "退出登录",
-  "menu.report": "报表",
-  "menu.report.relation": "全屏关系图",
-  "menu.extras": "扩展",
-  "menu.extras.helpcenter": "帮助中心",
-  "menu.extras.settings": "设置",
-  "menu.extras.poi": "门店",
-  "app.analysis.test": "工专路 {{no}} 号店",
-  "app.analysis.introduce": "指标说明",
-  "app.analysis.total-sales": "总销售额",
-  "app.analysis.day-sales": "日销售额",
-  "app.analysis.visits": "访问量",
-  "app.analysis.visits-trend": "访问量趋势",
-  "app.analysis.visits-ranking": "门店访问量排名",
-  "app.analysis.day-visits": "日访问量",
-  "app.analysis.week": "周同比",
-  "app.analysis.day": "日同比",
-  "app.analysis.payments": "支付笔数",
-  "app.analysis.conversion-rate": "转化率",
-  "app.analysis.operational-effect": "运营活动效果",
-  "app.analysis.sales-trend": "销售趋势",
-  "app.analysis.sales-ranking": "门店销售额排名",
-  "app.analysis.all-year": "全年",
-  "app.analysis.all-month": "本月",
-  "app.analysis.all-week": "本周",
-  "app.analysis.all-today": "今日",
-  "app.analysis.search-users": "搜索用户数",
-  "app.analysis.per-capita-search": "人均搜索次数",
-  "app.analysis.online-top-search": "线上热门搜索",
-  "app.analysis.the-proportion-of-sales": "销售额类别占比",
-  "app.analysis.channel.all": "全部渠道",
-  "app.analysis.channel.online": "线上",
-  "app.analysis.channel.stores": "门店",
-  "app.analysis.sales": "销售额",
-  "app.analysis.traffic": "客流量",
-  "app.analysis.table.rank": "排名",
-  "app.analysis.table.search-keyword": "搜索关键词",
-  "app.analysis.table.users": "用户数",
-  "app.analysis.table.weekly-range": "周涨幅",
-  "app.monitor.trading-activity": "活动实时交易情况",
-  "app.monitor.total-transactions": "今日交易总额",
-  "app.monitor.sales-target": "销售目标完成率",
-  "app.monitor.remaining-time": "活动剩余时间",
-  "app.monitor.total-transactions-per-second": "每秒交易总额",
-  "app.monitor.activity-forecast": "活动情况预测",
-  "app.monitor.efficiency": "券核效率",
-  "app.monitor.ratio": "跳出率",
-  "app.monitor.proportion-per-category": "各品类占比",
-  "app.monitor.fast-food": "中式快餐",
-  "app.monitor.western-food": "西餐",
-  "app.monitor.hot-pot": "火锅",
-  "app.monitor.waiting-for-implementation": "等待后期实现",
-  "app.monitor.popular-searches": "热门搜索",
-  "app.monitor.resource-surplus": "资源剩余",
-  "app.monitor.fund-surplus": "补贴资金剩余",
   "app.lock": "锁屏",
   "app.login.message-invalid-credentials": "账户或密码错误(admin/ant.design)",
   "app.login.message-invalid-verification-code": "验证码错误",