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

gridfw-i18n

v1.2.0

Published

fast i18n plugin for GridFW

Downloads

2

Readme

gridfw-i18n

fast i18n plugin for Gridfw

Features

  • Translate literals
  • Pluralize literals
  • Swith value depending on some value
  • Text combining
  • Compatible with Gridfw and Grid-Reactor

Configuration:

config via code

Gridfw = require('gridfw');

app = new Gridfw();

app.i18n.reload({
	default: 'en', // set as default local
	locals: '/path/to/locals/**/*.js'
});

// or like any other gridfw plugin via:
app.plugin('i18n').reload({...})

Locals are "js" files. See i18n gulp compiler to see how to create those files at: https://www.npmjs.com/package/gridfw-i18n-gulp

To keep memory usage minimal, the framework will use a memory cache and load useful files only depending on use.

Configure via Config file (recommanded)

See Gridfw file for more information Inside your config file, add the following:

{
	plugins:{
		//...
		"i18n": {
			"require": "gridfw-i18n",
			"default": "en", // set default local, @default: en
			"locals": '/path/to/locals/*.js' // @default: i18n/*.js
		}
	}
}

Options

* param: String - i18n attribute name inside "ctx" and templates, @default: 'i18n' 
* default: String - Contains default local to use when no one is selected
* locals: String or list of Strings - GLOB path format to load all locals (will load only useful ones to memory depending on use)
* setLangParam: String - name of query param that will be used to change language, @default: 'set-lang', Example: "?set-lang=en"
* ctxLocal: function - see "Define local" section bellow

* session: string or object - see session management bellow
* cache: boolean - when true, use cache to optimize memory, load only required i18n files. load all otherwise @default: true

Tips

  • The framework will look for locals inside "/i18n/*.js" in your app directory path unless you set "locals" option.
  • Use gridfw-i18n-gulp to generate js files.
  • Use Gridfw generator to generate your project.
  • ctx.i18n.local is reserved, it will contains current local name

Example of use:

Step 1: Create i18n source files and compile theme

see gridfw-i18n-gulp for more options on how to create your i18n files

appName: 'My app' # This message will be available for all locals

'hello %name':
	en: 'Hello #{self.name}'
	fr: 'Bonjour #{self.name}'

'you need x tickets':
	en: i18n.switch 'tickets.length',
		0: 'You need no ticket'
		1: 'You need one ticket'
		2: 'You need two tickets'
		else: 'You need #{self.tickets.length} tickets'
	fr: ...

# you can use PUGJS format, and nested messages it will be precompiled for ultra performance
'%name, you need x tickets now': '[b #{self.name}], #{i18n["you need x tickets"](self)} [span.danger now]'

At compile time, there are two cases:

  • If the text contains variables, it will be compiled to a function that accepts a map of those variables. Example: 'hello #{self.name}' will be compiled to: function({name}){...}
  • Otherwise, the text will be prerendered (compile pugjs content), and returned as text. Example: 'this is [span.danger very urgent]' will be compiled to: this is very urgent

Step 2: use it inside your code:

app.get '/my/app', (ctx)->
	appName = ctx.i18n.appName;
	greeting = ctx.i18n['hello %name']({name: 'mec'});

Or in any template engine you use:

html
	head
	body
		div App name: #{i18n.appName}
		div #{i18n['hello %name'](user)}

Tips:

if you use "gridfw-compiler" to organize and conditional compile your code use "<%= i18n.key %>" instead of "i18n.key" this will print "_i18n[key_index]". While i18n is a map of key: value, _i18n is an array. it is 10x faster, but you need to know index instead of the key. "gridfw-compiler" will do conversion for you. if you use "self" or any other root object in your templates, it will be: "self.<%= i18n.key %>" instead of "self.i18n.key"

Define local:

Permanent local:

A user local will be stored inside his session. Every page with no temporary local will be shown in this local.

To change a user local:

  • call URL: http:///?anyparam=...&set-lang=. will result a redirection to target URL

  • use: await ctx.setLocal('') # this will load local data, change ctx.i18n and ctx.locals.i18n

Temporary local: Recommanded for pages depending on search engines

You can define a page language depending on a visible param inside the URL. This make each page looks depending on the target local.

There are two common possibilities

  • /?anyParam...&lang=
  • //?anyParam...

The seconde one is the most recommanded.

The first example is the simplest: just add the "ctxLocal" option as follow

app.i18n.reload({
	//... other options
	ctxLocal: (ctx) => ctx.query.lang
	});

The second options (that is recommanded for websites) needs special attention. This approche could be confusing with routing logic. so be careful.

  • The first step is: extract the language param
  • The seconde step will be to rewrite the path, so the router will not see the language param "ctxLocal" will be called inside a request handler wrapper (see app.wrap method). It will be called before the routing system and will contains no path param or any resolved values.

See this example on how to do this

app.i18n.reload({
	ctxLocal: function(ctx){
		// Resolve the lang param
		matches = ctx.path.match(/^\/([a-z]*)(.*)/);

		// Rewrite the path so the lang param is invisible by the routing system
		ctx.path = matches[2];

		// return the lang value
		return matches[1]
	}
});

Simple! isn't it :) You can implement more complexe format as you want.

Session management:

By default, the framework will store the current local inside the user session under variable: "i18nLocal"

You can change this param name via option:

app.i18n.reload({
	//... other options
	session: 'your_custom_param'
});

You can do more on setting your custom logic to get and store this value yourself. You can use sync or async functions, return promises ...

app.i18n.reload({
	//... other options
	session:{
		get: async function(ctx){
			// do what ever you want, it's async!
			var lang= await ctx.session.get('i18nParam');
			return lang;
		},
		set: function(ctx, lang){
			ctx.session.set('i18nParam', lang)
		}
	}
});

Global methods:

/**
 * Load EN locals
 * @return {
 *	messages: Object - contains all mapped messages (key: value)
 *	arr: Array - contains indexed messages
 *	map: Object - map kies to indexes
 * }
 */
i18nEN = await app.i18n.get('en');
i18nEN.messages.local === 'en'

/**
 * Is a local is supported
 */
app.i18n.has('fr-FR') // is fr-FR is supported

/**
 * Get a list of all supported locals names
 * This is a Getter
 */
app.i18n.locals # returns ['en', ...]

/**
 * Get list of current loaded locals names
 * (in cache)
 * This is a Getter
 */
app.i18n.loaded # returns ['en', ...]

Client side useful methods

/**
 * Load locals from an object.
 * TIP: You can use static files or JSONP
 */
I18N.load({fr:{...}, en:{...}});

Supporters

coredigix