Ambari 汉化方案及实践
# 一、Ambari 汉化
Ambari 是一个开源的管理和监控平台,通常用于管理 Apache Hadoop 集群。在国际化和本地化过程中,我们常常需要对 Ambari 的 Web 界面进行汉化,以便为中文用户提供更好的体验。在本文中,我将分享一个基于 Java 脚本和百度翻译 API 实现 Ambari 汉化的方案,并提供详细的步骤和代码示例。
# 1. 使用 Java 脚本 + 翻译
# 1.1 Ambari 2.8.0 翻译
在进行 Ambari 界面翻译时,我们首先需要提取 Ambari Web 界面中所有的英文字符串,并将其翻译成中文。这个过程包括读取 JavaScript 文件,提取其中的字符串,利用翻译 API 进行批量翻译,最后生成一个汉化后的 JavaScript 文件供前端使用。
# Java 汉化代码,使用 Java 8
以下是一个使用 Java 8 脚本引擎 Nashorn
执行 JavaScript 的例子,它会读取一个 JavaScript 文件,并使用百度翻译 API 对其中的英文字符串进行翻译。
package com.ttr.waterprint;
import javax.script.*;
import java.io.*;
import java.nio.file.*;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
public class ExecuteJavaScript {
private static final String APP_ID = "";
private static final String SECURITY_KEY = "";
private static final String TRANSLATE_URL = "https://fanyi-api.baidu.com/api/trans/vip/translate";
public static void main(String[] args) {
try {
// 创建ScriptEngineManager和ScriptEngine
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
// 读取并执行JavaScript文件
engine.eval(new cn.hutool.core.io.file.FileReader("22.js").getReader());
// 获取变量a的值
Object a = engine.get("a");
if (a instanceof Map) {
// 将JavaScript对象转换为Java Map
Map<String, String> map = (Map<String, String>) a;
// 创建ObjectMapper实例
ObjectMapper mapper = new ObjectMapper();
File outputFile = new File("output33.json");
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));
writer.write("{\n");
// 翻译并逐条写入Map中的值
boolean firstEntry = true;
for (Map.Entry<String, String> entry : map.entrySet()) {
if (!firstEntry) {
writer.write(",\n");
}
firstEntry = false;
String translatedValue = translateText(entry.getValue(), "en", "zh");
writer.write(String.format(" \"%s\": \"%s\"", entry.getKey(), translatedValue));
// 确保QPS小于10
TimeUnit.MILLISECONDS.sleep(110);
}
writer.write("\n}");
writer.close();
System.out.println("JSON文件已成功生成!");
} else {
System.out.println("变量a不是一个Map对象");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String translateText(String text, String fromLang, String toLang) throws IOException {
OkHttpClient client = new OkHttpClient();
String salt = String.valueOf(System.currentTimeMillis());
String sign = MD5(APP_ID + text + salt + SECURITY_KEY);
HttpUrl.Builder urlBuilder = HttpUrl.parse(TRANSLATE_URL).newBuilder();
urlBuilder.addQueryParameter("q", text);
urlBuilder.addQueryParameter("from", fromLang);
urlBuilder.addQueryParameter("to", toLang);
urlBuilder.addQueryParameter("appid", APP_ID);
urlBuilder.addQueryParameter("salt", salt);
urlBuilder.addQueryParameter("sign", sign);
Request request = new Request.Builder().url(urlBuilder.build()).build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
ObjectMapper mapper = new ObjectMapper();
String v= response.body().string();
return Convert.toStr(JSONUtil.parse(v).getByPath("trans_result[0].dst"));
}
}
private static String MD5(String input) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(input.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
// error action
}
return null;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
该代码通过读取 JavaScript 文件并将其内容传递给翻译 API,生成一个新的翻译后的 JSON 文件。这个 JSON 文件包含了原始 JavaScript 文件中的所有翻译结果,方便后续的集成。
# 翻译后的代码
{
"SomeLabel": "一些标签",
"Next": "下一步",
"Submit": "提交"
}
2
3
4
5
完整的代码可在 gitee 仓库 (opens new window) 中查看。
# 1.2 最终效果
经过翻译的界面截图如下所示,翻译结果已经成功地嵌入到 Ambari Web UI 中:
# 2. 生产环境替换方案
在生产环境中,您可以通过不同的方式来应用汉化后的代码。下面介绍两种常见的替换方案。
# 2.1 方案一:源码打包
首先,我们可以通过修改 Ambari 的源代码,直接在 ambari-web/app/messages.js
文件中替换翻译后的字符串。修改完成后,重新打包 Ambari Web 代码即可。
查看 ambari-web/app/message.js
文件是否生效,确认翻译结果已经被正确加载。
# 2.2 方案二:替换服务端 app.js
文件
另一种方式是直接替换服务端的 app.js
文件。通过修改服务端脚本来实现汉化,可以避免频繁的打包和重启操作。