Skip to content

Commit 319da36

Browse files
committed
Support for nested messages.
1 parent e16acc1 commit 319da36

File tree

5 files changed

+70
-67
lines changed

5 files changed

+70
-67
lines changed

js/lang.js

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
define([], factory);
1717
} else if (typeof exports === 'object') {
1818
// NodeJS support.
19-
module.exports = new (factory())();
19+
module.exports = new(factory())();
2020
} else {
2121
// Browser global support.
22-
root.Lang = new (factory())();
22+
root.Lang = new(factory())();
2323
}
2424

2525
}(this, function() {
@@ -28,7 +28,7 @@
2828

2929
var defaults = {
3030
defaultLocale: 'en' /** The default locale if not set. */
31-
}
31+
};
3232

3333
// Constructor //
3434

@@ -59,10 +59,20 @@
5959
* @return {string} The translation message, if not found the given key.
6060
*/
6161
Lang.prototype.get = function(key, replacements) {
62-
if (typeof key !== 'string' || !this.has(key)) {
62+
if (!this.has(key)) {
63+
return key;
64+
}
65+
66+
var message = this._getMessage(key, replacements);
67+
if (message === null) {
6368
return key;
6469
}
65-
return this.getMessage(key, replacements);
70+
71+
if (replacements) {
72+
message = this._applyReplacements(message, replacements);
73+
}
74+
75+
return message;
6676
};
6777

6878
/**
@@ -76,9 +86,7 @@
7686
if (typeof key !== 'string' || !this.messages) {
7787
return false;
7888
}
79-
var message = this._getMessage(key);
80-
81-
return message !== undefined && typeof message === "string";
89+
return this._getMessage(key) !== null;
8290
};
8391

8492
/**
@@ -106,57 +114,58 @@
106114
*
107115
* @param key {string} The message key to parse.
108116
*
109-
* @return {object} A key object with main and sub properties.
117+
* @return {object} A key object with source and entries properties.
110118
*/
111-
Lang.prototype.parseKey = function(key) {
119+
Lang.prototype._parseKey = function(key) {
112120
if (typeof key !== 'string') {
113121
return null;
114122
}
115123
var segments = key.split('.');
116-
var main = this.getLocale() + '\\' + segments.shift();
117-
118124
return {
119-
main: main,
120-
sub: segments
125+
source: this.getLocale() + '.' + segments[0],
126+
entries: segments.slice(1)
121127
};
122128
};
123129

124130
/**
125131
* Returns a translation message. Use `Lang.get()` method instead, this methods assumes the key exists.
126132
*
127133
* @param key {string} The key of the message.
128-
* @param replacements {object} The replacements to be done in the message.
129134
*
130135
* @return {string} The translation message for the given key.
131136
*/
132-
Lang.prototype.getMessage = function(key, replacements) {
133-
var message = this._getMessage(key);
137+
Lang.prototype._getMessage = function(key) {
134138

135-
for (var replace in replacements) {
136-
message = message.split(':' + replace).join(replacements[replace]);
139+
key = this._parseKey(key);
140+
141+
// Ensure message source exists.
142+
if (this.messages[key.source] === undefined) {
143+
return null;
144+
}
145+
146+
// Get message text.
147+
var message = this.messages[key.source];
148+
while (key.entries.length && (message = message[key.entries.shift()]));
149+
150+
if (typeof message !== 'string') {
151+
return null;
137152
}
138153

139154
return message;
140155
};
141-
142-
/**
143-
* Get nested message.
156+
157+
/**
158+
* Apply replacements to a string message containing placeholders.
144159
*
145-
* @param key
146-
* @returns {*}
147-
* @private
160+
* @param message {string} The text message.
161+
* @param replacements {object} The replacements to be done in the message.
162+
*
163+
* @return {string} The string message with replacements applied.
148164
*/
149-
Lang.prototype._getMessage = function (key) {
150-
key = this.parseKey(key);
151-
152-
var length = key.sub.length,
153-
message = this.messages[key.main],
154-
i;
155-
156-
for ( i = 0; i < length; i++ ) {
157-
message = message[key.sub[i]];
165+
Lang.prototype._applyReplacements = function(message, replacements) {
166+
for (var replace in replacements) {
167+
message = message.split(':' + replace).join(replacements[replace]);
158168
}
159-
160169
return message;
161170
};
162171

tests/lang/en/messages.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,12 @@
3636
'language' => 'Language',
3737
'settingsSaved' => 'Settings saved successfully!',
3838

39+
'family' => array(
40+
'father' => 'John',
41+
'mother' => 'Susan',
42+
'children' => array(
43+
'son' => 'Jimmy',
44+
),
45+
),
46+
3947
);

tests/spec/data/messages.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,14 @@
9797
"settings": "Settings",
9898
"save": "Save",
9999
"language": "Language",
100-
"settingsSaved": "Settings saved successfully!"
100+
"settingsSaved": "Settings saved successfully!",
101+
"family": {
102+
"father": "John",
103+
"mother": "Susan",
104+
"children": {
105+
"son": "Jimmy"
106+
}
107+
}
101108
},
102109
"en.pagination": {
103110
"previous": "&laquo; Previous",

tests/spec/lang_get_spec.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ describe('The Lang.get() method', function() {
2525
expect(Lang.get('messages.home')).toBe('Home');
2626
});
2727

28+
it('should return the expected nested message', function() {
29+
expect(Lang.get('messages.family.father')).toBe('John');
30+
expect(Lang.get('messages.family.children.son')).toBe('Jimmy');
31+
});
32+
33+
it('should return the passed key when nested message does not point to a message', function() {
34+
expect(Lang.get('messages.family.children')).toBe('messages.family.children');
35+
expect(Lang.get('a.b.c.d.f.g.h.i.j.k')).toBe('a.b.c.d.f.g.h.i.j.k');
36+
});
37+
2838
it('should return the expected message with replacements', function() {
2939
expect(Lang.get('validation.accepted')).toBe('The :attribute must be accepted.');
3040
expect(Lang.get('validation.accepted', {

tests/spec/lang_parseKey_spec.js

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)