blob: 2252c770fc362960fec8912636a0592e67cd2ab8 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 * jquery.i18n.properties
3 *
4 * Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
5 * MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
6 *
7 * @version 1.0.x
8 * @author Nuno Fernandes
9 * @url www.codingwithcoffee.com
10 * @inspiration Localisation assistance for jQuery (http://keith-wood.name/localisation.html)
11 * by Keith Wood (kbwood{at}iinet.com.au) June 2007
12 *
13 *****************************************************************************/
14
15(function($) {
16$.i18n = {};
17
18/** Map holding bundle keys (if mode: 'map') */
19$.i18n.map = {};
20
21
22
23$.i18n.properties = function(settings) {
24 // set up settings
25 var defaults = {
26 name: 'Messages',
27 language: '',
28 path: '',
29 mode: 'vars',
30 callback: function(){}
31 };
32 settings = $.extend(defaults, settings);
33 if(settings.language === null || settings.language == '') {
34 settings.language = normaliseLanguageCode(navigator.language /* Mozilla */ || navigator.userLanguage /* IE */);
35 }
36 if(settings.language === null) {settings.language='';}
37
38 // load and parse bundle files
39 var files = getFiles(settings.name);
40 for(i=0; i<files.length; i++) {
41 // 1. load base (eg, Messages.properties)
42 //loadAndParseFile(settings.path + files[i] + '.properties', settings.language, settings.mode);
43 // 2. with language code (eg, Messages_pt.properties)
44 if(settings.language.length >= 2) {
45 loadAndParseFile(settings.path + files[i] + '_' + settings.language.substring(0, 2) +'.properties', settings.language, settings.mode);
46 }
47 // 3. with language code and country code (eg, Messages_pt_PT.properties)
48// if(settings.language.length >= 5) {
49// loadAndParseFile(settings.path + files[i] + '_' + settings.language.substring(0, 5) +'.properties', settings.language, settings.mode);
50// }
51 }
52
53 // call callback
54 if(settings.callback){ settings.callback(); }
55};
56
57
58/**
59 * When configured with mode: 'map', allows access to bundle values by specifying its key.
60 * Eg, jQuery.i18n.prop('com.company.bundles.menu_add')
61 */
62$.i18n.prop = function(key, placeHolderValues) {
63 var value = $.i18n.map[key];
64 if(value === null) { return key; }
65 if(!placeHolderValues) {
66 //if(key == 'spv.lbl.modified') {alert(value);}
67 return value;
68 }else{
69 for(var i=0; i<placeHolderValues.length; i++) {
70 var regexp = new RegExp('\\{('+i+')\\}', "g");
71 value = value.replace(regexp, placeHolderValues[i]);
72 }
73 return value;
74 }
75};
76
77
78/** Load and parse .properties files */
79function loadAndParseFile(filename, language, mode) {
80 $.ajax({
81 url: filename,
82 async: false,
83 contentType: "text/plain;charset=UTF-8",
84 dataType: 'text',
85 error: function(XMLHttpRequest, textStatus, errorThrown) {
86
87 loadAndParseFile(filename, language, mode);
88 },
89 success: function(data, status) {
90 var parsed = '';
91 var parameters = data.split( /\n/ );
92 var regPlaceHolder = /(\{\d+\})/g;
93 var regRepPlaceHolder = /\{(\d+)\}/g;
94 var unicodeRE = /(\\u.{4})/ig;
95 for(var i=0; i<parameters.length; i++ ) {
96 parameters[i] = parameters[i].replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); // trim
97 if(parameters[i].length > 0 && parameters[i].match("^#")!="#") { // skip comments
98 var pair = parameters[i].split('=');
99 if(pair.length > 0) {
100 /** Process key & value */
101 var name = unescape(pair[0]).replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); // trim
102 var value = pair.length == 1 ? "" : pair[1];
103 value = value.replace( /"/g, '\\"' ); // escape quotation mark (")
104 value = value.replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); // trim
105
106 /** Mode: bundle keys in a map */
107 if(mode == 'map' || mode == 'both') {
108 // handle unicode chars possibly left out
109 var unicodeMatches = value.match(unicodeRE);
110 if(unicodeMatches) {
111 for(var u=0; u<unicodeMatches.length; u++) {
112 value = value.replace( unicodeMatches[u], unescapeUnicode(unicodeMatches[u]));
113 }
114 }
115 // add to map
116 $.i18n.map[name] = value;
117 }
118
119 /** Mode: bundle keys as vars/functions */
120 if(mode == 'vars' || mode == 'both') {
121 // make sure namespaced key exists (eg, 'some.key')
122 checkKeyNamespace(name);
123
124 // value with variable substitutions
125 if(regPlaceHolder.test(value)) {
126 var parts = value.split(regPlaceHolder);
127 // process function args
128 var first = true;
129 var fnArgs = '';
130 var usedArgs = [];
131 for(var p=0; p<parts.length; p++) {
132 if(regPlaceHolder.test(parts[p]) && usedArgs.indexOf(parts[p]) == -1) {
133 if(!first) {fnArgs += ',';}
134 fnArgs += parts[p].replace(regRepPlaceHolder, 'v$1');
135 usedArgs.push(parts[p]);
136 first = false;
137 }
138 }
139 parsed += name + '=function(' + fnArgs + '){';
140 // process function body
141 var fnExpr = '"' + value.replace(regRepPlaceHolder, '"+v$1+"') + '"';
142 parsed += 'return ' + fnExpr + ';' + '};';
143
144 // simple value
145 }else{
146 parsed += name+'="'+value+'";';
147 }
148 }
149 }
150 }
151 }
152 eval(parsed);
153 }
154 });
155}
156
157/** Make sure namespace exists (for keys with dots in name) */
158function checkKeyNamespace(key) {
159 var regDot = /\./g;
160 if(regDot.test(key)) {
161 var fullname = '';
162 var names = key.split( /\./ );
163 for(var i=0; i<names.length; i++) {
164 if(i>0) {fullname += '.';}
165 fullname += names[i];
166 if(eval('typeof '+fullname+' == "undefined"')) {
167 eval(fullname + '={};');
168 }
169 }
170 }
171}
172
173/** Make sure filename is an array */
174function getFiles(names) {
175 return (names && names.constructor == Array) ? names : [names];
176}
177
178/** Ensure language code is in the format aa_AA. */
179function normaliseLanguageCode(lang) {
180 lang = lang.toLowerCase();
181 if(lang.length > 3) {
182 lang = lang.substring(0, 3) + lang.substring(3).toUpperCase();
183 }
184 return lang;
185}
186
187/** Unescape unicode chars ('\u00e3') */
188function unescapeUnicode(str) {
189 // unescape unicode codes
190 var codes = [];
191 var code = parseInt(str.substr(2), 16);
192 if (code >= 0 && code < Math.pow(2, 16)) {
193 codes.push(code);
194 }
195 // convert codes to text
196 var unescaped = '';
197 for (var i = 0; i < codes.length; ++i) {
198 unescaped += String.fromCharCode(codes[i]);
199 }
200 return unescaped;
201}
202
203})(jQuery);