Skip to content

Commit

Permalink
i18n support.
Browse files Browse the repository at this point in the history
  • Loading branch information
cskr committed Jul 27, 2010
1 parent 16b50c2 commit 573d458
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 10 deletions.
1 change: 1 addition & 0 deletions examples/i18n/grasshopper
8 changes: 8 additions & 0 deletions examples/i18n/index.html
@@ -0,0 +1,8 @@
<html>
<head>
<title><%= locale['title'] %></title>
</head>
<body>
<h1><%= locale['msg'] %></h1>
</body>
</html>
21 changes: 21 additions & 0 deletions examples/i18n/locales.js
@@ -0,0 +1,21 @@
var gh = require('./grasshopper');

var locales = {};
locales['en-us'] = {
title: 'Color Page',
msg: 'Color'
};
locales['en-gb'] = {
title: 'Colour Page',
msg: 'Colour'
};

gh.configure({
locales: locales
});

gh.get('/', function() {
this.render('index');
});

gh.serve(8080);
13 changes: 7 additions & 6 deletions lib/ghp.js
Expand Up @@ -21,19 +21,19 @@ var cache = {};

var helpers = [{h: escapeHTML}];

function fill(templateFile, model, encoding, viewsDir, extn) {
function fill(templateFile, model, encoding, viewsDir, extn, locale) {
var template = cache[templateFile];
if(!template) {
var content = fs.readFileSync(templateFile, encoding);
cache[templateFile] = template = compile(content, helpers.length + 1);
cache[templateFile] = template = compile(content, helpers.length + 2);
}
return template(model, [new IncludeHelper(model, encoding, viewsDir, extn)].concat(helpers));
return template(model, [new IncludeHelper(model, encoding, viewsDir, extn, locale), {locale: locale}].concat(helpers));
}

exports.fill = fill;

exports.fillText = function(text, model) {
return compile(text, helpers.length)(model, helpers);
return compile(text, 0)(model);
}

exports.addHelpers = function(newHelpers) {
Expand Down Expand Up @@ -76,15 +76,16 @@ function compile(text, helpersCount) {
}

// Class: IncludeHelper
function IncludeHelper(model, encoding, viewsDir, extn) {
function IncludeHelper(model, encoding, viewsDir, extn, locale) {
this.model = model;
this.encoding = encoding;
this.viewsDir = viewsDir;
this.extn = extn;
this.locale = locale;
}

IncludeHelper.prototype.include = function(templateFile) {
return fill(this.viewsDir + '/' + templateFile + '.' + this.extn , this.model, this.encoding, this.viewsDir, this.extn);
return fill(this.viewsDir + '/' + templateFile + '.' + this.extn , this.model, this.encoding, this.viewsDir, this.extn, this.locale);
}

function escapeHTML(html) {
Expand Down
4 changes: 3 additions & 1 deletion lib/grasshopper.js
Expand Up @@ -19,7 +19,8 @@ var http = require('http'),
querystring = require('querystring'),
renderer = require('./renderer'),
multipart = require('./multipart'),
session = require('./session');
session = require('./session'),
i18n = require('./i18n');

var routes = {};
var filters = [];
Expand All @@ -45,6 +46,7 @@ exports.configure = function(config) {
renderer.configure(config);
multipart.configure(config);
session.configure(config);
i18n.configure(config);
};

exports.get = function(path, controller) {
Expand Down
41 changes: 41 additions & 0 deletions lib/i18n.js
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2010 Chandra Sekar S
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var locales,
defaultLocale = 'en-us';

exports.configure = function(config) {
if(config.locales)
locales = config.locales;
if(config.defaultLocale)
defaultLocale = config.defaultLocale;
};

exports.init = function(ctx) {
if(locales) {
var acceptLanguage = ctx.request.headers['accept-language'];
if(acceptLanguage) {
var ranges = acceptLanguage.split(',');
for(var i = 0; i < ranges.length; i++) {
var range = ranges[i].split(';', 1)[0].toLowerCase();
if(locales[range]) {
ctx.locale = locales[range];
return;
}
}
}
ctx.locale = locales[defaultLocale];
}
};
14 changes: 11 additions & 3 deletions lib/renderer.js
Expand Up @@ -22,12 +22,14 @@ var fs = require('fs'),
uuid = require('./uuid'),
session = require('./session'),
ghp = require('./ghp'),
gh = require('./grasshopper');
gh = require('./grasshopper'),
i18n = require('./i18n');

var viewsDir = '.',
defaultViewExtn = 'html',
staticsDir = '.',
defaultEncoding = 'utf8',
defaultCharset = 'UTF-8',
layout = undefined;

exports.handleError = function(err, req, res, params) {
Expand All @@ -45,6 +47,8 @@ exports.configure = function(config) {
defaultViewExtn = config.defaultViewExtn;
if(config.staticsDir)
staticsDir = config.staticsDir;
if(config.defaultCharset)
defaultCharset = config.defaultCharset;
if(config.defaultEncoding)
defaultEncoding = config.defaultEncoding;
if(config.layout)
Expand Down Expand Up @@ -82,6 +86,9 @@ function RequestContext(request, response, params) {
}
}
}

i18n.init(this);
this.charset = defaultCharset;
}

RequestContext.prototype.getExtn = function() {
Expand Down Expand Up @@ -130,7 +137,7 @@ RequestContext.prototype.render = function(view, useLayout) {
}

try {
var content = ghp.fill(viewFile, this.model, this.encoding, viewsDir, this.extn);
var content = ghp.fill(viewFile, this.model, this.encoding, viewsDir, this.extn, this.locale);
this.send(content);
} catch(e) {
this.handleError(e);
Expand All @@ -151,6 +158,7 @@ RequestContext.prototype.renderText = function(text) {
};

RequestContext.prototype.send = function(text) {
this.headers['content-type'] += '; charset=' + this.charset
this.response.writeHead(this.status, this.headers);
if(this.request.method != 'HEAD') {
this.response.write(text, this.encoding);
Expand Down Expand Up @@ -215,7 +223,7 @@ RequestContext.prototype.renderError = function(status, error) {
fs.stat(viewFile, function(err, stats) {
if(!err && stats.isFile()) {
try {
var content = ghp.fill(viewFile, {error: error}, self.encoding, viewsDir, self.extn);
var content = ghp.fill(viewFile, {error: error}, self.encoding, viewsDir, self.extn, this.locale);
self.send(content);
} catch(e) {
self.handleError(e);
Expand Down

0 comments on commit 573d458

Please sign in to comment.