From 393fbd2bdb06bb6306f3a5fb4637b5191076cb4c Mon Sep 17 00:00:00 2001 From: Zhongwen Deng Date: Thu, 21 Apr 2022 22:57:16 +0800 Subject: [PATCH] feat: add emqx_dashboard i18n --- .../i18n/emqx_dashboard_i18n.conf | 12 -- .../i18n/emqx_dashboard_schema.conf | 190 ++++++++++++++++++ .../src/emqx_dashboard_schema.erl | 68 +++---- scripts/merge-i18n.escript | 2 +- 4 files changed, 217 insertions(+), 55 deletions(-) delete mode 100644 apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf create mode 100644 apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf diff --git a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf b/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf deleted file mode 100644 index 2a588b752..000000000 --- a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf +++ /dev/null @@ -1,12 +0,0 @@ -emqx_dashboard_schema { - protocol { - desc { - en: "Protocol Name" - zh: "协议名" - } - label: { - en: "Protocol" - zh: "协议" - } - } -} diff --git a/apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf b/apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf new file mode 100644 index 000000000..d7b2055bb --- /dev/null +++ b/apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf @@ -0,0 +1,190 @@ +emqx_dashboard_schema { + listeners { + desc { + en: """HTTP(s) listeners are identified by their protocol type and are
+used to serve dashboard UI and restful HTTP API.
+Listeners must have a unique combination of port number and IP address.
+For example, an HTTP listener can listen on all configured IP addresses +on a given port for a machine by specifying the IP address 0.0.0.0.
+Alternatively, the HTTP listener can specify a unique IP address for each listener, +but use the same port.""" + zh: """仪表盘监听器设置。""" + } + label { + en: "Listeners" + zh: "监听器" + } + } + sample_interval { + desc { + en: """How often to update metrics displayed in the dashboard.
" +Note: `sample_interval` should be a divisor of 60.""" + zh: """更新仪表板中显示的指标的时间间隔。""" + } + } + token_expired_time { + desc { + en: "JWT token expiration time." + zh: "JWT token 过期时间" + } + label { + en: "Token expired time" + zh: "JWT 过期时间" + } + } + num_acceptors { + desc { + en: "Socket acceptor pool size for TCP protocols." + zh: "TCP协议的Socket acceptor池大小" + } + label { + en: "Number of acceptors" + zh: "Acceptor 数量" + } + } + max_connections { + desc { + en: "Maximum number of simultaneous connections." + zh: "同时处理的最大连接数" + } + label { + en: "Maximum connections" + zh: "最大连接数" + } + } + backlog { + desc { + en: "Defines the maximum length that the queue of pending connections can grow to." + zh: "排队等待连接的队列的最大长度" + } + label { + en: "Backlog" + zh: "排队长度" + } + } + send_timeout { + desc { + en: "Send timeout for the socket." + zh: "Socket发送超时时间" + } + label { + en: "Send timeout" + zh: "发送超时时间" + } + } + inet6 { + desc { + en: "Enable IPv6 support." + zh: "启用IPv6" + } + label { + en: "IPv6" + zh: "IPv6" + } + } + ipv6_v6only { + desc { + en: "Disable IPv4-to-IPv6 mapping for the listener." + zh: "禁用IPv4-to-IPv6映射" + } + label { + en: "IPv6 only" + zh: "IPv6 only" + } + } + desc_dashboard { + desc { + en: "Configuration for EMQX dashboard." + zh: "EMQX仪表板配置" + } + label { + en: "Dashboard" + zh: "仪表板" + } + } + desc_listeners { + desc { + en: "Configuration for the dashboard listener." + zh: "仪表板监听器配置" + } + label { + en: "Listeners" + zh: "监听器" + } + } + desc_http { + desc { + en: "Configuration for the dashboard listener (plaintext)." + zh: "仪表板监听器(HTTP)配置" + } + label { + en: "HTTP" + zh: "HTTP" + } + } + desc_https { + desc { + en: "Configuration for the dashboard listener (TLS)." + zh: "仪表板监听器(HTTPS)配置" + } + label { + en: "HTTPS" + zh: "HTTPS" + } + } + bind { + desc { + en: "Port without IP(18083) or port with specified IP(127.0.0.1:18083)." + zh: "监听的地址与端口" + } + label { + en: "Bind" + zh: "绑定端口" + } + } + default_username { + desc { + en: "The default username of the automatically created dashboard user." + zh: "默认的仪表板用户名" + } + label { + en: "Default username" + zh: "默认用户名" + } + } + default_password { + desc { + en: """The initial default password for dashboard 'admin' user.
" +For safety, it should be changed as soon as possible.""" + zh: """默认的仪表板用户密码
+为了安全,应该尽快修改密码。""" + } + label { + en: "Default password" + zh: "默认密码" + } + } + cors { + desc { + en: """Support Cross-Origin Resource Sharing (CORS).
+Allows a server to indicate any origins (domain, scheme, or port) other than
+允许服务器指示任何来源(域名、协议或端口),除了本服务器之外的任何浏览器应允许加载资源。""" + } + label { + en: "CORS" + zh: "跨域资源共享" + } + } + i18n_lang { + desc { + en: "Internationalization language support." + zh: "多语言支持" + } + label { + en: "I18n language" + zh: "多语言支持" + } + } +} diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl index 6f187a694..4fb7b2abc 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl @@ -32,16 +32,7 @@ fields("dashboard") -> {listeners, sc( ref("listeners"), - #{ - desc => - "HTTP(s) listeners are identified by their protocol type and are\n" - "used to serve dashboard UI and restful HTTP API.
\n" - "Listeners must have a unique combination of port number and IP address.
\n" - "For example, an HTTP listener can listen on all configured IP addresses\n" - "on a given port for a machine by specifying the IP address 0.0.0.0.
\n" - "Alternatively, the HTTP listener can specify a unique IP address for each listener,\n" - "but use the same port." - } + #{ desc => ?DESC(listeners)} )}, {default_username, fun default_username/1}, {default_password, fun default_password/1}, @@ -50,9 +41,8 @@ fields("dashboard") -> emqx_schema:duration_s(), #{ default => "10s", - desc => - "How often to update metrics displayed in the dashboard.
" - "Note: `sample_interval` should be a divisor of 60." + desc => ?DESC(sample_interval), + validator => fun validate_sample_interval/1 } )}, {token_expired_time, @@ -60,7 +50,7 @@ fields("dashboard") -> emqx_schema:duration(), #{ default => "30m", - desc => "JWT token expiration time." + desc => ?DESC(token_expired_time) } )}, {cors, fun cors/1}, @@ -93,7 +83,7 @@ fields("http") -> integer(), #{ default => 4, - desc => "Socket acceptor pool size for TCP protocols." + desc => ?DESC(num_acceptors) } )}, {"max_connections", @@ -101,7 +91,7 @@ fields("http") -> integer(), #{ default => 512, - desc => "Maximum number of simultaneous connections." + desc => ?DESC(max_connections) } )}, {"backlog", @@ -109,8 +99,7 @@ fields("http") -> integer(), #{ default => 1024, - desc => - "Defines the maximum length that the queue of pending connections can grow to." + desc => ?DESC(backlog) } )}, {"send_timeout", @@ -118,7 +107,7 @@ fields("http") -> emqx_schema:duration(), #{ default => "5s", - desc => "Send timeout for the socket." + desc => ?DESC(send_timeout) } )}, {"inet6", @@ -126,7 +115,7 @@ fields("http") -> boolean(), #{ default => false, - desc => "Sets up the listener for IPv6." + desc => ?DESC(inet6) } )}, {"ipv6_v6only", @@ -134,7 +123,7 @@ fields("http") -> boolean(), #{ default => false, - desc => "Disable IPv4-to-IPv6 mapping for the listener." + desc => ?DESC(ipv6_v6only) } )} ]; @@ -145,27 +134,22 @@ fields("https") -> emqx_schema:server_ssl_opts_schema(#{}, true) ). -desc("dashboard") -> - "Configuration for EMQX dashboard."; -desc("listeners") -> - "Configuration for the dashboard listener."; -desc("http") -> - "Configuration for the dashboard listener (plaintext)."; -desc("https") -> - "Configuration for the dashboard listener (TLS)."; -desc(_) -> - undefined. +desc("dashboard") -> ?DESC(desc_dashboard); +desc("listeners") -> ?DESC(desc_listeners); +desc("http") -> ?DESC(desc_http); +desc("https") -> ?DESC(desc_https); +desc(_) -> undefined. bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]); bind(default) -> 18083; bind(required) -> true; -bind(desc) -> "Port without IP(18083) or port with specified IP(127.0.0.1:18083)."; +bind(desc) -> ?DESC(bind); bind(_) -> undefined. default_username(type) -> string(); default_username(default) -> "admin"; default_username(required) -> true; -default_username(desc) -> "The default username of the automatically created dashboard user."; +default_username(desc) -> ?DESC(default_username); default_username('readOnly') -> true; default_username(_) -> undefined. @@ -180,11 +164,7 @@ default_password('readOnly') -> default_password(sensitive) -> true; default_password(desc) -> - "" - "\n" - "The initial default password for dashboard 'admin' user.\n" - "For safety, it should be changed as soon as possible." - ""; + ?DESC(default_password); default_password(_) -> undefined. @@ -195,18 +175,22 @@ cors(default) -> cors(required) -> false; cors(desc) -> - "Support Cross-Origin Resource Sharing (CORS).\n" - "Allows a server to indicate any origins (domain, scheme, or port) other than\n" - "its own from which a browser should permit loading resources."; + ?DESC(cors); cors(_) -> undefined. i18n_lang(type) -> ?ENUM([en, zh]); i18n_lang(default) -> en; i18n_lang('readOnly') -> true; -i18n_lang(desc) -> "Internationalization language support."; +i18n_lang(desc) -> ?DESC(i18n_lang); i18n_lang(_) -> undefined. +validate_sample_interval(Second) -> + case Second >= 1 andalso Second =< 60 andalso (60 rem Second =:= 0) of + true -> ok; + false -> error({"Sample interval must be between 1 and 60 and be a divisor of 60.", Second}) + end. + sc(Type, Meta) -> hoconsc:mk(Type, Meta). ref(Field) -> hoconsc:ref(?MODULE, Field). diff --git a/scripts/merge-i18n.escript b/scripts/merge-i18n.escript index 13a7df27b..8a42cffe4 100755 --- a/scripts/merge-i18n.escript +++ b/scripts/merge-i18n.escript @@ -3,7 +3,7 @@ -mode(compile). main(_) -> - {ok, BaseConf} = file:read_file("apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf"), + {ok, BaseConf} = file:read_file("apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf"), Cfgs = get_all_cfgs("apps/"), Conf = [merge(BaseConf, Cfgs),