springboot+thymeleaf实现xml翻译
其中翻译插件使用的是腾讯云机器翻译api
页面包含功能有:文件上传,语言选择,下载翻译好的xml等,读者自行预览
成品效果图如下:
pom文件:
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.835</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!--使用thymelaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
控制器代码如下:
package com.cn.linka.business.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.tmt.v20180321.TmtClient;
import com.tencentcloudapi.tmt.v20180321.models.TextTranslateRequest;
import com.tencentcloudapi.tmt.v20180321.models.TextTranslateResponse;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
@Slf4j
@Controller
public class TranslationController {
// Replace these values with your Tencent Cloud API credentials
private final String SECRET_ID = "SECRET_ID ";
private final String SECRET_KEY = "SECRET_KEY ";
@PostMapping("/translate")
@ResponseBody
public String translateXML(@RequestParam("file") MultipartFile file, @RequestParam("targetLanguage") String targetLanguage) {
try {
// Read XML content from uploaded file
String xmlContent = new String(file.getBytes());
// Translate XML content using Tencent Cloud Translate API
return translateXml(xmlContent,targetLanguage);
} catch (Exception e) {
e.printStackTrace();
return "Translation failed.";
}
}
// Function to translate XML content using Tencent Cloud Translate API
private String translateXml(String xmlContent,String targetLanguage) {
try {
// Create a DocumentBuilder
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
// Parse the XML content
Document doc = builder.parse(new InputSource(new StringReader(xmlContent)));
// Find and translate text nodes containing Chinese characters
translateTextNodes(doc,targetLanguage);
// Serialize the modified document back to XML string
StringWriter writer = new StringWriter();
TransformerFactory tfactory = TransformerFactory.newInstance();
javax.xml.transform.Transformer xform = tfactory.newTransformer();
xform.transform(new DOMSource(doc), new javax.xml.transform.stream.StreamResult(writer));
return writer.toString();
} catch (Exception e) {
e.printStackTrace();
return "Translation failed.";
}
}
// Function to translate text nodes containing Chinese characters
private void translateTextNodes(Node node,String targetLanguage) {
if (node.getNodeType() == Node.TEXT_NODE) {
// Extract Chinese text from the node's value
String chineseText = extractChineseText(node.getNodeValue());
if (!chineseText.isEmpty()) {
// Translate Chinese text using Tencent Cloud Translate API
String translatedText = translateText(chineseText,targetLanguage);
// Replace Chinese text with translated text
node.setNodeValue(node.getNodeValue().replace(chineseText, translatedText));
}
} else if (node.hasChildNodes()) {
// Recursively translate child nodes
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
translateTextNodes(children.item(i),targetLanguage);
}
}
}
// Function to extract Chinese text from a string
private String extractChineseText(String text) {
StringBuilder chineseText = new StringBuilder();
Pattern pattern = Pattern.compile("[\\u4E00-\\u9FA5]+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
chineseText.append(matcher.group());
}
return chineseText.toString();
}
// Function to translate text using Tencent Cloud Translate API
private String translateText(String text,String targetLanguage) {
try {
Credential cred = new Credential(SECRET_ID, SECRET_KEY);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("tmt.tencentcloudapi.com");
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
TmtClient client = new TmtClient(cred, "ap-guangzhou", clientProfile);
TextTranslateRequest req = new TextTranslateRequest();
req.setSourceText(text);
req.setSource("auto");
req.setTarget(targetLanguage);
req.setProjectId(0L);
TextTranslateResponse resp = client.TextTranslate(req);
return resp.getTargetText();
} catch (Exception e) {
e.printStackTrace();
return "Translation failed.";
}
}
}
thymeleaf文件代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>XML Translator</title>
<style>
body {
font-family: Arial, sans-serif;
}
h1 {
margin-bottom: 20px;
}
.container {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.preview {
flex: 1;
margin-right: 20px;
}
pre {
width: 100%;
height: 300px;
border: 1px solid #ccc;
padding: 10px;
box-sizing: border-box;
overflow: auto;
white-space: pre-wrap;
}
.highlight {
background-color: #FFCCCC;
}
.button {
margin-top: 10px;
padding: 8px 16px;
font-size: 16px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
position: relative;
}
.button:hover {
background-color: #45a049;
}
.loading {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9999;
}
</style>
</head>
<body>
<h1>XML Translator</h1>
<div class="overlay" id="overlay"></div>
<form id="uploadForm" action="/translate" method="post" enctype="multipart/form-data">
<label for="file">Upload XML File:</label>
<input type="file" id="file" name="file" accept=".xml"><br><br>
<label for="targetLanguage">Translate to:</label>
<select id="targetLanguage">
<option value="en">English</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="fr">French</option>
<option value="ms">Malay</option>
</select>
<button type="submit" class="button">Translate</button>
<img src="https://img.zcool.cn/community/01e1f35ad46d23a8012040293d688a.gif" alt="Loading..." class="loading" id="loadingIcon">
</form>
<p class="loading" id="loadingText">正在努力翻译中...</p>
<div class="container">
<div class="preview">
<h2>Original XML Content:</h2>
<pre id="originalContent"></pre>
</div>
<div class="preview">
<h2>Translated XML Content:</h2>
<pre id="translatedContent"></pre>
<button id="downloadBtn" class="button">Download Translated XML</button>
</div>
</div>
<script>
// Display original XML content
function displayOriginalContent(file) {
var reader = new FileReader();
reader.onload = function(event) {
document.getElementById('originalContent').textContent = event.target.result;
};
reader.readAsText(file);
}
// Display translated XML content
function displayTranslatedContent(xml) {
document.getElementById('translatedContent').textContent = xml;
}
// Highlight translated text
function highlightTranslatedText() {
var originalContent = document.getElementById('originalContent').textContent;
var translatedContent = document.getElementById('translatedContent').textContent;
var originalLines = originalContent.split('\n');
var translatedLines = translatedContent.split('\n');
for (var i = 0; i < originalLines.length; i++) {
if (originalLines[i] !== translatedLines[i]) {
var originalWords = originalLines[i].split(' ');
var translatedWords = translatedLines[i].split(' ');
var highlightedWords = [];
for (var j = 0; j < originalWords.length; j++) {
if (originalWords[j] !== translatedWords[j]) {
highlightedWords.push('<span class="red-text">' + translatedWords[j] + '</span>');
} else {
highlightedWords.push(translatedWords[j]);
}
}
translatedLines[i] = highlightedWords.join(' ');
}
}
document.getElementById('translatedContent').innerHTML = translatedLines.join('\n');
}
// Function to download translated XML
function downloadTranslatedXML(xml) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(xml));
element.setAttribute('download', 'translated.xml');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// Show loading overlay
function showLoadingOverlay() {
document.getElementById('overlay').style.display = 'block';
document.getElementById('loadingIcon').style.display = 'block';
document.getElementById('loadingText').style.display = 'block';
}
// Hide loading overlay
function hideLoadingOverlay() {
document.getElementById('overlay').style.display = 'none';
document.getElementById('loadingIcon').style.display = 'none';
document.getElementById('loadingText').style.display = 'none';
}
// Event listener for form submission
document.getElementById('uploadForm').addEventListener('submit', function(event) {
event.preventDefault();
var file = document.getElementById('file').files[0];
displayOriginalContent(file);
showLoadingOverlay();
var formData = new FormData();
formData.append('file', file);
formData.append('targetLanguage', document.getElementById('targetLanguage').value);
fetch('/translate', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(data => {
displayTranslatedContent(data);
highlightTranslatedText();
downloadTranslatedXML(data);
hideLoadingOverlay();
})
.catch(error => {
console.error('Error:', error);
hideLoadingOverlay();
});
});
// Event listener for download button
document.getElementById('downloadBtn').addEventListener('click', function() {
var translatedXml = document.getElementById('translatedContent').textContent;
downloadTranslatedXML(translatedXml);
});
</script>
</body>
</html>