Coder Social home page Coder Social logo

express-locale's Introduction

express-locale CI

Express middleware to determine the locale identifier of the incomming request.

It returns (only) full locale identifiers based on the middleware's configuration. Configuration defines possible sources, their order and, optionally, a whitelist. For performance reasons, on each request, remaining lookups are ignored as soon as a match is found.

Use version 1.x for Express 3 support and/or older Node versions.

Installation

npm install --save express-locale

Usage

import express from 'express';
import createLocaleMiddleware from 'express-locale';

express()
  .use(createLocaleMiddleware())
  .use((req, res) => {
    res.end(`Request locale: ${req.locale}`);
  })
  .listen(3000);

The locale property on the request object will contain an object with these properties:

{
	"source": "default",
	"language": "en",
	"region": "GB"
}

When using this object in a string context, its toString method returns the locale identifier (en-GB in the example above).

Note: only full locales (language-REGION) are returned, but a mapping of languages to a default locale can be provided as a lookup.

Configuration

You can pass a configuration object to createLocaleMiddleware() with the default being:

{
  "priority": ["accept-language", "default"],
  "default": "en-GB"
}

This tells the middleware to use 2 sources in order: accept-language, which has no configuration, and default which is set to en-GB.

The name of the lookup used in the priority list always matches the configuration key.

Options

  • priority Array, default: ['accept-language', 'default']

    Defines the order of lookups. The first lookup to return a full locale will be the final result.

    Built-in lookups:

    • cookie
    • query
    • hostname
    • accept-language
    • map
    • default

    Read below on how to add custom lookups.

  • allowed Array

    If provided, each lookup's results are validated against this whitelist.

    Note: since this validation happens after each lookup, values which will still pass through the next lookup (like when using map) need to also be whitelisted as in the example below. This will likely be addressed in a future version (see #20).

    // example
    createLocaleMiddleware({
      priority: ['accept-language', 'cookie', 'map'],
      map: {
        'en': 'en-US',
        'fr': 'fr-CA'
      },
      allowed: ['en', 'fr', 'en-US', 'fr-CA']
    });
  • requestProperty String, default 'locale'

    The property on the request object (req) in which the locale is set.

  • cookie Object, default '{name: 'locale'}'

    The name of the cookie that contains the locale for the cookie lookup.

    Use with cookie-parser middleware.

  • query Object, default '{name: 'locale'}'

    The name of the query string parameter that contains the locale for the query lookup.

  • hostname Object

    A mapping of hostnames to locales for the hostname lookup.

    // example
    createLocaleMiddleware({
      priority: ['hostname'],
      map: {
        'en.wikipedia.org': 'en-US',
        'nl.wikipedia.org': 'nl-NL'
      }
    });
  • map Object

    Maps lookup results that return only a language to a full locale.

    // example
    createLocaleMiddleware({
      priority: ['accept-language', 'cookie', 'map'],
      map: {
        'en': 'en-US',
        'fr': 'fr-CA'
      }
    });
  • default String, default 'en-GB'

    The default locale for the default lookup.

  • lookups Object

    Add custom lookups or overwrite the default ones by using the lookups property.

    // example
    createLocaleMiddleware({
      priority: ['custom'],
      lookups: {
        custom: (req) => req.ip === '127.0.0.1' ? 'en-US' : undefined
      }
    });

express-locale's People

Contributors

benpptung avatar huhgawz avatar marionebl avatar nachaos avatar smhg avatar stutrek 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

Watchers

 avatar  avatar  avatar  avatar

express-locale's Issues

The map parameter shows no effect

Hi

I use the middleware as follows:
app.use( createLocaleMiddleware({ map: { de: "de-DE", en: "en-GB" } }) );

When i send a request with Accept-Language: de i expect the locale to be translated based on the map. In the example de becomes de-DE and req.locale will be de. But unfortunately req.locale is always en (default value).

Does the parameter map have to be passed differently?
How can I use the parameter map if there is only a language without region in the header parameter accept-language?

Thanks & regards

allow for setting language not based on region

I've seen that if I set a language without the region (like 'pt' instead of 'pt-BR' or 'en' instead of 'en-US') in the cookie, the locale isn't properly set.

Is there a way to disable this? Is this a bug or an unimplemented feature?

Error: Cannot find module 'babel-polyfill'

I'm getting this error when running in production after transpiling my code (no babel-node anymore).

This happens not only because of that, but because babel-polyfill is listed as a dev-dependency, but it leaked into the transpiled file.

add config sanity checks

As mentioned in this PR by @Bramzor:

It would be good to have non-production warning messages about conflicting configuration options.

This would mainly be an evaluation of the allowed property against locales defined inside configs of individual lookups.

Additionally, the current priority property's check should be refactored similarly.

Always defaults

I have the following lines on a page request:

console.log(req.header('Accept-Language'));
console.log(req.locale);

which produce the following output:

sv-SE,sv-FI;q=0.8,en-US;q=0.5,en;q=0.3
{ code: 'en_GB', source: 'default' }

I've configured the module like this:

app.use(locale({
    priority: ['accept-language', 'cookie', 'domain', 'default']
}));

so clearly I'm interested in the 'accept-language' first and my browser is providing it as sv-SE but the module returns the default. what have I missed to configure properly?

Parse short codes

It would be nice to have

req.locale.code = 'en_UK';
req.locale.short = 'en'

This way we don't need to manually match all english based browsers in our code.

1.0.0 roadmap

  • Split up lookups into separate files
  • Lookup functions should be thunks that take middleware options
  • Make adding custom lookups more intuitive (instead of config + method call on instance)
  • Add a querytstring lookup
  • Add more real-world (lookup combinations) tests
  • Add changelog

Future versions:

  • Test individual components
  • Add a path lookup
  • Add an IP geocoding lookup (see #5)

Add option to limit accepted locales

I'd really like to have an option to limit accepted locales to a predefined set.
Something like:

app.use(localeMiddleware({
    priority: ["session", "accept-language", "default"],
    "accept-language": ["en_US", "kh_KH"],
    "default": "en_US",
    lookups: {
        session: (req) => req.session.locale ? languages.map(req.session.locale) : undefined
    },
}));

Note set of allowed locales for 'accept-language' source. So if user visits with 'accept-language: kh_KH' we got kh_KH locale, but if he visits with ru_RU or any other not listed in allowed set - this lookup produces null or undefined and falls back to next (default) lookup.

Date.toLocaleString (native) - RangeError: Invalid language tag: en_US

I just realized Date.toLocaleString expect en-US instead of en_US, and I know the following from the this

when you’re configuring Unix environment, you have to define POSIX locale with underscore as en_US.UTF-8. On the other hand, if you’re trying to set locale (called CultureInfo) in your C# app it will be en-US...IETF locale tags are used in other modern standards such as those related to HTML, World Wide Web Consortium

I'm wondering if we should put a note in README to highlight that we need to convert en_US to en-US? Also, add another method to get the locale string?

Because, if we use req.locale.toString() and put the locale into Date.toLocaleString(), it will throw RangeError: Invalid language tag.

figure out missing region information

@ekkis wrote:
I notice that setting my language preference to Swedish (in Chrome) sets the language to 'sv' but includes no locale, so whereas I might have 'sv-SE' (Sweden), I could also have 'sv-FI' (Finland) but without locale I don't know how to properly format a price (because I don't know the currency). that seems to be browser dependent though as Chrome doesn't set it but Firefox does. so is there a way to tell the locale when the browser has not set it?

Unclear interaction between `map` and `allowed`

The map parameter has no effect when the list of allowed locales is provided and it only includes full locale tags. This is not clear from the documentation. It this behavior desired at all?

Example configuration:

expressLocale({
  priority: ['query', 'map', 'default'],
  allowed: ['en-CA', 'fr-CA'],
  map: { en: 'en-CA', fr: 'fr-CA' },
})

With this configuration a request with query string ?locale=fr will not have locale set to fr-CA.

If this is indeed a desired behavior it would be nice to mention it in the documentation. Or is this a bug?

Query lookup doesn’t appear to be bundled

Setting up the middleware with config with express-locale version ^1.0.0

app.use(locale({
  priority: ['query', 'cookie', 'accept-language', 'hostname', 'map', 'default'],
  ...
}))

I get the error Error: Locale lookup source method "query" not defined

When inspecting the bundled code, it does indeed appear to be missing...

lib/index.js:

var LOOKUPS = {
  'cookie': _cookie2.default,
  'hostname': _hostname2.default,
  'accept-language': _acceptLanguage2.default,
  'default': _default2.default
};

Any ideas? 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.