Giter VIP home page Giter VIP logo

i18n-node-2's Introduction

Node.js: i18n-2

  • Designed to work out-of-the-box with Express.js
  • Lightweight simple translation module with dynamic json storage.
  • Uses common __('...') syntax in app and templates.
  • Stores language files in json files compatible to webtranslateit json format.
  • Adds new strings on-the-fly when first used in your app.
  • No extra parsing needed.

Installation

Run the following:

npm install i18n-2

Simple Example

Note: If you plan on using the module with Express.js, please view Using with Express.js, below.

// Load Module and Instantiate
var i18n = new (require('i18n-2'))({
    // setup some locales - other locales default to the first locale
    locales: ['en', 'de']
});

// Use it however you wish
console.log( i18n.__("Hello!") );

API:

new i18n(options)

The i18n function is the return result from calling require('i18n-2'). You use this to instantiate an I18n instance and set any configuration options. You'll probably only do this if you're not using the expressBind method.

i18n.expressBind(app, options)

You'll use this method to attach the i18n functionality to the request object inside Express.js. The app argument should be your Express.js app and the options argument should be the same as if you were calling new i18n(options). See "Using with Express.js" at the end of this README for more details.

__(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

You can also use nested object :

{
    "foo": {
        "bar": "ok"
    }
}

And use dot notation to access the value :

i18n.__('foo.bar');

__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.

You may also use in your locale object/file :

{
    "catEat": {
        "one": "%d cat eat the %s",
        "other": "%d cat eat the %s"
    }
}

and use __n() as you would use __() (directly, or from locale) :

var singular = i18n.__n('catEat', 1, 'mouse');
var plural = i18n.__n('catEat', 10, 'mouse');

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').

setLocaleFromQuery([request])

To be used with Express.js or another framework that provides a request object. Generally you would want to use this by setting the query option to true.

This method takes in an Express.js request object, looks at the query property, and specifically at the lang parameter. Reading the value of that parameter will then set the locale.

For example:

example.com/?lang=de

Will then do:

setLocale('de')

setLocaleFromSessionVar([request])

To be used with Express.js or another framework that provides a request object. Generally you would want to use this by setting the session option to true.

This methods takes in an Express.js request object, looks at the variable locale (you may override this behaviour by changing the option sessionVarName, which defaults to locale) contained in the session object, and it will set the locale to that value.

For example, if the session is : { user: { ... }, locale: 'de' }

Then setLocaleFromSessionVar will do setLocale('de')

setLocaleFromSubdomain([request])

To be used with Express.js or another framework that provides a request object. Generally you would want to use this by setting the subdomain option to true.

This method takes in an Express.js request object, looks at the hostname, and extracts the sub-domain. Reading the value of the subdomain the locale is then set.

For example:

de.example.com

Will then do:

setLocale('de')

setLocaleFromCookie([request])

To be used with Express.js or another framework that provides a request object. This method takes a request object, looks at it's cookies property and tries to find a cookie named cookieName (default: lang).

See Using with Express.js for a complete example.

For example:

console.log(req.cookies.lang) //=> 'de'
setLocaleFromCookie()

Will then do:

setLocale('de')

setLocaleFromEnvironmentVariable()

To be used with some desktop application environment (like Electron or NW.js) or console. This method tries to get language code from LANG environment variable. For example, it get de from de_DE.UTF-8.

For example:

console.log(process.env.LANG) //=> 'en_US.UTF-8'
setLocaleFromEnvironmentVariable()

Will then do:

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.

Configuration

When you instantiate a new i18n object there are a few options that you can pass in. The only required option is locales.

locales

You can pass in the locales in two ways: As an array of strings or as an object of objects. For example:

locales: ['en', 'de']

This will set two locales (en and de) and read in the JSON contents of both translation files. (By default this is equal to "./locales/NAME.js", you can configure this by changing the directory and extension options.) Additionally when you pass in an array of locales the first locale is automatically set as the defaultLocale.

You can also pass in an object, like so:

locales: {
    "en": {
        "Hello": "Hello"
    },
    "de": {
        "Hello": "Hallo"
    }
}

In this particular case no files will ever be read when doing a translation. This is ideal if you are loading your translations from a different source. Note that no defaultLocale is set when you pass in an object, you'll need to set it yourself.

defaultLocale

You can explicitly define a default locale to be used in cases where .setLocale(locale) is used with an unknown locale. 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').

directory and extension

These default to "./locales" and ".js" accordingly. They are used for saving and reading the locale data files (see the locales option for more information on how this works).

When your server is in production mode it will read these files only once and then cache the result. It will not write any updated strings when in production mode.

When in development, or testing, mode the files will be read on every instantiation of the i18n object. Additionally newly-detected strings will be automatically added, and written out, to the locale JSON files.

A generated 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.

base

You can specify a function that will be used to extract base file name for each locale. It may be used for instance to keep in the locales only region-specific translations and move all what's shared to the base files.

It will take effect only when locales are provided as an array and base is a function that returns a string value. You can skip this mechanism for particular locale if base returns no value.

Each locale is merged with its base (if found) such that locale translations override the base. If the base file does not exist or is not parsable - it will not be created.

Following example takes de.js and en.js as bases respectively for each locale:

locales: ['at-de', 'de-de', 'at-en', 'de-en'],
base: function(locale) {
    return locale.slice(-2);
}

parse(data, [indent]) and dump(data)

Optional custom methods to override JSON.parse() and JSON.stringify(), respectively. One possible use for this is to allow for file formats other than JSON. For example:

var i18n = new (require('i18n-2'))({
    locales: ['en', 'de'],
    extension: '.yaml',
    parse: function (data) {
        return require('js-yaml').safeLoad(data);
    },
    dump: function (data) {
        return require('js-yaml').safeDump(data);
    }
});

request, subdomain, query and session

These options are to be used with Express.js or another framework that provides a request object. In order to use the subdomain and query options you must specify the request option, passing in the Express.js request object.

If you pass in a request object a new i18n property will be attached to it, containing the i18n instance.

Note that you probably won't need to use request directly, if you use expressBind it is taken care of automatically.

Setting the subdomain option to true will run the setLocaleFromSubdomain method automatically on every request.

Setting the session option to true will run the setLocaleFromSessionVar method automatically on every request.

By default the query option is set to true. Setting the query option to false will stop the setLocaleFromQuery method from running automatically on every request.

register

Copy the __, __n, getLocale, and isPreferredLocale methods over to the object specified by the register property.

var obj = {};
new i18n({ 'register': obj })
console.log( obj.__("Hello.") );

devMode

By default the devMode property is automatically set to be false if Node.js is in production mode and true otherwise. You can override this by setting a different value to the devMode option.

indent

Sets the indent string for JSON.stringify when updating the locale files. Defaults to a tab character. Might be useful when you use a source formatter in your project.

Using with Express.js

Load and Configure

In your app.js:

// load modules
var express = require('express'),
    i18n = require('i18n-2');

// Attach the i18n property to the express request object
// And attach helper methods for use in templates
i18n.expressBind(app, {
    // setup some locales - other locales default to en silently
    locales: ['en', 'de'],
    // change the cookie name from 'lang' to 'locale'
    cookieName: 'locale'
});

// This is how you'd set a locale from req.cookies.
// Don't forget to set the cookie either on the client or in your Express app.
app.use(function(req, res, next) {
    req.i18n.setLocaleFromCookie();
    next();
});

// Set up the rest of the Express middleware
app.use(app.router);
app.use(express.static(__dirname + '/public'));

Inside Your Express View

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

Inside Your Templates

(This example uses the Swig templating system.)

{% extends "page.swig" %}

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

Debugging

i18n-2 uses the debug module to output debug messages to the console. To output all debug messages, set the DEBUG environment variable:

DEBUG=i18n-2:*

This will output debugging messages from the module.

Changelog

  • 0.6.0: added setLocaleFromEnvironmentVariable()
  • 0.5.0: base files for locales
  • 0.4.7: configurable indent for locale json files
  • 0.4.6: bug fixes, new feature (dot notation & __n supporting object locales)
  • 0.4.5: a number of bug fixes
  • 0.4.4: fix typo
  • 0.4.3: fix issue with preferredLocale failing on useragents with no accept lang header
  • 0.4.2: fix some issues with cache init
  • 0.4.1: rename locale query string param to lang
  • 0.4.0: made settings contained, and scoped, to a single object (complete re-write by jeresig)
  • 0.3.5: fixed some issues, prepared refactoring, prepared publishing to npm finally
  • 0.3.4: merged pull request #13 from Fuitad/master and updated README
  • 0.3.3: merged pull request from codders/master and modified for backward compatibility. Usage and tests pending
  • 0.3.2: merged pull request #7 from carlptr/master and added tests, modified fswrite to do sync writes
  • 0.3.0: added configure and init with express support (calling guessLanguage() via 'accept-language')
  • 0.2.0: added plurals
  • 0.1.0: added tests
  • 0.0.1: start

i18n-node-2's People

Contributors

abdelilah avatar annelorraineuy avatar awilczek avatar bbqsrc avatar brankosekulic avatar cbaigorri avatar cleishm avatar dlongley avatar e-compton avatar eungjun-yi avatar fabioricali avatar framp avatar fuitad avatar fundon avatar gjuchault avatar jeresig avatar mashpie avatar msporny avatar pawelrychlik avatar richin13 avatar rikkertkoppes avatar sylvinus avatar timbru31 avatar wallali avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

i18n-node-2's Issues

Accept-Language header parsing ignores region tags?

Currently line 224:

(accept.match(/(^|,\s*)([a-z]+)/g) || []).forEach(function(locale) {

https://github.com/jeresig/i18n-node-2/blob/master/i18n.js#L224

This only grabs the language tag, not the region tag, so it doesn't differentiate between e.g. simplified Chinese (zh-CN) and traditional (zh-TW).

@jed's locale and @mozilla's i18n-abide both have parsing code that takes region tags and even score into account.

E.g. https://github.com/mozilla/i18n-abide/blob/master/lib/i18n.js#L269-L295

Hope that helps!

How access translations in a structured json?

How can I access translations in a structured json?

My json:

{
    "first-level": "shown",
    "test": {
        "lorem": "ipsum",
        "foo": "bar"
    }
}
req.i18n.__('first-level') // prints "shown"
req.i18n.__('test.lorem') // prints "test.lorem"

preferredLocale method is incorrect result.

I think this method has bug, my accept-language header is "ja,en-US;q=0.8,en;q=0.6,zh;q=0.4,hu;q=0.2" and locales is "['en', 'zh-CN']"๏ผŒconsole output "prefLocale" all is undefined. isPreferredLocale() always return false.

preferredLocale: function(req) {
        req = req || this.request;

        if (!req || !req.headers) {
            return;
        }

        var accept = req.headers["accept-language"] || "",
            regExp = /(^|,\s*)([a-z-]+)/gi,
            self = this,
            prefLocale;

        while ((match = regExp.exec(accept))){
            var locale = match[2];
            var parts = locale.split("-");

            if (!prefLocale) {
                if (self.locales[locale]) {
                    prefLocale = locale;
                } else if (parts.length > 1 && self.locales[parts[0]]) {
                    prefLocale = parts[0];
                }
            }
        }

        return prefLocale || this.defaultLocale;
    }

bind i18n in express

when we bind i18n in express
we can use __() method in our swig template.

why we could use __() methdod in our swig template ?

I have seen the i18n source code ,but I still can't figure these problem out?

Locale file overwritten on parsing error

If there is a json parsing error when i18n tries to open a locale file, it will create a new file and overwrite any existing one. Needless to say, it is not a good idea if you have spent a lot of time to create a file and then lose it simply because of a parsing error, which happened to me. I suggest you add fs.existsSync(localeFile) right above this.writeFile(locale) so that it will ONLY write file if localeFile doesn't exist.

        try {
            var localeFile = fs.readFileSync(file);

            try {
                // parsing filecontents to locales[locale]
                this.initLocale(locale, JSON.parse(localeFile));

            } catch (e) {
                console.error('unable to parse locales from file (maybe ' + file +
                    ' is empty or invalid json?): ', e);
            }

        } catch (e) {
            // unable to read, so intialize that file
            // locales[locale] are already set in memory, so no extra read required
            // or locales[locale] are empty, which initializes an empty locale.json file
            // @ec1980: Do not overwrite existing locale files
            if (!fs.existsSync(localeFile))
                this.writeFile(locale);
        }

BTW, if you are scratching your head trying to find out why your perfectly okay json file causes unexpected token parsing error, check that the file is not encoded with UTF-8 BOM, which is the default format on Windows. You can disable it in Visual Studio -> File -> Advanced Save Options -> Encoding -> Unicode(UTF-8 without signature).

i18n-node-2 for Hapi

Hey folks,

I've read both @jeresig posts about his i18n strategy (here and here) and I like what you've accomplished here. The thing is, I use Hapi instead of Express. Since this module is MIT licenced, I'm letting you know that I'm going to adapt it to work with Hapi and launch it as a plugin. Hope that's ok.

Splitting resources into multiple files

I would like to implement a feature of the library where localisation keys can be split amongst multiple files, which can be 'namespaced' by the file name. The reason is mainly for organisation on large sites where there may be hundreds or thousands of keys.

Things for consideration:

  • There would be the default locale file plus n 'namespaced' files
  • The default file could remain en.js whereas additional files could be countries-en.js, months-en.js, etc.
  • We would need some kind of marker to indicate which file to pull from if not the default. Something like i18n.__("countries.Germany") or i18n.__("Germany", "countries"). Either with some kind of marker in the key name as in the former example, or with a method parameter as in the latter (I'm leaning towards the latter)
  • If no file is specified, then the key is pulled from the default file
  • If a file is specified but a key name is not found, then it is searched for in the default file. If it is not found in the default file, then a key is created as in the current behaviour

Is there anything else I should consider?

Templating i18n with dot.js

I'm trying to make it work with dotjs like the swig example

<h1>{{ __("Welcome to:") }}</h1>

Dot.js uses {{=it.object}} for rendering variables, so {{=it.__("Welcome to:") }} or {{__("Welcome to:") }} does not work.
Should I pass the entire i18n object to the template in express and render like this:?

<h1>{{ =it.i18n.welcome_message }}</h1>

using __ and __n with express-handlebars views

When trying to access a locale property inside a handlebars view like follows:

  <h1>{{ __("someProperty") }} </h1>

I get a Parse Error with the following stack trace:

Error: Parse error on line 46:
... <h1>{{ __("someProperty") }} </h1>
-----------^
Expecting 'ID', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'INVALID'
    at Object.parseError (./node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js:218:19)
    at Object.parse (./node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js:287:30)
    at HandlebarsEnvironment.parse (./node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/base.js:45:43)
    at compileInput (./node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:477:19)
    at ret (./node_modules/express-handlebars/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:486:18)
    at ExpressHandlebars._renderTemplate ./node_modules/express-handlebars/lib/express-handlebars.js:247:12)
    at ExpressHandlebars.<anonymous> (./node_modules/express-handlebars/lib/express-handlebars.js:173:21)

I can only circumvent this by using:

  <h1>{{ __ "someProperty" }} </h1>

Is this the intended use for handlebars or am I missing some helper function ?

Extract strings beforehand

Is there a way to extract the translation strings beforehand, like with gulp or grunt? Seems foolish to translate only on page request, it would be better if it was done before build.

weird bug

I have translation files inside ./locales (en.js and it.js)
Sometimes the translation files itself are being modified, do you know what's causing this?

And also if I try to translate a missing key, it gets added automatically in the translation file

Edit: it seems it's a feature stated here Adds new strings on-the-fly when first used in your app
Is there an option to turn this off? it's messing my translation files.

Thank you for a very nice module, I hope you can help me with this.

New strings not saved

Hello,

As in the title, new strings are not saved to locales file in version 0.6.0

I added a quick fix in after line 329 like this:

if (!this.locales[locale][singular]) {
this.locales[locale][singular] = singular; // the fix
if (this.devMode) {
this.writeFile(locale);
}
}

Hope this will be fixed soon

Readfile on each request?

Firstoff: Nice rewrite - your thoughts would have been helpful, when contributed, although your approach acts more like middleware than as independent module.

Looking at your code ist seams like each reqeuest leads to a full read of translation files in a blocking manner. I doupt, this is intendet?

/intl/.. support

Not really an issue but is there a way to use /intl/language instead of using a query string to set the language?

Accept-Language is not used at all

prefLocale variable seems to be unused.
Or please give an example with ejs and language detection just based on accept-language header (no cookies and no subdomains).

how to use for ejs template?

exports.index = function(req, res){
res.render('index', { title: 'Welcome' , slides: req.i18n.__('slides') });
};
<h2><%= slides %></h2>

"express": "3.1.0"

I get this error 500 TypeError: Cannot call method '__' of undefined

fallback to default locale

When in production mode and a key does not exist in the current language, the key is displayed. We have some keys that are generated so we want to avoid showing them to the customer even if a translation in the current language is not available, instead we would like to show the translation in the default language.

Would it be ok to first check the translation in the default locale before returning the key?

Something like:

    if (!this.locales[locale][singular]) {
        if (this.devMode) {
            this.locales[locale][singular] = plural ? { one: singular, other: plural } : singular;
            this.writeFile(locale);
        } else {
            locale = this.defaultLocale;
        }
    }

License?

The mashpie/i18n-node base project is MIT, but no license is found in this repo, nor even referred to in the package.json.

Can this be rectified? I can't use this in my projects without a permissive license, and certainly, no license is not permissive. ๐Ÿ˜„

readFile error checking

While deploying my express 3.X app the first time to production, I ran into an issue with readFile where it wasn't able to read the locales directory, and also didn't have permissions to write new files. Relevant code from i18n.js (https://github.com/jeresig/i18n-node-2/blob/master/i18n.js#L268):

try {
    var localeFile = fs.readFileSync(file);
    //... continues
} catch (e) {
    this.writeFile(locale);
}

The end result is that my app complains that it can't find res.locals.__. Which makes sense - the middleware for express in expressBind calls new i18n(opts) which isn't successful, and thus (silently AFAIK) dies.

I think a reasonable thing to do might be to wrap the writeFile call in a try/catch and log an error. I can create a PR if that seems reasonable to you.

(PS: I'm not asking for help with my app - I just needed to explicitly pass the directory option)

nested json not work

I cannot use the following notation to access ___('contact.name')_

{
  "contact": {
      "name": "ๅง“ๅ"
  }

}

In i18n, this is allowed:

https://github.com/mashpie/i18n-node#object-notation

Instead of calling __("Hello") you might call __("greeting.formal") to retrieve a formal greeting from a translation document like this one:

"greeting": {
    "formal": "Hello",
    "informal": "Hi",
    "placeholder": {
        "formal": "Hello %s",
        "informal": "Hi %s"
    }
}

Update npm package

Could you update the npm package to the latest version?
The latest version that appear in npm is 0.4.6

Feature Request: General Place-holders

Would it be feasible to add support for general place-holders, where one localised string could refer to another one? This would enable common terms/phrases to be used in the content of others, without requiring parameter parsing at the code level.

For example;

{
   "contact service desk": "contact Service Desk (x3000)",
   "wrong id": "You've entered a wrong ID. Please try again, or {{contact service desk}} for further assistance",
   "db error": "Oops! Something is wrong with our servers. If this problem persists, please {{contact service desk}}"
}

In this way, any mention of contacting the Service Desk is consistent, and if the message (eg; the phone extension) changes, it's reflected across all other references.

Preferably, such a feature would be able to be enabled/disabled, and the place-holder syntax be customisable, to avoid clashes with real content syntax in templates, etc...

Here's an idea for an alternative syntax:

{
   "contact service desk": "contact Service Desk (x3000)",
   "wrong id": ["You've entered a wrong ID. Please try again, or %p for further assistance", "contact service desk"],
   "db error": ["Oops! Something is wrong with our servers. If this problem persists, please %p", "contact service desk"]
}

This syntax is similar to the "%s" place-holder syntax, but in this case, the substituted value is another i18n entry, named within the locales config.

__n() treats zero as singular

Given that we have the following function:

i18n.__n('%s movie', '%s movies', 0);

We get 0 movie back. Surely, this should be 0 movies? Is there a specific reason for this behaviour?

Cheers!

Setting locale form browser

Hello,

Is it possible to set the locale according to the language desired by the browser's Accept-language header ?

Using Module for Client-side Validation

Hi,

I have been trying how to work out how I might make use of i18n-2 for Client side validation I am using Happy.js (It is on top of JQuery Validation) but essentially I am trying to access the values from the client. Have you considered this or do you have any advice?

Thanks,

Andrew

Using i18n-2 in models

Hi!

I would to use i18n-2 in models js files, during data valitation.
How to access i18n2 functions?

I tried with

var i18n = require('i18n-2');

var validationError = i18n.__("Validation error");

but i get "i18n.__("Validation error")
^
TypeError: undefined is not a function"

What am i doing wrong?

Thanks

Testing to see if a translation exists

First of all thanks for sharing your hard work on i18n-2. Secondly I'd like to make a change but wanted to check it was something you're interested in first.

We're using the following snippet to localise 'Word document', 'Powerpoint document', etc.

req.i18n.__('fileType.' + attachment.type);                

If someone uploads a file type that has no translation for this will end up displaying 'fileType.xyz', when really we want to display nothing. We could maintain a list of known filetypes but I'd rather test to see if the translation is available.

var key = 'fileType.' + attachment.type;
req.i18n.__e(key) ? req.i18n.__(key) : '';

A further enhancement could be to pass the default value to req.i18n.__ but because of the var args I suspect this would require a new method, e.g.

req.i18n.__d(key, 'default template if key not found', 'arg1', 'arg2');

Not quite sure how this could be made to work with plurals though. Assuming you're happy with the above I'll fork and PR

Why convert locales to lowercase in methods like setLocaleFromQuery()?

Some methods like setLocaleFromQuery(), setLocaleFromCookie() will convert the locale to lower case. I see a lot of projects use uppercase letter in their i18n locales file name like en-US.json, zh-CN.json.
Also, the accept language in HTTP request header use the uppercase letter in the locale like en,zh-CN;q=0.8,zh;q=0.6.
So my question is why those methods convert locales to lowercase? Why not just keep the original case?

JSON Object notation

How to access text when the locale JSON file has nested text: For example:
{
"main-page": {
"title": "This is the main title"
}
}

Trying to access this via I18n.__("main-page.title") returns the string "main-page.title" instead of the intended "This is the main title".

Would you mind to clarify how to access nested JSON elements within the locale file?

release 0.4.7 on npmjs.com

Hi,

I'd like to use the latest version 0.4.7 which implements the dot notation for the translation keys.

Please update the release on npmjs.com

Cheers

Expess code from readme not working ...

Hi,

I am doing the following but this is not working for me.

At the top of my app.js, I have:

i18n = require('i18n-2');

In my app.configure method, I have at the end:

// multilanguage support
i18n.expressBind(app, {
// setup some locales - other locales default to en silently
locales: ['en', 'de'],
defaultLocale: 'en'
});

I have created a folder at the root where app.js is, named 'locales' and have a en.js file there with simply:

{
"Hello": "I am Hello in English"
}

i18n.("Hello") does not work anywhere in the app whereas in the request req.i18n.("Hello") does not work either.

The error I keep getting says something like "has not method __"

Can you help ?

Dictionaries inheritance proposal

It would be nice to have a feature like inheritance between dictionaries that could spare a lot of duplications.
Assuming we have files de-de.json and at-de.json - both extending the root de.json - we would provide the options:

{
    "locales": ["de-de", "at-de"],
    "extension": ".json",
    "parents": ".{2}\.json"
}

Where parents is a regexp for extracting parent name for each file. What do you think?

register option bug

I don't use the library but was reading the code for ideas. I think the code at line 28

i18n.registerMethods.forEach(function(method) {

should be

i18n.resMethods.forEach(function(method) {

Auto-detect supported locales from locales directory?

It would be great if I didn't have to specify the locales manually, if instead it could just be derived automatically by seeing which extension (e.g. .js) files were in directory (e.g. ./locales).

That way, you wouldn't need to maintain the list of locales in the configuration separately from the files you've had translated.

Would you be open to that? I might be able to put together a pull req if so. Thanks again for the great lib!

Compatiblity with Swig's filters

It would be quite useful to able to combine i18n with Swig's filters.
So far I couldn't make it work, is it supported?

{{ __('this is a test')|title }} // Should return 'This Is A Test'

Mocha test fails because of global var match

Hi,

I noticed that our mocha tests started failing when we added this module with the following error:

Error: global leak detected: match

We've solved it by running the mocha command with --globals match but it would be nice not to have to do this.

I've looked through i18n.js and I think that this could be solved by adding a var match;right before:

225: while ((match = regExp.exec(accept))){

I could make a pull request for it.

setLocaleFromSessionVar

  1. Why you didn't describe setLocaleFromSessionVar function in documentation?
  2. I propose to make variable in session configurable like cookieName.

Request with no "accept-language" header

"preferredLocale" function in i18n.js fails when there is no accept-language header. Proposed fix:

preferredLocale: function(req) {
        req = req || this.request;

        if (!req || !req.headers) {
            return;
        }

        var accept = req.headers["accept-language"],
            self = this,
            prefLocale;

        if (accept) {
            accept.match(/(^|,\s*)([a-z]+)/g).forEach(function(locale) {
                if (!prefLocale && self.locales[locale]) {
                    prefLocale = locale;
                }
            });
        } else {
            prefLocale = self.defaultLocale;
        }

        return prefLocale;
    }

Swig Problem

Hey,

First of all great work on this module. It was exactly what i was looking for.

I'm trying to use it with swig and it's not really working

I get the following error: " 500 TypeError: Cannot read property '__' of undefined".

Not sure what else i need to do to make it work.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.