利用jquery.i18n.properties实现前端网页国际化小示例(详细版)
文件目录结构:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery.i18n.properties Example</title>
<script src="./js/jquery.js"></script>
<script src="./js/jquery.i18n.properties.js"></script>
<script>
$(document).ready(function () {
// 加载属性文件
jQuery.i18n.properties({
name: 'messages', //属性文件名
path: 'i18n/', //属性文件路径
mode: 'map', //用map来存储属性值
language: 'zh', //默认语言
callback: function () {
// 设置页面上的文本
$('body').find('*').each(function () {
if ($(this).attr('data-i18n')) {
$(this).html($.i18n.prop($(this).attr('data-i18n')));
}
});
// $('body').i18n();
}
});
// 切换语言
$('#langSelect').change(function () {
var lang = $(this).val();
jQuery.i18n.properties({
name: 'messages',
path: 'i18n/',
mode: 'map',
language: lang,
callback: function () {
$('body').find('*').each(function () {
if ($(this).attr('data-i18n')) {
$(this).html($.i18n.prop($(this).attr('data-i18n')));
}
});
}
});
});
});
</script>
</head>
<body>
<!-- 语言选择器 -->
<select id="langSelect">
<option value="zh">中文</option>
<option value="en">English</option>
</select>
<!-- 显示文本的元素 -->
<h1 data-i18n="title">我是标题</h1>
<p data-i18n="description">我是标题描述</p>
<!-- <label for="name" data-i18n="inputLabel">
姓名
<input type="text" id="name" data-i18n="placeholder"/>
</label> -->
</body>
</html>
jquery.i18n.properties.js
访问jQuery.i18n.properties插件的官方GitHub仓库也可以自行下载:https://github.com/jquery-i18n-properties/jquery-i18n-properties
/******************************************************************************
* jquery.i18n.properties
*
* Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
* MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
*
* @version 1.2.7
* @url https://github.com/jquery-i18n-properties/jquery-i18n-properties
* @inspiration Localisation assistance for jQuery (http://keith-wood.name/localisation.html)
* by Keith Wood (kbwood{at}iinet.com.au) June 2007
*
*****************************************************************************/
(function ($) {
$.i18n = {};
/**
* Map holding bundle keys if mode is 'map' or 'both'. Values of this can also be an
* Object, in which case the key is a namespace.
*/
$.i18n.map = {};
var debug = function (message) {
window.console && console.log('i18n::' + message);
};
/**
* Load and parse message bundle files (.properties),
* making bundles keys available as javascript variables.
*
* i18n files are named <name>.js, or <name>_<language>.js or <name>_<language>_<country>.js
* Where:
* The <language> argument is a valid ISO Language Code. These codes are the lower-case,
* two-letter codes as defined by ISO-639. You can find a full list of these codes at a
* number of sites, such as: http://www.loc.gov/standards/iso639-2/englangn.html
* The <country> argument is a valid ISO Country Code. These codes are the upper-case,
* two-letter codes as defined by ISO-3166. You can find a full list of these codes at a
* number of sites, such as: http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html
*
* Sample usage for a bundles/Messages.properties bundle:
* $.i18n.properties({
* name: 'Messages',
* language: 'en_US',
* path: 'bundles'
* });
* @param name (string/string[], optional) names of file to load (eg, 'Messages' or ['Msg1','Msg2']). Defaults to "Messages"
* @param language (string, optional) language/country code (eg, 'en', 'en_US', 'pt_BR'). if not specified, language reported by the browser will be used instead.
* @param path (string, optional) path of directory that contains file to load
* @param mode (string, optional) whether bundles keys are available as JavaScript variables/functions or as a map (eg, 'vars' or 'map')
* @param debug (boolean, optional) whether debug statements are logged at the console
* @param cache (boolean, optional) whether bundles should be cached by the browser, or forcibly reloaded on each page load. Defaults to false (i.e. forcibly reloaded)
* @param encoding (string, optional) the encoding to request for bundles. Property file resource bundles are specified to be in ISO-8859-1 format. Defaults to UTF-8 for backward compatibility.
* @param callback (function, optional) callback function to be called after script is terminated
*/
$.i18n.properties = function (settings) {
var defaults = {
name: 'Messages',
language: '',
path: '',
namespace: null,
mode: 'vars',
cache: false,
debug: false,
encoding: 'UTF-8',
async: false,
callback: null
};
settings = $.extend(defaults, settings);
if (settings.namespace && typeof settings.namespace == 'string') {
// A namespace has been supplied, initialise it.
if (settings.namespace.match(/^[a-z]*$/)) {
$.i18n.map[settings.namespace] = {};
} else {
debug('Namespaces can only be lower case letters, a - z');
settings.namespace = null;
}
}
// Ensure a trailing slash on the path
if (!settings.path.match(/\/$/)) settings.path += '/';
// Try to ensure that we have at a least a two letter language code
settings.language = this.normaliseLanguageCode(settings);
// Ensure an array
var files = (settings.name && settings.name.constructor === Array) ? settings.name : [settings.name];
// A locale is at least a language code which means at least two files per name. If
// we also have a country code, thats an extra file per name.
settings.totalFiles = (files.length * 2) + ((settings.language.length >= 5) ? files.length : 0);
if (settings.debug) {
debug('totalFiles: ' + settings.totalFiles);
}
settings.filesLoaded = 0;
files.forEach(function (file) {
var defaultFileName, shortFileName, longFileName, fileNames;
// 1. load base (eg, Messages.properties)
defaultFileName = settings.path + file + '.properties';
// 2. with language code (eg, Messages_pt.properties)
var shortCode = settings.language.substring(0, 2);
shortFileName = settings.path + file + '_' + shortCode + '.properties';
// 3. with language code and country code (eg, Messages_pt_BR.properties)
if (settings.language.length >= 5) {
var longCode = settings.language.substring(0, 5);
longFileName = settings.path + file + '_' + longCode + '.properties';
fileNames = [defaultFileName, shortFileName, longFileName];
} else {
fileNames = [defaultFileName, shortFileName];
}
loadAndParseFiles(fileNames, settings);
});
// call callback
if (settings.callback && !settings.async) {
settings.callback();
}
}; // properties
/**
* When configured with mode: 'map', allows access to bundle values by specifying its key.
* Eg, jQuery.i18n.prop('com.company.bundles.menu_add')
*/
$.i18n.prop = function (key /* Add parameters as function arguments as necessary */) {
var args = [].slice.call(arguments);
var phvList, namespace;
if (args.length == 2) {
if ($.isArray(args[1])) {
// An array was passed as the second parameter, so assume it is the list of place holder values.
phvList = args[1];
} else if (typeof args[1] === 'object') {
// Second argument is an options object {namespace: 'mynamespace', replacements: ['egg', 'nog']}
namespace = args[1].namespace;
var replacements = args[1].replacements;
args.splice(-1, 1);
if (replacements) {
Array.prototype.push.apply(args, replacements);
}
}
}
var value = (namespace) ? $.i18n.map[namespace][key] : $.i18n.map[key];
if (value === null) {
return '[' + ((namespace) ? namespace + '#' + key : key) + ']';
}
// Place holder replacement
/**
* Tested with:
* test.t1=asdf ''{0}''
* test.t2=asdf '{0}' '{1}'{1}'zxcv
* test.t3=This is \"a quote" 'a''{0}''s'd{fgh{ij'
* test.t4="'''{'0}''" {0}{a}
* test.t5="'''{0}'''" {1}
* test.t6=a {1} b {0} c
* test.t7=a 'quoted \\ s\ttringy' \t\t x
*
* Produces:
* test.t1, p1 ==> asdf 'p1'
* test.t2, p1 ==> asdf {0} {1}{1}zxcv
* test.t3, p1 ==> This is "a quote" a'{0}'sd{fgh{ij
* test.t4, p1 ==> "'{0}'" p1{a}
* test.t5, p1 ==> "'{0}'" {1}
* test.t6, p1 ==> a {1} b p1 c
* test.t6, p1, p2 ==> a p2 b p1 c
* test.t6, p1, p2, p3 ==> a p2 b p1 c
* test.t7 ==> a quoted \ s tringy x
*/
var i;
if (typeof(value) == 'string') {
// Handle escape characters. Done separately from the tokenizing loop below because escape characters are
// active in quoted strings.
i = 0;
while ((i = value.indexOf('\\', i)) != -1) {
if (value.charAt(i + 1) == 't') {
value = value.substring(0, i) + '\t' + value.substring((i++) + 2); // tab
} else if (value.charAt(i + 1) == 'r') {
value = value.substring(0, i) + '\r' + value.substring((i++) + 2); // return
} else if (value.charAt(i + 1) == 'n') {
value = value.substring(0, i) + '\n' + value.substring((i++) + 2); // line feed
} else if (value.charAt(i + 1) == 'f') {
value = value.substring(0, i) + '\f' + value.substring((i++) + 2); // form feed
} else if (value.charAt(i + 1) == '\\') {
value = value.substring(0, i) + '\\' + value.substring((i++) + 2); // \
} else {
value = value.substring(0, i) + value.substring(i + 1); // Quietly drop the character
}
}
// Lazily convert the string to a list of tokens.
var arr = [], j, index;
i = 0;
while (i < value.length) {
if (value.charAt(i) == '\'') {
// Handle quotes
if (i == value.length - 1) {
value = value.substring(0, i); // Silently drop the trailing quote
} else if (value.charAt(i + 1) == '\'') {
value = value.substring(0, i) + value.substring(++i); // Escaped quote
} else {
// Quoted string
j = i + 2;
while ((j = value.indexOf('\'', j)) != -1) {
if (j == value.length - 1 || value.charAt(j + 1) != '\'') {
// Found start and end quotes. Remove them
value = value.substring(0, i) + value.substring(i + 1, j) + value.substring(j + 1);
i = j - 1;
break;
} else {
// Found a double quote, reduce to a single quote.
value = value.substring(0, j) + value.substring(++j);
}
}
if (j == -1) {
// There is no end quote. Drop the start quote
value = value.substring(0, i) + value.substring(i + 1);
}
}
} else if (value.charAt(i) == '{') {
// Beginning of an unquoted place holder.
j = value.indexOf('}', i + 1);
if (j == -1) {
i++; // No end. Process the rest of the line. Java would throw an exception
} else {
// Add 1 to the index so that it aligns with the function arguments.
index = parseInt(value.substring(i + 1, j));
if (!isNaN(index) && index >= 0) {
// Put the line thus far (if it isn't empty) into the array
var s = value.substring(0, i);
if (s !== "") {
arr.push(s);
}
// Put the parameter reference into the array
arr.push(index);
// Start the processing over again starting from the rest of the line.
i = 0;
value = value.substring(j + 1);
} else {
i = j + 1; // Invalid parameter. Leave as is.
}
}
} else {
i++;
}
} // while
// Put the remainder of the no-empty line into the array.
if (value !== "") {
arr.push(value);
}
value = arr;
// Make the array the value for the entry.
if (namespace) {
$.i18n.map[settings.namespace][key] = arr;
} else {
$.i18n.map[key] = arr;
}
}
if (value.length === 0) {
return "";
}
if (value.length == 1 && typeof(value[0]) == "string") {
return value[0];
}
var str = "";
for (i = 0, j = value.length; i < j; i++) {
if (typeof(value[i]) == "string") {
str += value[i];
} else if (phvList && value[i] < phvList.length) {
// Must be a number
str += phvList[value[i]];
} else if (!phvList && value[i] + 1 < args.length) {
str += args[value[i] + 1];
} else {
str += "{" + value[i] + "}";
}
}
return str;
};
function callbackIfComplete(settings) {
if (settings.debug) {
debug('callbackIfComplete()');
debug('totalFiles: ' + settings.totalFiles);
debug('filesLoaded: ' + settings.filesLoaded);
}
if (settings.async) {
if (settings.filesLoaded === settings.totalFiles) {
if (settings.callback) {
settings.callback();
}
}
}
}
function loadAndParseFiles(fileNames, settings) {
if (settings.debug) debug('loadAndParseFiles');
if (fileNames !== null && fileNames.length > 0) {
loadAndParseFile(fileNames[0], settings, function () {
fileNames.shift();
loadAndParseFiles(fileNames,settings);
});
} else {
callbackIfComplete(settings);
}
}
/** Load and parse .properties files */
function loadAndParseFile(filename, settings, nextFile) {
if (settings.debug) {
debug('loadAndParseFile(\'' + filename +'\')');
debug('totalFiles: ' + settings.totalFiles);
debug('filesLoaded: ' + settings.filesLoaded);
}
if (filename !== null && typeof filename !== 'undefined') {
$.ajax({
url: filename,
async: settings.async,
cache: settings.cache,
dataType: 'text',
success: function (data, status) {
if (settings.debug) {
debug('Succeeded in downloading ' + filename + '.');
debug(data);
}
parseData(data, settings);
nextFile();
},
error: function (jqXHR, textStatus, errorThrown) {
if (settings.debug) {
debug('Failed to download or parse ' + filename + '. errorThrown: ' + errorThrown);
}
if (jqXHR.status === 404) {
settings.totalFiles -= 1;
}
nextFile();
}
});
}
}
/** Parse .properties files */
function parseData(data, settings) {
var parsed = '';
var lines = data.split(/\n/);
var regPlaceHolder = /(\{\d+})/g;
var regRepPlaceHolder = /\{(\d+)}/g;
var unicodeRE = /(\\u.{4})/ig;
for (var i=0,j=lines.length;i<j;i++) {
var line = lines[i];
line = line.trim();
if (line.length > 0 && line.match("^#") != "#") { // skip comments
var pair = line.split('=');
if (pair.length > 0) {
/** Process key & value */
var name = decodeURI(pair[0]).trim();
var value = pair.length == 1 ? "" : pair[1];
// process multi-line values
while (value.search(/\\$/) != -1) {
value = value.substring(0, value.length - 1);
value += lines[++i].trimRight();
}
// Put values with embedded '='s back together
for (var s = 2; s < pair.length; s++) {
value += '=' + pair[s];
}
value = value.trim();
/** Mode: bundle keys in a map */
if (settings.mode == 'map' || settings.mode == 'both') {
// handle unicode chars possibly left out
var unicodeMatches = value.match(unicodeRE);
if (unicodeMatches) {
unicodeMatches.forEach(function (match) {
value = value.replace(match, unescapeUnicode(match));
});
}
// add to map
if (settings.namespace) {
$.i18n.map[settings.namespace][name] = value;
} else {
$.i18n.map[name] = value;
}
}
/** Mode: bundle keys as vars/functions */
if (settings.mode == 'vars' || settings.mode == 'both') {
value = value.replace(/"/g, '\\"'); // escape quotation mark (")
// make sure namespaced key exists (eg, 'some.key')
checkKeyNamespace(name);
// value with variable substitutions
if (regPlaceHolder.test(value)) {
var parts = value.split(regPlaceHolder);
// process function args
var first = true;
var fnArgs = '';
var usedArgs = [];
parts.forEach(function (part) {
if (regPlaceHolder.test(part) && (usedArgs.length === 0 || usedArgs.indexOf(part) == -1)) {
if (!first) {
fnArgs += ',';
}
fnArgs += part.replace(regRepPlaceHolder, 'v$1');
usedArgs.push(part);
first = false;
}
});
parsed += name + '=function(' + fnArgs + '){';
// process function body
var fnExpr = '"' + value.replace(regRepPlaceHolder, '"+v$1+"') + '"';
parsed += 'return ' + fnExpr + ';' + '};';
// simple value
} else {
parsed += name + '="' + value + '";';
}
} // END: Mode: bundle keys as vars/functions
} // END: if(pair.length > 0)
} // END: skip comments
}
eval(parsed);
settings.filesLoaded += 1;
}
/** Make sure namespace exists (for keys with dots in name) */
// TODO key parts that start with numbers quietly fail. i.e. month.short.1=Jan
function checkKeyNamespace(key) {
var regDot = /\./;
if (regDot.test(key)) {
var fullname = '';
var names = key.split(/\./);
for (var i=0,j=names.length;i<j;i++) {
var name = names[i];
if (i > 0) {
fullname += '.';
}
fullname += name;
if (eval('typeof ' + fullname + ' == "undefined"')) {
eval(fullname + '={};');
}
}
}
}
/** Ensure language code is in the format aa_AA. */
$.i18n.normaliseLanguageCode = function (settings) {
var lang = settings.language;
if (!lang || lang.length < 2) {
if (settings.debug) debug('No language supplied. Pulling it from the browser ...');
lang = (navigator.languages && navigator.languages.length > 0) ? navigator.languages[0]
: (navigator.language || navigator.userLanguage /* IE */ || 'en');
if (settings.debug) debug('Language from browser: ' + lang);
}
lang = lang.toLowerCase();
lang = lang.replace(/-/,"_"); // some browsers report language as en-US instead of en_US
if (lang.length > 3) {
lang = lang.substring(0, 3) + lang.substring(3).toUpperCase();
}
return lang;
};
/** Unescape unicode chars ('\u00e3') */
function unescapeUnicode(str) {
// unescape unicode codes
var codes = [];
var code = parseInt(str.substr(2), 16);
if (code >= 0 && code < Math.pow(2, 16)) {
codes.push(code);
}
// convert codes to text
return codes.reduce(function (acc, val) { return acc + String.fromCharCode(val); }, '');
}
}) (jQuery);
jquery.js就不贴出来了 需要自己官网找就行 我这里用的是 jQuery v3.2.1
jQuery.i18n.properties插件是一个基于jQuery的多语言国际化插件,兼容性与jQuery版本有一定的关系。以下是jQuery.i18n.properties插件兼容的jQuery版本:
jQuery 1.x系列:1.6.4及以上版本;
jQuery 2.x系列:2.1.4及以上版本;
jQuery 3.x系列:3.0.0及以上版本。
建议使用最新版本的jQuery和jQuery.i18n.properties插件以获得最好的兼容性和性能。同时,也要注意不要与其他的jQuery插件或框架产生冲突。
messages_en.properties
title=title
description=titledescription
inputLabel=name
messages_zh.properties
title=我是标题
description=我是标题描述
inputLabel=姓名
以上就是代码和目录结构啦
但是你肯定目前还是运行不了的,肯定报跨域了,这就得下载nginx并且配置nginx了,放心吧,都给你准备好了
下载nginx后将文件放在这个位置
然后配置nginx,
找到这个位置 打开圈画的文件 打开将下面代码全部粘贴进去
add_header ‘Access-Control-Allow-Origin’ ‘*’;
这句画重点
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html/aaa;
index index.html index.htm;
autoindex on;
add_header 'Access-Control-Allow-Origin' '*';
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
然后双击启动服务
最后浏览器输入localhost就OK了
来吧展示:
但是有个问题研究了半天没搞好,谁知道怎么转换input的placeholder或者value吗?哪位大佬知道麻烦下面评论!