npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

loc

v0.6.1

Published

lightweight simple translation module with dynamic json storage

Downloads

248

Readme

loc

Build Status NPM version

Features

  • Full featured localization module for express.js
  • server side translation
  • Pluggable storages
  • Pluggable strategies like query, path, cookie ect.
  • Url Translation
  • Uses common __('...') syntax in app and templates
  • Support for plurals
  • Stores language files in json files compatible to webtranslateit json format
  • Adds new strings on-the-fly when first used in your app
  • Nested, hierarchical contexts, separated in different files
  • Uses the closest to the preferred user locale, if not set explicitely by the user request
  • Automatic fallback to more generic localization (http://www.rfc-editor.org/rfc/rfc4647.txt)
  • Support for locale names according to http://www.rfc-editor.org/rfc/bcp/bcp47.txt
  • No extra parsing needed.
  • Handles simultaneous requests with different locales correctly :-)

Background

The module was originally developed by https://github.com/mashpie/i18n-node, then forked and refactored by https://github.com/jeresig/i18n-node-2. This is a serious refactoring of the latter. Reasons:

  • were not pluggable / extendable
  • not specific to express.js
  • complicated code
  • features missing: url translation, hierarchical contexts, locale fallback, preferred user locale, ...

TODO

  • better description
  • more tests
  • client side translation / routes
  • import/export language definitions e.g. gettext

Installation

Run the following:

npm install loc

Usage

Load and Configure

In your app.js:

// example localization initialization
var loc = require('loc')({
	// it gets the locale from the following strategies in this order.
	// if the locale is not part of the `path`it looks it up in the `query` ect.
  getLocaleFrom: ['path', 'query', 'subdomain', 'cookie'],

  // if the locale was found in one of the strategies above, it stores it with this strategy.
  // in this case in the `cookie`
  storeLocaleTo: ['cookie'],

  // the locale definitions (translations) are retrieved from `file`.
  storage: 'file',

  // the following locales are supported (optional). 
  // If this option is omitted, it accetps what ever is defined in the definitions.
  locales: ['de', 'de-ch', 'en', 'en-GB', 'en-us'],

  // locale definition director
  directory: "./locales",
  
  // locale definition file extension
  extension: ".json",

  // Exclude List for the path rewrite middleware used for the path strategy.	
  // problematic are static assets and url's that start with one to three letters in the path like:
  // /p/, /js/ or /img/ and should therefore be excluded.
  excludeList: [".css", ".js", '.ico', '/api/', '/img/', '/css/', '/js/']
});

// adds all middlewares as bundle
//loc.bind(app);
//or add them separately

// adds the loc middleware. adds the req.i18n object.
app.use(loc.loc());

// adds the locPathRewrite middleware used for the `path` strategy.
// it redirects the request to the url without the locale in the path. e.g. `/en-GB/about` to `/about` 
app.use(loc.pathRewrite());

// adds the urlTranslation middleware
app.use(loc.urlTranslation());

// print out localeCache for debugging purposes 
loc.writeLocaleCache();

Inside Your Express View

module.exports = {
	index: function(req, res) {
		req.render("index", {
			title: req.i18n.__("My Site Title"),
			desc: req.i18n.__("My Site Description")
		});
	}
};

Inside Your Templates: Swig example

{% extends "page.swig" %}

{% block content %}
<h1>{{ __("Welcome to:") }} {{ title }}</h1>
<p>{{ desc }}</p>
{% endblock %}

Inside Your Templates: ejs example

<head>
  <title><%=__("title") %></title>
  ...

locale definition

An example locale definition en.js inside ./locales/ may look something like:

{
	"Hello": "Hello",
	"Hello %s, how are you today?": "Hello %s, how are you today?",
	"weekend": "weekend",
	"Hello %s, how are you today? How was your %s.": "Hello %s, how are you today? How was your %s.",
	"Hi": "Hi",
	"Howdy": "Howdy",
	"%s cat": {
		"one": "%s cat",
		"other": "%s cats"
	},
	"There is one monkey in the %%s": {
		"one": "There is one monkey in the %%s",
		"other": "There are %d monkeys in the %%s"
	},
	"tree": "tree"
}

that file can be edited or just uploaded to webtranslateit for any kind of collaborative translation workflow.

locale definition with contexts example

Source Files

// locales/en.json
{
	"Home": "Start Page",
	"Lessons": "Lessons",
	"About Us": "About Us"
}

// locales/de-ch.json
{
	"Home": "De Hei",
	"Lessons": "Lektion",
	"About Us": "Über üüs"
}

// locales/url/de-ch.json
{
	"title": "Tegscht"
}

// locales/url/cms/de-ch.json
{
	"cms title": "CMS Überschrift",
	"nested": {
		"keys": "Verschachtelt"
	}
}

Queries

var loc = require('loc')();
var i18n = new Translation(loc);

// Example 1
i18n.setLocale('en')
i18n.t('Home')

// Example 2
i18n.setLocale('de-ch')
i18n.t('url/cms/cms title')

// Example 3
i18n.setLocale('de-ch')
i18n.t('url/cms/nested.cms title')

Queries (internal)

// Example 1
// locale sep   key        Resulting Value
//  ----  ---  ------      ---------------
// ['en']['/']['Home'] --> "Start Page"

// Example 2
//  locale     context     sep     key            Resulting Value
//  -------  ------------  ---  -----------      -----------------
// ['de-ch']['url']['cms']['/']['cms title'] --> "CMS Überschrift"

// Example 3
//  locale     context     sep       key              Resulting Value
//  -------  ------------  ---  ----------------      ---------------
// ['de-ch']['url']['cms']['/']['nested']['keys'] --> "Verschachtelt"

localeCache (internal)

{
	"en": {
		"Home": "Start Page",
		"Lessons": "Lessons",
		"About Us": "About Us"
	},
	"de-ch": {
		"/": {
			"Home": "De Hei",
			"Lessons": "Lektion",
			"About Us": "Über üüs"
		},
		"url": {
			"/": {
				"title": "Tegscht"
			},
			"cms": {
				"/": {
					"cms title": "CMS Überschrift",
					"nested": {
						"keys": "Verschachtelt"
					}
				}
			}
		}
	}
}

url translate

if the url translation middleware is added: app.use(loc.urlTranslation()); Urls will be translated according to the context url. The url is being translated by segments.

Example: File: locales/de-ch.json { "Start" : "home", "Seite": "page" }

  • the url: /Start is being redirected to /home
  • the url: /Start?Seite=1 is being redirected to /home?page=1

methods

In order to run the following examples, you must first require loc and create a new i18n object. The i18n object is created on every request.

var loc = require('loc')();
var i18n = new Translation(loc);

__(string, [...])

Translates a string according to the current locale. Also supports sprintf syntax, allowing you to replace text, using the node-sprintf module.

For example:

var greeting = i18n.__('Hello %s, how are you today?', 'Marcus');

this puts Hello Marcus, how are you today?. You might also add endless arguments or even nest it.

var greeting = i18n.__('Hello %s, how are you today? How was your %s?', 
	'Marcus', i18n.__('weekend'));

which puts Hello Marcus, how are you today? How was your weekend?

You might even use dynamic variables. They get added to the current locale file if they do not yet exist.

var greetings = ['Hi', 'Hello', 'Howdy'];
for (var i = 0; i < greetings.length; i++) {
	console.log( i18n.__(greetings[i]) );
};

which outputs:

Hi
Hello
Howdy

__n(one, other, count, [...])

Different plural forms are supported as a response to count:

var singular = i18n.__n('%s cat', '%s cats', 1);
var plural = i18n.__n('%s cat', '%s cats', 3);

this gives you 1 cat and 3 cats. As with __(...) these could be nested:

var singular = i18n.__n('There is one monkey in the %%s', 'There are %d monkeys in the %%s', 1, 'tree');
var plural = i18n.__n('There is one monkey in the %%s', 'There are %d monkeys in the %%s', 3, 'tree');

putting There is one monkey in the tree or There are 3 monkeys in the tree.

getLocale()

Returns a string containing the current locale. If no locale has been specified then it default to the value specified in defaultLocale.

setLocale(locale)

Sets a locale to the specified string. If the locale is unknown, the locale defaults to the one specified by defaultLocale. For example if you have locales of 'en' and 'de', and a defaultLocale of 'en', then call .setLocale('ja') it will be equivalent to calling .setLocale('en').

isPreferredLocale()

To be used with Express.js or another framework that provides a request object. This method works if a request option has been specified when the i18n object was instantiated.

This method returns true if the locale specified by getLocale matches a language desired by the browser's Accept-language header.

tests

run the tests with

mocha

history

  • v0.6.0: express 4 support

license

MIT License