New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-intl-db

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-intl-db - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

2

package.json
{
"name": "react-intl-db",
"version": "0.0.2",
"version": "0.0.3",
"description": "Load app translations automatically partitioned by domain",

@@ -5,0 +5,0 @@ "main": "lib/domaindb.js",

react-intl-db
=============
Load i18n domains for Format.js's React integration.
Introduction
------------
To install the required dependencies::
This package contains i18n domain and message id support for the
[React integration](http://formatjs.io/react/) of
[Format.js](http://formatjs.io). It also makes it possible to load
translation messages dynamically from a backend or other source.
$ npm install
Usage
-----
First we can define a loader that shows how to load the messages from
the server. It should return a `Promise`:
function loader(localeId, domainId) {
// return a promise with the messages
}
The loader gets the id of the locale to be loaded and the id of the
domain. The locale is an ISO locale; something like `en-US`. The
domain id you make up yourself. Typically each UI application would
use its own separate domain string.
The loader should return a promise that resolves to an object with
message id keys and message values, for this particular locale and
domain. The loader could for instance load its information from the
server:
function loader(localeId, domainId) {
return fetch(`http://example.com/i18n/${localeId}/${domainId}`);
}
The next step is to create an `IntDomainDatabase` with this loader:
import {IntlDomainDatabase} from `react-intl-db`;
i18ndb = new IntlDomainDatabase(loader);
You can supply the `i18ndb` with default messages as well. These
messages are used when no loader argument is passed in, or if the
loader returns a promise that resolves to `null` or `undefined` for
that domain.
i18ndb.defaultMessages({
domainId: 'mydomain',
messages: {
'hello': "Hello world!",
'photos': ('{name} took {numPhotos, plural,' +
' =0 {no photos}' +
' =1 {one photo}' +
' other {# photos}' +
'} on {takenDate, date, long}.')
}
})
We can now start using this i18ndb with React. You first need to make
the root component of the application aware of the i18n db:
const IntlApp = i18ndb.makeIntl(App)
You now have a new `IntlApp` React component that is like `App``, but
takes the `locales` prop. This should contain the locale you want
the application to use:
<IntlApp locales="en-US" />
`IntlApp` now also makes sure that the right messages are loaded using
the loader before rendering begins.
We can now create a `Format` component for a particular domain that a
UI application can then use:
const Format = i18ndb.makeFormat('myapp')
The argument to `makeFormat` is the name of the application's domain.
Once you have the `Format` component you can use it with a `messageId` prop:
<Format messageId="hello" />
When you use this in code, the system automatically looks up the message id
`hello` for the domain `myapp` and inserts it.
Some messages take variables. You can pass them in like you do for
`FormattedMessage` from `react-intl`:
<Format
messageId="photos"
name="Annie"
numPhotos={1000}
takenDate={Date.now()} />
Sometimes you need to be able render a formatted message in code,
for instance when you want to set the value of a prop. You can do by
creating a helper function:
const formatStr = i18ndb.makeFormatStr('myapp')
You use it by passing the component (typically `this`) as the first
argument, as it needs this to obtain the locale information from the
context:
render() {
return <input value={formatStr(this, 'myMessageId')} />;
}
Limitation
----------
Currently `react-intl-db` only properly supports a single locale per
application, not a list of locales. You can instead make sure the
right fallback is happening in the loader. I'm also happy to receive
code that lists this limitation!
Example application
-------------------
There is example code included in `src/example.jsx`.
First install the required dependencies:
$ npm install
To try this out can use the webpack-dev-server, which automatically
rebuilds the bundle and serves the content in ``build`` like this::
rebuilds the bundle and serves the content in ``build`` like this:
$ webpack-dev-server --progress --colors --content-base build
$ webpack-dev-server --progress --colors --content-base build
You can then access the app http://localhost:8080
You can then access the example app on http://localhost:8080

@@ -6,4 +6,4 @@ import React from 'react';

export class IntlDomainDatabase {
constructor(defaultDomains, loader) {
this.defaultDomains = defaultDomains;
constructor(loader) {
this.defaultDomains = {};
this.locales = {};

@@ -16,2 +16,5 @@ this.loader = loader;

}
defaultMessages(data) {
this.defaultDomains[data.domainId] = data.messages;
}
loadMessages(localeId, domainId) {

@@ -27,4 +30,8 @@ let domains = this.locales[localeId];

if (this.loader === undefined) {
return Promise.reject(new Error(
"Loader not defined and cannot find domain: " + domainId));
const messages = this.defaultDomains[domainId];
if (!messages) {
return Promise.reject(new Error(
"Loader not defined and cannot find domain: " + domainId));
}
return Promise.resolve(messages);
}

@@ -63,2 +70,25 @@ return this.loader(localeId, domainId).then(messages => {

}
getMessageById(localeId, domainId, path) {
const messages = this.getMessages(localeId, domainId);
const pathParts = path.split('.');
let message;
try {
message = pathParts.reduce((obj, pathPart) => {
return obj[pathPart];
}, messages);
} finally {
if (message === undefined) {
throw new ReferenceError(
'Could not find Intl message: ' + path);
}
}
return message;
}
makeFormatStr(domainId) {
const db = this;
this.neededDomainIds.add(domainId);
return function(component, path) {
return db.getMessageById(getLocaleId(component), domainId, path);
};
}
makeFormat(domainId) {

@@ -75,23 +105,3 @@ const db = this;

getMessageById(path) {
const locales = this.props.locales || this.context.locales;
let localeId;
if (Array.isArray(locales)) {
localeId = locales[0];
} else {
localeId = locales;
}
const messages = db.getMessages(localeId, domainId);
const pathParts = path.split('.');
let message;
try {
message = pathParts.reduce((obj, pathPart) => {
return obj[pathPart];
}, messages);
} finally {
if (message === undefined) {
throw new ReferenceError(
'Could not find Intl message: ' + path);
}
}
return message;
return db.getMessageById(getLocaleId(this), domainId, path);
},

@@ -130,1 +140,9 @@ render() {

}
function getLocaleId(component) {
const locales = component.props.locales || component.context.locales;
if (Array.isArray(locales)) {
return locales[0];
}
return locales;
}

@@ -5,3 +5,4 @@ import chai from 'chai';

import dummy from 'intl';
import {FormattedMessage} from 'react-intl';
import {FormattedMessage } from 'react-intl';
import ReactIntl from 'react-intl';
import { IntlDomainDatabase } from '../src/domaindb';

@@ -16,3 +17,3 @@

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);
return db.loadMessages('en-US', 'foo').then((messages) => {

@@ -28,3 +29,3 @@ assert.deepEqual(messages, {'foo': 'bar'});

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);
db.loadMessages('en-US', 'foo').then((messages) => {

@@ -45,3 +46,3 @@ assert.equal(loads, 1);

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);
db.loadMessages('en-US', 'a').then((messages) => {

@@ -74,3 +75,3 @@ assert.equal(loads.a, 1);

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);
db.loadMessages('en', 'a').then((messages) => {

@@ -93,10 +94,10 @@ assert.equal(loads.en.a, 1);

test("default domains", function(done) {
let defaultDomains = {
'a': {'aDefault': 'A_DEFAULT'},
'b': {'bDefault': 'B_DEFAULT'}
};
function myloader(localeId, domainId) {
return Promise.resolve(null);
}
const db = new IntlDomainDatabase(defaultDomains, myloader);
const db = new IntlDomainDatabase(myloader);
db.defaultMessages({domainId: 'a',
messages: {'aDefault': 'A_DEFAULT'}});
db.defaultMessages({domainId: 'b',
messages: {'bDefault': 'B_DEFAULT'}});
db.loadMessages('en-US', 'a').then((messages) => {

@@ -108,3 +109,3 @@ assert.deepEqual(messages, {'aDefault': 'A_DEFAULT'});

test("no loader", function(done) {
const db = new IntlDomainDatabase({});
const db = new IntlDomainDatabase();
db.loadMessages('en-US', 'a').catch((e) => {

@@ -116,2 +117,11 @@ assert.equal(e.message,

});
test("no loader with default domains", function(done) {
const db = new IntlDomainDatabase();
db.defaultMessages({domainId: 'a',
messages: {'aDefault': 'A_DEFAULT'}});
db.loadMessages('en-US', 'a').then((messages) => {
assert.deepEqual(messages, {'aDefault': 'A_DEFAULT'});
done();
});
});
test("no messages for domain", function(done) {

@@ -121,3 +131,3 @@ function myloader(localeId, domainId) {

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);
db.loadMessages('en-US', 'a').catch((e) => {

@@ -135,3 +145,3 @@ assert.equal(e.message,

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);

@@ -149,3 +159,5 @@ db.neededDomainIds.add('a');

const renderer = React.addons.TestUtils.createRenderer();
const db = new IntlDomainDatabase({'a': {'foo': 'bar'}});
const db = new IntlDomainDatabase();
db.defaultMessages({domainId: 'a',
messages: {'foo': 'bar'}});
const Format = React.createFactory(db.makeFormat('a'));

@@ -162,2 +174,25 @@ const formatted = Format({'messageId': 'foo', 'locales': 'en-US'});

test("makeFormatStr with default", function() {
const renderer = React.addons.TestUtils.createRenderer();
const db = new IntlDomainDatabase();
db.defaultMessages({domainId: 'a',
messages: {'foo': 'bar'}});
const formatStr = db.makeFormatStr('a');
const Element = React.createClass({
mixins: [ReactIntl.IntlMixin],
render() {
return formatStr(this, 'foo');
}
});
const ElementFactory = React.createFactory(Element);
const formatted = ElementFactory({'locales': 'en-US'});
renderer.render(formatted);
const output = renderer.getRenderOutput();
assert.deepEqual(
output,
'bar');
});
test("makeFormat with loader", function(done) {

@@ -180,3 +215,3 @@ const locales = {

}
const db = new IntlDomainDatabase({}, myloader);
const db = new IntlDomainDatabase(myloader);

@@ -183,0 +218,0 @@ const renderer = React.addons.TestUtils.createRenderer();

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc