Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@lion/localize

Package Overview
Dependencies
Maintainers
1
Versions
102
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lion/localize - npm Package Compare versions

Comparing version 0.4.1 to 0.4.2

12

CHANGELOG.md

@@ -6,2 +6,14 @@ # Change Log

## [0.4.2](https://github.com/ing-bank/lion/compare/@lion/localize@0.4.1...@lion/localize@0.4.2) (2019-07-09)
### Bug Fixes
* **localize:** don't fire localeChanged event if set to the same locale ([3115c50](https://github.com/ing-bank/lion/commit/3115c50))
* **localize:** observe <html lang> attribute ([18589f4](https://github.com/ing-bank/lion/commit/18589f4))
## [0.4.1](https://github.com/ing-bank/lion/compare/@lion/localize@0.4.0...@lion/localize@0.4.1) (2019-06-27)

@@ -8,0 +20,0 @@

4

package.json
{
"name": "@lion/localize",
"version": "0.4.1",
"version": "0.4.2",
"description": "The localization system helps to manage localization data split into locales and automate its loading",

@@ -44,3 +44,3 @@ "author": "ing-bank",

},
"gitHead": "187d50b6bc14b5c9a2fec3e4908a242513257617"
"gitHead": "a598a47dabccc92e68f12411b7b613a8e5132762"
}

@@ -9,3 +9,4 @@ import { LocalizeManager } from './LocalizeManager.js';

export function setLocalize(newLocalize) {
localize.teardown();
localize = newLocalize;
}

@@ -14,5 +14,6 @@ import MessageFormat from '@bundled-es-modules/message-format/MessageFormat.js';

if (!this.locale) {
this.locale = 'en-GB';
if (!document.documentElement.lang) {
document.documentElement.lang = 'en-GB';
}
this._autoLoadOnLocaleChange = !!params.autoLoadOnLocaleChange;

@@ -24,4 +25,10 @@ this.__storage = {};

this.formatNumberOptions = { returnIfNaN: '' };
this._setupHtmlLangAttributeObserver();
}
teardown() {
this._teardownHtmlLangAttributeObserver();
}
// eslint-disable-next-line class-methods-use-this

@@ -34,3 +41,7 @@ get locale() {

const oldLocale = document.documentElement.lang;
this._teardownHtmlLangAttributeObserver();
document.documentElement.lang = value;
this._setupHtmlLangAttributeObserver();
this._onLocaleChanged(value, oldLocale);

@@ -96,2 +107,21 @@ }

_setupHtmlLangAttributeObserver() {
if (!this._htmlLangAttributeObserver) {
this._htmlLangAttributeObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
this._onLocaleChanged(document.documentElement.lang, mutation.oldValue);
});
});
}
this._htmlLangAttributeObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ['lang'],
attributeOldValue: true,
});
}
_teardownHtmlLangAttributeObserver() {
this._htmlLangAttributeObserver.disconnect();
}
_isNamespaceInCache(locale, namespace) {

@@ -188,2 +218,5 @@ return !!(this.__storage[locale] && this.__storage[locale][namespace]);

_onLocaleChanged(newLocale, oldLocale) {
if (newLocale === oldLocale) {
return;
}
this.dispatchEvent(new CustomEvent('localeChanged', { detail: { newLocale, oldLocale } }));

@@ -190,0 +223,0 @@ if (this._autoLoadOnLocaleChange) {

import { expect } from '@open-wc/testing';
import sinon from 'sinon';

@@ -25,6 +26,12 @@ import { LionSingleton } from '@lion/core';

const oldLocalize = localize;
const newLocalize = {};
const oldLocalizeTeardown = localize.teardown;
localize.teardown = sinon.spy();
const newLocalize = { teardown: () => {} };
setLocalize(newLocalize);
expect(localize).to.equal(newLocalize);
expect(oldLocalize.teardown.callCount).to.equal(1);
setLocalize(oldLocalize);
localize.teardown = oldLocalizeTeardown;
});

@@ -31,0 +38,0 @@

@@ -1,2 +0,3 @@

import { expect, oneEvent } from '@open-wc/testing';
import { expect, oneEvent, aTimeout } from '@open-wc/testing';
import sinon from 'sinon';
import { fetchMock } from '@bundled-es-modules/fetch-mock';

@@ -13,2 +14,4 @@ import { setupFakeImport, resetFakeImport, fakeImport } from './test-utils.js';

describe('LocalizeManager', () => {
let manager;
beforeEach(() => {

@@ -20,2 +23,6 @@ // makes sure that between tests the localization is reset to default state

afterEach(() => {
manager.teardown();
});
afterEach(() => {
fetchMock.restore();

@@ -26,3 +33,3 @@ resetFakeImport();

it('initializes locale from <html> by default', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
expect(manager.locale).to.equal('en-GB');

@@ -32,3 +39,3 @@ });

it('syncs locale back to <html> if changed', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.locale = 'nl-NL';

@@ -40,3 +47,3 @@ expect(document.documentElement.lang).to.equal('nl-NL');

document.documentElement.lang = '';
const manager = new LocalizeManager();
manager = new LocalizeManager();
expect(manager.locale).to.equal('en-GB');

@@ -46,10 +53,38 @@ expect(document.documentElement.lang).to.equal('en-GB');

it('fires "localeChanged" event with detail.newLocale and detail.oldLocale if locale was changed', async () => {
const manager = new LocalizeManager();
setTimeout(() => {
it('has teardown() method removing all side effects', () => {
manager = new LocalizeManager();
const disconnectObserverSpy = sinon.spy(manager._htmlLangAttributeObserver, 'disconnect');
manager.teardown();
expect(disconnectObserverSpy.callCount).to.equal(1);
});
describe('"localeChanged" event with detail.newLocale and detail.oldLocale', () => {
it('fires "localeChanged" event if locale was changed via manager', async () => {
manager = new LocalizeManager();
setTimeout(() => {
manager.locale = 'en-US';
});
const event = await oneEvent(manager, 'localeChanged');
expect(event.detail.newLocale).to.equal('en-US');
expect(event.detail.oldLocale).to.equal('en-GB');
});
it('fires "localeChanged" event if locale was changed via <html lang> attribute', async () => {
manager = new LocalizeManager();
setTimeout(() => {
document.documentElement.lang = 'en-US';
});
const event = await oneEvent(manager, 'localeChanged');
expect(event.detail.newLocale).to.equal('en-US');
expect(event.detail.oldLocale).to.equal('en-GB');
});
it('does not fire "localeChanged" event if it was set to the same locale', () => {
manager = new LocalizeManager();
const eventSpy = sinon.spy();
manager.addEventListener('localeChanged', eventSpy);
manager.locale = 'en-US';
manager.locale = 'en-US';
expect(eventSpy.callCount).to.equal(1);
});
const event = await oneEvent(manager, 'localeChanged');
expect(event.detail.newLocale).to.equal('en-US');
expect(event.detail.oldLocale).to.equal('en-GB');
});

@@ -59,3 +94,3 @@

it('allows to provide inline data', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -95,3 +130,3 @@ manager.addData('en-GB', 'lion-hello', { greeting: 'Hi!' });

it('prevents mutating existing data for the same locale & namespace', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -114,3 +149,3 @@ manager.addData('en-GB', 'lion-hello', { greeting: 'Hi!' });

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -131,3 +166,3 @@ await manager.loadNamespace({

const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.locale = 'en-US';

@@ -153,3 +188,3 @@

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -173,3 +208,3 @@ await manager.loadNamespaces([

const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.locale = 'en-US';

@@ -196,3 +231,3 @@

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -211,3 +246,3 @@ await manager.loadNamespace({

it('throws if both locale and language files could not be loaded', async () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -235,3 +270,3 @@ try {

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -256,3 +291,3 @@ manager.setupNamespaceLoader('my-component', async locale => {

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -281,3 +316,3 @@ manager.setupNamespaceLoader('my-defaults', async locale => {

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -302,3 +337,3 @@ manager.setupNamespaceLoader(/my-.+/, async (locale, namespace) => {

const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -321,22 +356,31 @@ manager.setupNamespaceLoader(/my-.+/, async (locale, namespace) => {

describe('loading extra features', () => {
it('has a Promise "loadingComplete" that resolved once all pending loading is done', async () => {
describe('{ autoLoadOnLocaleChange: true }', () => {
it('loads namespaces automatically when locale is changed via manager', async () => {
setupFakeImport('./my-component/en-GB.js', { default: { greeting: 'Hello!' } });
const manager = new LocalizeManager();
setupFakeImport('./my-component/nl-NL.js', { default: { greeting: 'Hallo!' } });
manager.loadNamespace({
manager = new LocalizeManager({ autoLoadOnLocaleChange: true });
await manager.loadNamespace({
'my-component': locale => fakeImport(`./my-component/${locale}.js`, 25),
});
expect(manager.__storage).to.deep.equal({});
expect(manager.__storage).to.deep.equal({
'en-GB': { 'my-component': { greeting: 'Hello!' } },
});
manager.locale = 'nl-NL';
await manager.loadingComplete;
expect(manager.__storage).to.deep.equal({
'en-GB': { 'my-component': { greeting: 'Hello!' } },
'nl-NL': { 'my-component': { greeting: 'Hallo!' } },
});
});
it('supports auto loading of namespaces when locale has been changed', async () => {
it('loads namespaces automatically when locale is changed via <html lang> attribute', async () => {
setupFakeImport('./my-component/en-GB.js', { default: { greeting: 'Hello!' } });
setupFakeImport('./my-component/nl-NL.js', { default: { greeting: 'Hallo!' } });
const manager = new LocalizeManager({ autoLoadOnLocaleChange: true });
manager = new LocalizeManager({ autoLoadOnLocaleChange: true });

@@ -351,3 +395,4 @@ await manager.loadNamespace({

manager.locale = 'nl-NL';
document.documentElement.lang = 'nl-NL';
await aTimeout(); // wait for mutation observer to be called
await manager.loadingComplete;

@@ -360,3 +405,19 @@

});
});
describe('loading extra features', () => {
it('has a Promise "loadingComplete" that resolved once all pending loading is done', async () => {
setupFakeImport('./my-component/en-GB.js', { default: { greeting: 'Hello!' } });
manager = new LocalizeManager();
manager.loadNamespace({
'my-component': locale => fakeImport(`./my-component/${locale}.js`, 25),
});
expect(manager.__storage).to.deep.equal({});
await manager.loadingComplete;
expect(manager.__storage).to.deep.equal({
'en-GB': { 'my-component': { greeting: 'Hello!' } },
});
});
it('loads namespace only once for the same locale', async () => {

@@ -370,3 +431,3 @@ let called = 0;

};
const manager = new LocalizeManager();
manager = new LocalizeManager();

@@ -385,3 +446,3 @@ await Promise.all([

const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.addData('en-GB', 'my-component', { greeting: 'Hello!' });

@@ -412,3 +473,3 @@

it('gets the message for the key in the format of "namespace:name"', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.addData('en-GB', 'my-ns', { greeting: 'Hello!' });

@@ -419,3 +480,3 @@ expect(manager.msg('my-ns:greeting')).to.equal('Hello!');

it('supports nested names in the format of "namespace:path.to.deep.name"', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.addData('en-GB', 'my-ns', { 'login-section': { greeting: 'Hello!' } });

@@ -426,3 +487,3 @@ expect(manager.msg('my-ns:login-section.greeting')).to.equal('Hello!');

it('supports variables', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.addData('en-GB', 'my-ns', { greeting: 'Hello {name}!' });

@@ -433,3 +494,3 @@ expect(manager.msg('my-ns:greeting', { name: 'John' })).to.equal('Hello John!');

it('supports Intl MessageFormat proposal for messages', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.addData('en-GB', 'my-ns', {

@@ -449,3 +510,3 @@ date: 'I was written on {today, date}.',

it('takes into account globally changed locale', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.locale = 'nl-NL';

@@ -458,3 +519,3 @@ manager.addData('en-GB', 'my-ns', { greeting: 'Hi!' });

it('allows to provide a different locale for specific call', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
manager.addData('en-GB', 'my-ns', { greeting: 'Hi!' });

@@ -472,3 +533,3 @@ manager.addData('nl-NL', 'my-ns', { greeting: 'Hey!' });

it('allows to provide an ordered list of keys where the first resolved is used', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
const keys = ['overridden-ns:greeting', 'default-ns:greeting'];

@@ -483,3 +544,3 @@ expect(manager.msg(keys)).to.equal('');

it('throws a custom error when namespace prefix is missing', () => {
const manager = new LocalizeManager();
manager = new LocalizeManager();
const msgKey = 'greeting';

@@ -486,0 +547,0 @@ manager.addData('en-GB', 'my-ns', { [msgKey]: 'Hello!' });

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