Implementing Real-Time Website Translation Using jQuery and Baidu Translate API
Front-end Structure
To enable dynamic translation, markup elements that require localization with a specific class and store their unique identifiers in data attributes. A dropdown menu allows users to switch between languages.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dynamic Localization Demo</title>
</head>
<body>
<!-- Localizable Content -->
<h1 class="translate-node" data-msg-id="header">Hello, welcome to our service!</h1>
<p class="translate-node" data-msg-id="description">This content can be translated dynamically using the Baidu API.</p>
<button class="translate-node" data-msg-id="actionBtn">Learn More</button>
<!-- Language Selection Dropdown -->
<div style="margin-top: 20px;">
<label for="langSelector">Select Language: </label>
<select id="langSelector">
<option value="en">English</option>
<option value="zh">Chinese (Simplified)</option>
<option value="jp">Japanese</option>
<option value="kor">Korean</option>
</select>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="./hash-utils.js"></script>
<script src="./app-translator.js"></script>
</body>
</html>
Translation Logic with jQuery
The following script listens for changes in the dropdown menu, iterates through all element marked for translation, and updates their text content by calling the Baidu Translate service.
$(document).ready(function () {
const $selector = $('#langSelector');
$selector.on('change', function () {
const targetLang = $(this).val();
processTranslation(targetLang);
});
});
/**
* Scans the DOM for translatable elements and updates them.
* @param {string} langCode - The target language code (e.g., 'zh', 'en').
*/
function processTranslation(langCode) {
$('.translate-node').each(function () {
const $element = $(this);
const rawText = $element.text();
fetchBaiduTranslation(rawText, langCode)
.then(translated => {
$element.text(translated);
})
.catch(err => {
console.error("Translation Error:", err);
});
});
}
/**
* Handles the API request to Baidu Translate.
* @param {string} query - The text to translate.
* @param {string} destLang - The target language.
*/
function fetchBaiduTranslation(query, destLang) {
return new Promise((resolve, reject) => {
const config = {
appId: 'YOUR_APP_ID',
secretKey: 'YOUR_SECRET_KEY',
endpoint: 'http://api.fanyi.baidu.com/api/trans/vip/translate'
};
const salt = Date.now();
const fromLang = 'auto';
// Construct signature: appId + query + salt + secretKey
const signature = CryptoUtils.md5(config.appId + query + salt + config.secretKey);
$.ajax({
url: config.endpoint,
type: 'GET',
dataType: 'jsonp',
data: {
q: query,
appid: config.appId,
salt: salt,
from: fromLang,
to: destLang,
sign: signature
},
success: (response) => {
if (response.trans_result && response.trans_result.length > 0) {
resolve(response.trans_result[0].dst);
} else {
reject(response.error_msg || 'Unknown error');
}
},
error: (xhr, status, error) => {
reject(error);
}
});
});
}
MD5 Utility Implementation
Baidu's API security requires an MD5 signtaure. Below is a encapsulated utility to handle string hashing and UTF-8 encoding.
const CryptoUtils = (function () {
function rotateLeft(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
function addUnsigned(lX, lY) {
const lX8 = (lX & 0x80000000);
const lY8 = (lY & 0x80000000);
const lX4 = (lX & 0x40000000);
const lY4 = (lY & 0x40000000);
const lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
return (lResult & 0x40000000) ? (lResult ^ 0xC0000000 ^ lX8 ^ lY8) : (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ lX8 ^ lY8);
}
}
function md5(string) {
let x = [];
let k, AA, BB, CC, DD, a, b, c, d;
const S11 = 7, S12 = 12, S13 = 17, S14 = 22;
const S21 = 5, S22 = 9, S23 = 14, S24 = 20;
const S31 = 4, S32 = 11, S33 = 16, S34 = 23;
const S41 = 6, S42 = 10, S43 = 15, S44 = 21;
function F(x, y, z) { return (x & y) | ((~x) & z); }
function G(x, y, z) { return (x & z) | (y & (~z)); }
function H(x, y, z) { return (x ^ y ^ z); }
function I(x, y, z) { return (y ^ (x | (~z))); }
function FF(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
}
function GG(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
}
function HH(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
}
function II(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
}
const utf8String = unescape(encodeURIComponent(string));
const lMessageLength = utf8String.length;
const lNumberOfWords_temp1 = lMessageLength + 8;
const lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
const lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
let lWordArray = Array(lNumberOfWords - 1);
let lBytePosition = 0;
let lByteCount = 0;
while (lByteCount < lMessageLength) {
const lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (utf8String.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
const lWordCountFinal = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCountFinal] = lWordArray[lWordCountFinal] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
x = lWordArray;
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k = 0; k < x.length; k += 16) {
AA = a; BB = b; CC = c; DD = d;
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
// ... (rest of MD5 rounds omitted for brevity but required for full logic)
a = addUnsigned(a, AA); b = addUnsigned(b, BB); c = addUnsigned(c, CC); d = addUnsigned(d, DD);
}
const wordToHex = (lValue) => {
let hex = "";
for (let i = 0; i <= 3; i++) {
let byte = (lValue >>> (i * 8)) & 255;
hex += ("0" + byte.toString(16)).slice(-2);
}
return hex;
};
return (wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d)).toLowerCase();
}
return { md5 };
})();
```",
"tags": ["jQuery", "JavaScript", "Baidu Translate API", "Front-end Development", "MD5", "Localization"]
}