Skip to content

Commit 7b53ab7

Browse files
committed
Merge pull request #7 from drewfish/ctx-key
no longer need a block helper to wrap each template
2 parents c688466 + e6ef7a5 commit 7b53ab7

File tree

4 files changed

+82
-25
lines changed

4 files changed

+82
-25
lines changed

examples/express/app.js

+13-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ var
77

88
// These are our polyfills.
99
global.Intl = require('intl');
10-
global.IntlMessageFormat = require('intl-messageformat');
10+
// We need to do it this way until intl-messageformat is published to NPM.
11+
global.IntlMessageFormat = require('intl-messageformat/index');
12+
require('intl-messageformat/locale-data/complete');
1113

1214
dustIntl = require('../../lib/helpers');
1315
dustIntl.register(dust);
@@ -19,16 +21,22 @@ app.set('port', 3000);
1921

2022

2123
// middleware for setting up the locale
22-
app.get('*', function(req, res, next) {
24+
app.use(function(req, res, next) {
2325
res.locals.intl = {};
26+
res.locals.intl.formats = {
27+
number: {
28+
eur: { style: 'currency', currency: 'EUR' },
29+
usd: { style: 'currency', currency: 'USD' }
30+
}
31+
};
2432
res.locals.intl.messages = {
25-
FROM: "from request: {num, number, integer}"
33+
FROM: "from request: {num, number, eur}"
2634
};
2735

2836
//// This is the best approach...
29-
//res.locals.intl.locale = req.acceptedLanguages[0];
37+
//res.locals.intl.locales = req.acceptedLanguages[0];
3038
//// ...but for our testing we'll fake a German user.
31-
res.locals.intl.locale = 'de-DE'
39+
res.locals.intl.locales = 'de-DE'
3240

3341
next();
3442
});

examples/express/views/index.dust

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
{@intl locales=intl.locale messages=intl.messages}
21
<html>
32
<head>
43
</head>
54
<body>
6-
<strong>request locale:</strong> {intl.locale} <br>
5+
<strong>request locale:</strong> {intl.locales} <br>
76
<ul>
87
<li>{@intlMessage _key="FROM" num=NUM/}</li>
98
{@intl locales="en"}
10-
<li>fixed to "en": {@intlNumber val=NUM/}</li>
9+
<li>fixed to "en": {@intlNumber val=NUM formatName="eur" /}</li>
1110
{/intl}
1211
<li>{@intlMessage _key="FROM" num=NUM/}</li>
1312
</ul>
1413
</body>
1514
</html>
16-
{/intl}

lib/helpers.js

+44-11
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
}
3636

3737

38-
var CONTEXT_KEY = '--intl--';
38+
var CONTEXT_KEY = 'intl';
3939

4040

4141
/**
@@ -81,6 +81,39 @@
8181
}
8282

8383

84+
/**
85+
Returns something from deep within the a value in the context, taking into
86+
consideration the context stack. (The built-in version of context.get()
87+
isn't quite sophisticated enough for us.)
88+
@protected
89+
@method _contextGet
90+
@param {Object} ctx The dust context.
91+
@param {Array} keys An ordered list of keys to drill down into the data structure.
92+
@return {mixed} Value found for the key path, or undefined if not found.
93+
*/
94+
function _contextGet(ctx, keys) {
95+
var frame, // the current stack frame
96+
data, // the spot within the stack frame we're inspecting
97+
last = keys.length - 1,
98+
k,
99+
key;
100+
for (frame = ctx.stack; frame; frame = frame.tail) {
101+
data = frame.head;
102+
for (k = 0; k < last; k += 1) {
103+
key = keys[k];
104+
if (! data.hasOwnProperty(key)) {
105+
break;
106+
}
107+
data = data[key];
108+
}
109+
if (k === last && data.hasOwnProperty(keys[last])) {
110+
return data[keys[last]];
111+
}
112+
}
113+
return undefined; // value not found anywhere
114+
}
115+
116+
84117
/**
85118
Determins the current locales, possibly looking in parent contexts
86119
if they've been defined there. Defaults to the global `this`.
@@ -94,7 +127,7 @@
94127
if (params.locales) {
95128
return _tap(params.locales, chunk, context);
96129
}
97-
return context.get([CONTEXT_KEY, 'locales']) || this.locale;
130+
return _contextGet(context, [CONTEXT_KEY, 'locales']) || this.locale;
98131
}
99132

100133

@@ -107,15 +140,15 @@
107140
@param {Object} context The dust context stack.
108141
@return {Object} The format options.
109142
*/
110-
function _getFormatOptions(chunk, params, context) {
143+
function _getFormatOptions(type, chunk, params, context) {
111144
var raw,
112145
k,
113146
fixed = {},
114147
fmt;
115-
if (params._fmt) {
116-
fmt = _tap(params._fmt, chunk, context);
117-
delete params._fmt;
118-
raw = context.get([CONTEXT_KEY, 'formats', fmt]);
148+
if (params.formatName) {
149+
fmt = _tap(params.formatName, chunk, context);
150+
delete params.formatName;
151+
raw = _contextGet(context, [CONTEXT_KEY, 'formats', type, fmt]);
119152
// TODO: only need to copy-and-merge if there are still parameters
120153
raw = _extend({}, raw); // shallow copy
121154
_extend(raw, params);
@@ -152,7 +185,7 @@
152185
msg = params._msg;
153186
}
154187
else if (params._key) {
155-
msg = context.get([CONTEXT_KEY, 'messages', _tap(params._key, chunk, context)]);
188+
msg = _contextGet(context, [CONTEXT_KEY, 'messages', _tap(params._key, chunk, context)]);
156189
}
157190
else {
158191
throw new ReferenceError('@intlMessage needs either a `_msg` or `_key` parameter');
@@ -164,7 +197,7 @@
164197
return chunk;
165198
}
166199

167-
formatOptions = context.get([CONTEXT_KEY, 'formats']);
200+
formatOptions = _contextGet(context, [CONTEXT_KEY, 'formats']);
168201
locales = _getLocales(chunk, params, context);
169202
formatter = new IntlMessageFormat(msg, locales, formatOptions);
170203
chunk.write(formatter.format(params));
@@ -194,7 +227,7 @@
194227
val = _tap(params.val, chunk, context);
195228
delete params.val; // since params might be interpretted as format options
196229

197-
formatOptions = _getFormatOptions(chunk, params, context);
230+
formatOptions = _getFormatOptions('number', chunk, params, context);
198231
locales = _getLocales(chunk, params, context);
199232
// TODO: caching based on key [locales, formatOptions]
200233
formatter = new Intl.NumberFormat(locales, formatOptions);
@@ -226,7 +259,7 @@
226259
delete params.val; // since params might be interpretted as format options
227260
val = new Date(val).getTime();
228261

229-
formatOptions = _getFormatOptions(chunk, params, context);
262+
formatOptions = _getFormatOptions('date', chunk, params, context);
230263
locales = _getLocales(chunk, params, context);
231264
// TODO: caching based on key [locales, formatOptions]
232265
formatter = new Intl.DateTimeFormat(locales, formatOptions);

tests/helpers.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ describe('Helper `intlNumber`', function () {
165165
expect(out).to.equal(expected);
166166
});
167167
});
168+
169+
it('should work wwith a locale from explicit context', function () {
170+
var tmpl = '{@intlNumber val=NUM /}',
171+
ctx = {
172+
intl: {
173+
locales: 'de-DE'
174+
},
175+
NUM: 40000.004
176+
},
177+
expected = "40.000,004";
178+
Dust.renderSource(tmpl, ctx, function(err, out) {
179+
expect(out).to.equal(expected);
180+
});
181+
});
168182
});
169183
});
170184

@@ -539,12 +553,14 @@ describe('Helper `intl`', function () {
539553

540554
describe('should provide formats', function () {
541555
it('for intlNumber', function () {
542-
var tmpl = '{@intl formats=intl.formats}{@intlNumber val=NUM _fmt="usd"/} {@intlNumber val=NUM _fmt="eur"/} {@intlNumber val=NUM style="currency" currency="USD"/}{/intl}',
556+
var tmpl = '{@intl formats=intl.formats}{@intlNumber val=NUM formatName="usd"/} {@intlNumber val=NUM formatName="eur"/} {@intlNumber val=NUM style="currency" currency="USD"/}{/intl}',
543557
ctx = {
544558
intl: {
545559
formats: {
546-
eur: { style: 'currency', currency: 'EUR' },
547-
usd: { style: 'currency', currency: 'USD' }
560+
number: {
561+
eur: { style: 'currency', currency: 'EUR' },
562+
usd: { style: 'currency', currency: 'USD' }
563+
}
548564
}
549565
},
550566
NUM: 40000.004
@@ -556,11 +572,13 @@ describe('Helper `intl`', function () {
556572
});
557573

558574
it('for intlDate', function () {
559-
var tmpl = '{@intl formats=intl.formats}{@intlDate val=' + timeStamp + ' _fmt="hm"/}{/intl}',
575+
var tmpl = '{@intl formats=intl.formats}{@intlDate val=' + timeStamp + ' formatName="hm"/}{/intl}',
560576
ctx = {
561577
intl: {
562578
formats: {
563-
hm: { hour: 'numeric', minute: 'numeric' }
579+
date: {
580+
hm: { hour: 'numeric', minute: 'numeric' }
581+
}
564582
}
565583
}
566584
},

0 commit comments

Comments
 (0)