Skip to content

Commit 8094a54

Browse files
Support for custom callback when using raw objects
The method that replace the localized tags by the texts defined inside of a raw object did not consider any of the possible options you could receive as a second parameter in a 'localize' call. The 'callback' option is now supported. The 'data' object will be converted to a valid json object before calling the default callback, so if the user sets any of the data properties to a function, the elements for which the 'data-localize' attribute references any of those invalid property values will not be updated. The 'localize_test.coffee' file do now include new methods to test the new functionality. The 'localize_from_object.html' has been also updated and seems to be working as expected in the following browsers: - Google Chrome (59.0.3071.115) - Mozilla Firefox (45.0, 47.0.1) - Microsoft Edge (40.15063.0.0)
1 parent 71cd51a commit 8094a54

6 files changed

+107
-18
lines changed

dist/jquery.localize.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ http://keith-wood.name/localisation.html
1818
};
1919
$.defaultLanguage = normaliseLang(navigator.languages && navigator.languages.length > 0 ? navigator.languages[0] : navigator.language || navigator.userLanguage);
2020
$.localize = function(pkg, options) {
21-
var defaultCallback, deferred, fileExtension, intermediateLangData, jsonCall, loadLanguage, localizeElement, localizeForSpecialKeys, localizeImageElement, localizeInputElement, localizeOptgroupElement, notifyDelegateLanguageLoaded, regexify, setAttrFromValueForKey, setTextFromValueForKey, useFileAsDataSource, useObjectAsDataSource, valueForKey, wrappedSet;
21+
var defaultCallback, deferred, fileExtension, intermediateLangData, jsonCall, loadLanguage, localizeElement, localizeForSpecialKeys, localizeImageElement, localizeInputElement, localizeOptgroupElement, notifyDelegateLanguageLoaded, regexify, sanitizedCallback, setAttrFromValueForKey, setTextFromValueForKey, useFileAsDataSource, useObjectAsDataSource, valueForKey, wrappedSet;
2222
if (options == null) {
2323
options = {};
2424
}
@@ -189,10 +189,17 @@ http://keith-wood.name/localisation.html
189189
return loadLanguage(filename, lang, 1);
190190
}
191191
};
192-
useObjectAsDataSource = function(object) {
192+
sanitizedCallback = function(object) {
193193
var data;
194194
data = JSON.parse(JSON.stringify(object));
195-
defaultCallback(data);
195+
return defaultCallback(data);
196+
};
197+
useObjectAsDataSource = function(object) {
198+
if (options.callback != null) {
199+
options.callback(object, sanitizedCallback);
200+
} else {
201+
sanitizedCallback(object);
202+
}
196203
return deferred.resolve();
197204
};
198205
if (typeof pkg === "object") {

dist/jquery.localize.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/localize_from_object.html

+13-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ <h1>Test localization...</h1>
2424
Ruby image should be round.
2525
</p>
2626
<p data-localize="basic">It failed :(</p>
27+
<p data-localize="message">Optional callback never happened.</p>
28+
2729
<p data-localize="function">This text should remain unchanged</p>
30+
<input data-localize="function" type="text" value="fixed value" readonly />
31+
<input data-localize="added_function" type="text" value="fixed value" readonly />
32+
2833
<script type="text/javascript" charset="utf-8">
2934
$(function(){
3035
var object = {
@@ -55,7 +60,14 @@ <h1>Test localization...</h1>
5560
"function": function () {}
5661
};
5762

58-
$("[data-localize]").localize(object);
63+
var customCallback = function(data, defaultCallback) {
64+
data.message = "Optional call back works.";
65+
data.added_function = function () {};
66+
defaultCallback(data);
67+
};
68+
69+
var opts = { callback: customCallback };
70+
$("[data-localize]").localize(object, opts);
5971
})
6072
</script>
6173
</body>

src/jquery.localize.coffee

+10-4
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,18 @@ do ($ = jQuery) ->
144144
else
145145
loadLanguage(filename, lang, 1)
146146

147-
# Retrieve translations from an object
148-
useObjectAsDataSource = (object) ->
149-
# We stringify and parse the received object to ensure the object is a valid json
150-
# Any functions defined within the object will be removed during this process
147+
# We stringify and parse the received object to ensure the object is a valid json
148+
# Any functions defined within the object will be removed during this process
149+
sanitizedCallback = (object) ->
151150
data = JSON.parse(JSON.stringify(object))
152151
defaultCallback(data)
152+
153+
# Retrieve translations from an object
154+
useObjectAsDataSource = (object) ->
155+
if options.callback?
156+
options.callback(object, sanitizedCallback)
157+
else
158+
sanitizedCallback(object)
153159
deferred.resolve()
154160

155161
# If 'pkg' is an object, use it as the source for translations

test/localize_test.coffee

+29-5
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,37 @@ do ($ = jQuery) ->
208208
module "Using object as data source"
209209

210210
asyncTest "basic tag text substitution using object as data source", (assert) ->
211-
obj = { "basic": "basic success" }
211+
obj = basic: "basic success"
212212
t = localizableTagWithRel("p", "basic", text: "basic fail")
213213
t.localize(obj).localizePromise.then ->
214214
assert.equal t.text(), "basic success"
215215

216-
asyncTest "don't replace tag text if matching object property contains a function", (assert) ->
217-
obj = { "function": (->) }
218-
t = localizableTagWithRel("p", "function", text: "This text should remain unchanged")
216+
asyncTest "custom callback is fired when object is used as data source", (assert) ->
217+
opts = {}
218+
opts.callback = (data, defaultCallback) ->
219+
data.custom_callback = "custom callback success"
220+
defaultCallback(data)
221+
t = localizableTagWithRel("p", "custom_callback", text: "custom callback fail")
222+
t.localize({}, opts).localizePromise.then ->
223+
assert.equal t.text(), "custom callback success"
224+
225+
asyncTest "tag text must not be replaced if matching object property contains a function", (assert) ->
226+
obj = "function": (->)
227+
t = localizableTagWithRel("p", "function", text: "this text should remain unchanged")
219228
t.localize(obj).localizePromise.then ->
220-
assert.equal t.text(), "This text should remain unchanged"
229+
assert.equal t.text(), "this text should remain unchanged"
230+
231+
asyncTest "input value must not be replaced if matching object property contains a function", (assert) ->
232+
obj = "function": (->)
233+
t = localizableTagWithRel("input", "function", text: "remain after default callback")
234+
t.localize(obj).localizePromise.then ->
235+
assert.equal t.text(), "remain after default callback"
236+
237+
asyncTest "input value must not be replaced if custom callback introduced a matching property that contains a function", (assert) ->
238+
opts = {}
239+
opts.callback = (data, defaultCallback) ->
240+
data.added_function = (->)
241+
defaultCallback(data)
242+
t = localizableTagWithRel("input", "added_function", text: "remain after custom callback")
243+
t.localize({}, opts).localizePromise.then ->
244+
assert.equal t.text(), "remain after custom callback"

test/localize_test.js

+44-4
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@
366366
asyncTest("basic tag text substitution using object as data source", function(assert) {
367367
var obj, t;
368368
obj = {
369-
"basic": "basic success"
369+
basic: "basic success"
370370
};
371371
t = localizableTagWithRel("p", "basic", {
372372
text: "basic fail"
@@ -375,16 +375,56 @@
375375
return assert.equal(t.text(), "basic success");
376376
});
377377
});
378-
return asyncTest("don't replace tag text if matching object property contains a function", function(assert) {
378+
asyncTest("custom callback is fired when object is used as data source", function(assert) {
379+
var opts, t;
380+
opts = {};
381+
opts.callback = function(data, defaultCallback) {
382+
data.custom_callback = "custom callback success";
383+
return defaultCallback(data);
384+
};
385+
t = localizableTagWithRel("p", "custom_callback", {
386+
text: "custom callback fail"
387+
});
388+
return t.localize({}, opts).localizePromise.then(function() {
389+
return assert.equal(t.text(), "custom callback success");
390+
});
391+
});
392+
asyncTest("tag text must not be replaced if matching object property contains a function", function(assert) {
379393
var obj, t;
380394
obj = {
381395
"function": (function() {})
382396
};
383397
t = localizableTagWithRel("p", "function", {
384-
text: "This text should remain unchanged"
398+
text: "this text should remain unchanged"
399+
});
400+
return t.localize(obj).localizePromise.then(function() {
401+
return assert.equal(t.text(), "this text should remain unchanged");
402+
});
403+
});
404+
asyncTest("input value must not be replaced if matching object property contains a function", function(assert) {
405+
var obj, t;
406+
obj = {
407+
"function": (function() {})
408+
};
409+
t = localizableTagWithRel("input", "function", {
410+
text: "remain after default callback"
385411
});
386412
return t.localize(obj).localizePromise.then(function() {
387-
return assert.equal(t.text(), "This text should remain unchanged");
413+
return assert.equal(t.text(), "remain after default callback");
414+
});
415+
});
416+
return asyncTest("input value must not be replaced if custom callback introduced a matching property that contains a function", function(assert) {
417+
var opts, t;
418+
opts = {};
419+
opts.callback = function(data, defaultCallback) {
420+
data.added_function = (function() {});
421+
return defaultCallback(data);
422+
};
423+
t = localizableTagWithRel("input", "added_function", {
424+
text: "remain after custom callback"
425+
});
426+
return t.localize({}, opts).localizePromise.then(function() {
427+
return assert.equal(t.text(), "remain after custom callback");
388428
});
389429
});
390430
})(jQuery);

0 commit comments

Comments
 (0)