• Stars
    star
    135
  • Rank 269,297 (Top 6 %)
  • Language
    JavaScript
  • License
    Other
  • Created about 11 years ago
  • Updated almost 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An internationalization module for kraken and express

Makara

Build Status

A module to set up internationalization in Kraken and Express.js apps.

makara is the more opinionated configuration of its component parts, suitable for dropping into an express application and working with relatively little configuration.

It consists of bundalo for loading localized strings for use by application logic, engine-munger for controlling the lookup of templates and associated localized strings, and includes adaro as a template engine, connecting dustjs-linkedin to Express.

There's nothing inherently dust-centric about makara, but it does provide dust template engines as a default.

Using Makara

Here's a tiny but complete application

var express = require('express');
var makara = require('makara');
var path = require('path');

var app = express();

var helpers = [ 'dust-makara-helpers' ];
var env = process.env.NODE_ENV;
app.engine('dust', makara.dust({ cache: false, helpers: helpers }));
app.engine('js', makara.js({ cache: true, helpers: helpers }));

app.set('views', path.resolve(__dirname, 'public/templates'));

if (env === 'development') {
    app.set('view engine', 'dust');
} else {
    app.set('view engine', 'js');
}

app.use(makara({
    i18n: {
        contentPath: path.resolve(__dirname, 'locales'),
        fallback: 'en-US'
    },
    specialization: {
        'oldtemplate': [
            {
                is: 'newtemplate',
                when: {
                    'testmode': 'beta'
                }
            }
        ]
    },
    localeContext: "makaraLocale"
}));

app.get('/path', function (req, res) {
    res.render('localizedtemplate');

    // Or

    makara.getBundler(req).get('contentbundle', function (err, data) {
        // Do something with err and data here
    });
});

Configuration

The middleware that sets up the Express view engine replacement engine-munger takes most of the configuration in makara.

  • i18n.contentPath - String, the root to search for content in. Required.
  • i18n.formatPath - Function, a function to convert a locale to a path fragment. Optional, defaults to one that returns country/language.
  • i18n.fallback - String or Object as bcp47 creates, the locale to use when content isn't found for the locale requested. Required.
  • enableMetadata - Boolean, defaults to false. Sets up metadata editing tags for integration with in-place content editing systems.
  • specialization - Object, the specialization rule map, in the form expected by karka.
  • cache - Boolean, defaults to false. Whether the dust engine should cache its views.
  • localeContext - String, defaults to locale. Specifies the key to the locale information in req object.

Content

Content intended for localization is stored in .properties files as simple key=value pairs.

These are the files that hold the content strings for the different languages your application supports.

Normally, you are likely to start with a master set of content (likely in English) and the localization process will populate corresponding files for the other languages you will need.

Placement of .properties files

The root of the .properties content files is the locales folder at the top level of your project. Under it will be a folder per country (as in US/, DE/, et cetera). Below each country folder is one or more language folders (as in en/, de/). So locales/US/en/ will be the likely location for your master set of .properties files.

.properties files are correlated with the dust templates that use them, by path and name.

If you have a top level index.dust file, its content .properties file will be at locales/US/en/index.properties This holds all the external content strings used by that template. If your template is at widgets/display.dust then the content for US English will be at locales/US/en/widgets/display.properties. If you have content you want to share across pages, then you should factor out use of that content into a separate partial and use that partial to achieve content sharing.

You can override this filename mapping by providing a formatPath function to the makara i18n configuration.

What's in a .properties file

The parser for this file format is spud.

The format is simple: key=value with one message per line encoded as UTF-8. Comments are prefixed with #.

Let's look at some samples and then use them to discuss various points.

index.properties file:

index.title=PayPal Merchant
index.callToAction=Enroll now!
index.greeting=Welcome {userName}

# A list
index.ccList[0]=Visa
index.ccList[1]=Mastercard
index.ccList[2]=Discover

# A map
index.states[AL]=Alabama
index.states[AK]=Alaska
index.states[AZ]=Arizona
index.states[CA]=California

We are using the name of the file to start our key on each line. This is strictly a convention that makes the path to the file clear. There's duplication between the two, but it makes debugging easier.

Text to the right of the = sign is a simple message string with the text of the message.

If you have runtime values to be inserted, use dust brace to select the value from the dust template context as in the index.greeting line. Note that there is no restriction on inserting HTML tags into the messages. They are just another string of characters as far as the content processing is concerned.

In addition to simple strings, we support lists and maps. The index.ccList above might be used to provide a list of values to go in a list of allowed credit cards.

The index.states might be used to populate a dropdown list of states with the key as the option tag value and the full state name as the visible text.

To support writing the key part in natural languages other than English, all UTF-8 characters are allowed with a few exceptions needed to make the key=value syntax work. The exceptions are:

  • No equal sign in key part (e.g. first equal sign starts the value)
  • No periods in key part (used to allow keys like a.b.c)
  • No square brackets (used for subscript and map key notation)
  • May not start with # (Used for comments)

These same general restrictions apply to map key values. If you need to use characters that are restricted, you can do so using either of these escaping mechanisms:

  • \udddd - Like JavaScript but only handles the same characters supported by this notation in JavaScript
  • \u{dddddd} - Like JavaScript ES6 notation and handles all possible Unicode characters

For example,

\u2603=snowman

would use the Unicode snowman character for the key name.

Key Promotion

There are some edge cases worth mentioning:

Case 1:

key.subkey=value
key.subkey[property]=value2

In this case, key.subkey is created originally as a string value but is then overridden as a map. The original value will be discarded.

Case 2:

key.subkey[0]=1
key.subkey[property]=value

In this case, key.subkey is created originally as a list but is then converted to a map when the alphanumeric key is added.

Referencing internationalized content from a dust template

This is done using the {@message} helper tag. A sample usage of @message is:

{@message type="content" key="index.title"/}

Lists and maps are bit trickier when it comes to inlining.

There are two approaches available. The first uses three additional attributes on the @message tag, before="xxx" and after="yyy" and sep="z". When emitting the list elements, each will be prefixed by the "before" string, if there is one, suffixed by the "after" string, if there is one, and separated by the "sep" string, if there is one. With sep, the last element is not followed by the separator. Note that the value {$idx} can be used in the before/after attribute strings and it will be replaced by the current iteration count when inlining the lists. Similarly, {$key} will be replaced with the current key when inlining a map. No replacement is done in the sep string.

In some cases inlining won't do, even with before/after/sep. For example, if you need to pass the list as a parameter to a templating partial that might implement a dropdown functionality.

For this, @message with a mode="paired" attribute offers more flexibility.

The mode="paired" parameter produces the content list such that you can use both the index of the element for the value in an option tag and the value for the displayable text.

The mode="paired" attribute delivers the content in the form of a JSON object, which in the case of a list of months might look like:

[{$id:0,$elt:"Jan"}, {$id:1,$elt:"Feb"},.. ]

This gives you more ability to work with both the list/map value and the element value in your template.

In addition to mode="paired" there is an alternate form, mode="json" This generates the content list or map as a standard JavaScript array or an object with properties, respectively.

For more on using mode="paired" see the advanced helper docs.

Contributing

Please see the contribution guide

More Repositories

1

kraken-js

An express-based Node.js web application bootstrapping module.
JavaScript
4,948
star
2

zoid

Cross domain components
JavaScript
2,008
star
3

lusca

Application security for express apps.
JavaScript
1,787
star
4

post-robot

Cross domain post-messaging on the client side using a simple listener/client pattern.
JavaScript
734
star
5

kappa

A hierarchical npm-registry proxy
JavaScript
557
star
6

swaggerize-express

Design-driven apis with swagger 2.0 and express.
JavaScript
354
star
7

grumbler

A template for writing distributable front-end javascript modules.
JavaScript
292
star
8

beaver-logger

Client-side logging w/ super powers
JavaScript
252
star
9

hapi-openapi

Build design-driven apis with OpenAPI (formerly swagger) 2.0 and hapi.
JavaScript
210
star
10

jsx-pragmatic

Build JSX structures, then decide at runtime which pragma you want to use to render them.
JavaScript
188
star
11

express-enrouten

An express route initialization and configuration module.
JavaScript
172
star
12

levee

A circuit-breaker pattern implementation with fallback support.
JavaScript
171
star
13

fetch-robot

Proxy fetch through an iframe
JavaScript
157
star
14

cross-domain-utils

Cross Domain utilities
JavaScript
131
star
15

adaro

A Dust.js view renderer for express
JavaScript
127
star
16

kraken-example-with-shoppingcart

An example Kraken app showing off a shopping cart
JavaScript
116
star
17

generator-kraken

Yeoman generator for kraken.js apps
JavaScript
110
star
18

jwt-csrf

Stateless CSRF protection using jsonwebtoken (JWT)
JavaScript
108
star
19

shush

A simple module for reading JSON files that may have comments.
JavaScript
92
star
20

meddleware

Middleware configuration for express.
JavaScript
88
star
21

generator-swaggerize

Yeoman generator for design-driven apis with swagger 2.0 and krakenjs/swaggerize tools.
JavaScript
70
star
22

confit

Environment-aware configuration.
JavaScript
61
star
23

zoid-demo

A clonable demo project for xcomponent
JavaScript
61
star
24

swaggerize-routes

Swagger document driven route builder.
JavaScript
58
star
25

zalgo-promise

Release zalgo with synchronous promises
JavaScript
57
star
26

shortstop

Enables use of protocols in configuration.
JavaScript
55
star
27

kraken-example-with-passport

An example integrating kraken with passport authentication
JavaScript
53
star
28

caller

A node module for enabling a module to determine its caller.
JavaScript
47
star
29

nemo

node.js selenium-webdriver/mocha based combined testing framework
JavaScript
43
star
30

kraken-devtools

Development-time tools for kraken.js applications.
JavaScript
40
star
31

cross-domain-safe-weakmap

Cross-domain safe WeakMap shim
JavaScript
33
star
32

grabthar

Hot install and activation of npm modules
JavaScript
23
star
33

karka

A simple rule parser
JavaScript
21
star
34

belter

Miscellaneous browser utilities
JavaScript
17
star
35

good-influxdb

HapiJS good-reporter for use with InfluxDb
JavaScript
16
star
36

angular-remove-di-loaders

Webpack loaders to remove Angular DI (Dependency Injection)
JavaScript
16
star
37

freshy

An (admittedly naΓ―ve) node module (un|re)loader/refreshener.
JavaScript
15
star
38

endgame

A tiny module for ensuring uncaught exceptions are handled in Node.js
JavaScript
15
star
39

shortstop-handlers

Common protocol handlers for use with the shortstop node module.
JavaScript
15
star
40

passport-saml-encrypted

A strategy for Passport authentication that supports encrypted SAML responses
JavaScript
14
star
41

pine

A logging wrapper for winston.
JavaScript
14
star
42

react-redux-krakenjs-swaggerize-express

React client app, redux stage management, passport oauth2, paypal rest api and swagger based krakenjs node.js server
JavaScript
14
star
43

spud

A content store parser, reading a java .properties-like format
JavaScript
14
star
44

kraken-example-with-i18n

An example Kraken app showing off internationalization support
JavaScript
11
star
45

kraken-example-with-specialization

An example Kraken app showing off template specialization features.
JavaScript
11
star
46

bundalo

Manage localized sets of content files (be they property/json/etc) which may require rendering with data models
JavaScript
10
star
47

engine-munger

A helper module to insert specialization and i18n in the render workflow
JavaScript
10
star
48

memcookies

Persist cookies on the client-side, useful for supporting cookies disabled browsers
JavaScript
9
star
49

subprocess-robot

Create processes, process pools, and message between processes
JavaScript
8
star
50

grumbler-scripts

Build scripts for grumbler modules
JavaScript
6
star
51

universal-serialize

Universal serializer allowing for custom types
JavaScript
5
star
52

reverend

DEPRECATED: Merge an express-style path string with data to create a valid path.
JavaScript
5
star
53

sync-browser-mocks

Synchronous browser mocks for testing
JavaScript
4
star
54

webpack-mem-compile

Compile webpack to and from memory
TypeScript
3
star
55

hotware

JavaScript
3
star
56

localizr

A library and tool to apply localization to dust templates before rendering
JavaScript
3
star
57

neff

nconf & express based feature flags
JavaScript
3
star
58

krakenjs.github.io

Source for the kraken website
JavaScript
3
star
59

construx

Compile-on-the-fly and other development tools for use when building express applications.
JavaScript
2
star
60

spundle

command line tool and library to package localization files as json
JavaScript
2
star
61

dust-makara-helpers

Server-side configuration of helpers for makara
JavaScript
2
star
62

nodejs_deployment

Design and architecture details of node.js deployment solutions
JavaScript
2
star
63

node-benchmarker

Runs benchmarks and publishes results
JavaScript
2
star
64

grabthar-release

Release scripts for grabthar modules
JavaScript
2
star
65

express-promisified

Express with promises
JavaScript
2
star
66

webpack-promise-shim-plugin

Plugin to shim in Promise polyfill into webpack core
JavaScript
2
star
67

file-resolver

Used in kraken based projects for resolving files given the locale , file name, and the file extension.
JavaScript
2
star
68

beaver-logger-ios

Beaver Logger client for iOS
Swift
2
star
69

anemone-machina

express view engine and browser renderer for React and react-router
JavaScript
1
star
70

findatag

A specialized tokenizer for finding dust-style tags ({@tagname [attributes]})
JavaScript
1
star
71

construx-webpack

web pack dev middleware for krakenjs
JavaScript
1
star
72

express-bcp47

Locale handling middleware for Express
JavaScript
1
star
73

dustjacket

Loader middleware for dustjs
JavaScript
1
star
74

strict-merge

Strict deep merge of objects
JavaScript
1
star
75

makara-languagepackpath

Middleware for exposing the path to a language pack to templates
JavaScript
1
star