/**
|
* Simple I18n Helper for Layui/jQuery projects
|
*/
|
var I18n = (function() {
|
var lang = localStorage.getItem('lang') || 'zh-cn'; // Default to zh-cn
|
var messages = {};
|
var isReady = false;
|
|
function loadLanguage(language, callback) {
|
// Auto-detect path based on script location
|
var path = '';
|
var scripts = document.getElementsByTagName('script');
|
for (var i = 0; i < scripts.length; i++) {
|
if (scripts[i].src && scripts[i].src.indexOf('i18n-helper.js') !== -1) {
|
var src = scripts[i].src;
|
// Assuming structure: .../static/js/i18n/i18n-helper.js
|
// We want: .../static/i18n/
|
var jsI18nDir = src.substring(0, src.lastIndexOf('/')); // .../static/js/i18n
|
var jsDir = jsI18nDir.substring(0, jsI18nDir.lastIndexOf('/')); // .../static/js
|
var staticDir = jsDir.substring(0, jsDir.lastIndexOf('/')); // .../static
|
path = staticDir + '/i18n/' + language + '.json';
|
break;
|
}
|
}
|
|
// Fallback if script tag detection fails
|
if (!path) {
|
if (typeof baseUrl !== 'undefined') {
|
path = baseUrl + '/static/i18n/' + language + '.json';
|
} else {
|
path = '../../static/i18n/' + language + '.json';
|
}
|
}
|
|
// Add timestamp to prevent caching
|
path += '?t=' + new Date().getTime();
|
|
$.getJSON(path, function(data) {
|
messages = data;
|
isReady = true;
|
if (callback) callback();
|
updatePage();
|
$(document).trigger('i18n:ready');
|
$(document).trigger('i18n:updated');
|
$(document).trigger('i18n:languageChanged');
|
}).fail(function(jqxhr, textStatus, error) {
|
console.error('Failed to load language file: ' + path + ', error: ' + error);
|
// Even if failed, mark as ready so dependent scripts can proceed (using keys or defaults)
|
isReady = true;
|
$(document).trigger('i18n:ready');
|
$(document).trigger('i18n:updated');
|
});
|
}
|
|
// Listen for language changes from other tabs/frames
|
window.addEventListener('storage', function(e) {
|
if (e.key === 'lang' && e.newValue && e.newValue !== lang) {
|
lang = e.newValue;
|
loadLanguage(lang);
|
}
|
});
|
|
function t(key, params) {
|
var text = messages[key];
|
|
// Support nested keys (e.g. "form.select.noMatch") if not found directly
|
if (text === undefined && key.indexOf('.') !== -1) {
|
var parts = key.split('.');
|
var current = messages;
|
for (var i = 0; i < parts.length; i++) {
|
if (current[parts[i]] !== undefined) {
|
current = current[parts[i]];
|
} else {
|
current = undefined;
|
break;
|
}
|
}
|
if (current !== undefined && typeof current === 'string') {
|
text = current;
|
}
|
}
|
|
// Fallback to key if still not found
|
if (text === undefined) {
|
text = key;
|
}
|
|
if (params) {
|
for (var prop in params) {
|
text = text.replace(new RegExp('{{' + prop + '}}', 'g'), params[prop]);
|
}
|
}
|
return text;
|
}
|
|
function updatePage(root) {
|
var $root = root ? $(root) : $('body');
|
|
$root.find('[data-i18n]').each(function() {
|
var key = $(this).attr('data-i18n');
|
if (!key) return;
|
|
var attr = $(this).attr('data-i18n-attr');
|
var text = t(key);
|
|
if (attr) {
|
$(this).attr(attr, text);
|
} else if (this.tagName === 'INPUT' || this.tagName === 'TEXTAREA') {
|
$(this).attr('placeholder', text);
|
} else {
|
$(this).text(text);
|
}
|
});
|
|
// Handle data-i18n-placeholder
|
$root.find('[data-i18n-placeholder]').each(function() {
|
var key = $(this).attr('data-i18n-placeholder');
|
if (!key) return;
|
var text = t(key);
|
$(this).attr('placeholder', text);
|
});
|
|
// Handle data-i18n-lay-tips
|
$root.find('[data-i18n-lay-tips]').each(function() {
|
var key = $(this).attr('data-i18n-lay-tips');
|
if (!key) return;
|
var text = t(key);
|
$(this).attr('lay-tips', text);
|
});
|
|
// Trigger a custom event for JS to listen to if needed (only if full page update)
|
if (!root) {
|
$(document).trigger('i18n:updated');
|
}
|
}
|
|
function setLanguage(language) {
|
lang = language;
|
localStorage.setItem('lang', language);
|
loadLanguage(language);
|
}
|
|
function getLanguage() {
|
return lang;
|
}
|
|
function checkReady() {
|
return isReady;
|
}
|
|
// Initialize
|
$(document).ready(function() {
|
loadLanguage(lang);
|
});
|
|
// Listen for storage changes (for syncing across tabs/frames)
|
window.addEventListener('storage', function(e) {
|
if (e.key === 'lang' && e.newValue && e.newValue !== lang) {
|
lang = e.newValue;
|
loadLanguage(lang);
|
}
|
});
|
|
function updateLayuiPagination() {
|
// Update 'Total X items'
|
$('.layui-laypage-count').each(function() {
|
var text = $(this).text();
|
var count = text.match(/\d+/);
|
if (count) {
|
$(this).text(t('total_prefix') + count[0] + t('total_suffix'));
|
}
|
});
|
|
// Update 'Go to [input] page [button]'
|
$('.layui-laypage-skip').each(function() {
|
var $this = $(this);
|
|
// Iterate over all child nodes to find text nodes containing specific keywords
|
$this.contents().each(function() {
|
if (this.nodeType === 3) { // Text node
|
var text = this.textContent;
|
// Replace "到第" or "Go to"
|
if (text.indexOf('到第') !== -1 || text.indexOf('Go to') !== -1) {
|
this.textContent = t('jump_to');
|
}
|
// Replace "页" or "page" (but excluding "items/page" if somehow mixed, though usually that's in select)
|
else if (text.indexOf('页') !== -1 || (text.indexOf('page') !== -1 && text.indexOf('items/page') === -1)) {
|
this.textContent = t('page');
|
}
|
}
|
});
|
|
// Replace Button text
|
var btn = $this.find('.layui-laypage-btn');
|
if (btn.length) {
|
btn.text(t('confirm'));
|
}
|
});
|
|
// Update 'X items/page'
|
$('.layui-laypage-limits select option').each(function() {
|
var text = $(this).text();
|
var limit = text.match(/\d+/);
|
if (limit) {
|
var newText = limit[0] + t('items_per_page');
|
$(this).text(newText);
|
|
// If this is the selected option, update the custom Layui select input if present
|
if ($(this).is(':selected')) {
|
var $select = $(this).parent();
|
var $layuiSelect = $select.next('.layui-form-select');
|
if ($layuiSelect.length) {
|
$layuiSelect.find('.layui-select-title input').val(newText);
|
}
|
}
|
}
|
});
|
|
// Also update the dd options in the custom select (if Layui rendered it)
|
$('.layui-laypage-limits .layui-form-select dl dd').each(function() {
|
var text = $(this).text();
|
var limit = text.match(/\d+/);
|
if (limit) {
|
$(this).text(limit[0] + t('items_per_page'));
|
}
|
});
|
}
|
|
return {
|
t: t,
|
setLanguage: setLanguage,
|
getLanguage: getLanguage,
|
updatePage: updatePage,
|
updateLayuiPagination: updateLayuiPagination,
|
isReady: checkReady
|
};
|
})();
|