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

@shopify/react-i18n

Package Overview
Dependencies
Maintainers
13
Versions
289
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopify/react-i18n - npm Package Compare versions

Comparing version 1.1.2 to 1.1.3

8

CHANGELOG.md

@@ -11,2 +11,10 @@ # Changelog

## [1.1.3] - 2019-04-17
### Fixed
- Fixed a number of performance issues with resolving asynchronous translations ([#659](https://github.com/Shopify/quilt/pull/659))
## [1.1.1] - 2019-04-12
### Changed

@@ -13,0 +21,0 @@

3

dist/context.d.ts

@@ -5,2 +5,3 @@ import * as React from 'react';

export declare const I18nContext: React.Context<I18nManager | null>;
export declare const I18nParentsContext: React.Context<I18n | null>;
export declare const I18nIdsContext: React.Context<string[]>;
export declare const I18nParentContext: React.Context<I18n | null>;

@@ -6,2 +6,3 @@ "use strict";

exports.I18nContext = React.createContext(null);
exports.I18nParentsContext = React.createContext(null);
exports.I18nIdsContext = React.createContext([]);
exports.I18nParentContext = React.createContext(null);
import * as React from 'react';
import { I18n } from './i18n';
import { RegisterOptions } from './manager';
export declare function useI18n({ id, fallback, translations, }?: Partial<RegisterOptions>): [I18n, React.ComponentType<{
declare type Result = [I18n, React.ComponentType<{
children: React.ReactNode;
}>];
export declare function useSimpleI18n(): I18n;
export declare function useI18n(options?: Partial<RegisterOptions>): Result;
export {};

@@ -5,6 +5,6 @@ "use strict";

var React = tslib_1.__importStar(require("react"));
var react_hooks_1 = require("@shopify/react-hooks");
var i18n_1 = require("./i18n");
var context_1 = require("./context");
function useI18n(_a) {
var _b = _a === void 0 ? {} : _a, id = _b.id, fallback = _b.fallback, translations = _b.translations;
function useI18n(options) {
var manager = React.useContext(context_1.I18nContext);

@@ -14,38 +14,71 @@ if (manager == null) {

}
var parentI18n = React.useContext(context_1.I18nParentsContext);
var parentIds = parentI18n ? parentI18n.ids || [] : [];
// eslint-disable-next-line react-hooks/exhaustive-deps
var ids = React.useMemo(function () { return (id ? tslib_1.__spread([id], parentIds) : parentIds); }, tslib_1.__spread([
id
], parentIds));
var registerOptions = React.useRef(options);
if (shouldRegister(registerOptions.current) !== shouldRegister(options)) {
throw new Error('You switched between providing registration options and not providing them, which is not supported.');
}
// Yes, this would usually be dangerous. But just above this line, we check to make
// sure that they never switch from the case where `options == null` to `options != null`,
// so we know that a given use of this hook will only ever hit one of these two cases.
/* eslint-disable react-hooks/rules-of-hooks */
if (options == null) {
return useSimpleI18n(manager);
}
else {
return useComplexI18n(options, manager);
}
/* eslint-enable react-hooks/rules-of-hooks */
}
exports.useI18n = useI18n;
function useComplexI18n(_a, manager) {
var id = _a.id, fallback = _a.fallback, translations = _a.translations;
var parentIds = React.useContext(context_1.I18nIdsContext);
// Parent IDs can only change when a parent gets added/ removed,
// which would cause the component using `useI18n` to unmount.
// We also don't support the `id` changing between renders. For these
// reasons, it's safe to just store the IDs once and never let them change.
var ids = react_hooks_1.useLazyRef(function () { return (id ? tslib_1.__spread([id], parentIds) : parentIds); });
if (id && (translations || fallback)) {
manager.register({ id: id, translations: translations, fallback: fallback });
}
var _c = tslib_1.__read(React.useState(function () {
var translations = manager.state(ids).translations;
return new i18n_1.I18n(translations, manager.details, ids);
}), 2), i18n = _c[0], setI18n = _c[1];
var _b = tslib_1.__read(React.useState(function () {
var translations = manager.state(ids.current).translations;
return new i18n_1.I18n(translations, manager.details);
}), 2), i18n = _b[0], setI18n = _b[1];
var i18nRef = React.useRef(i18n);
React.useEffect(function () {
return manager.subscribe(ids, function (_a, details) {
return manager.subscribe(ids.current, function (_a, details) {
var translations = _a.translations;
setI18n(new i18n_1.I18n(translations, details, ids));
var newI18n = new i18n_1.I18n(translations, details);
i18nRef.current = newI18n;
setI18n(newI18n);
});
}, [ids, manager]);
var ShareTranslations = React.useMemo(function () {
// We use refs in this component so that it never changes. If this component
// is regenerated, it will unmount the entire tree of the previous component,
// which is usually not desirable. Technically, this does leave surface area
// for a bug to sneak in: if the component that renders this does so inside
// a component that blocks the update from passing down, nothing will force
// this component to re-render, so no descendants will get the new ids/ i18n
// value. Because we don't actually have any such cases, we're OK with this
// for now.
var shareTranslationsComponent = react_hooks_1.useLazyRef(function () {
return function ShareTranslations(_a) {
var children = _a.children;
return (React.createElement(context_1.I18nParentsContext.Provider, { value: i18n }, children));
return (React.createElement(context_1.I18nIdsContext.Provider, { value: ids.current },
React.createElement(context_1.I18nParentContext.Provider, { value: i18nRef.current }, children)));
};
}, [i18n]);
return [i18n, ShareTranslations];
});
return [i18n, shareTranslationsComponent.current];
}
exports.useI18n = useI18n;
function useSimpleI18n() {
var manager = React.useContext(context_1.I18nContext);
if (manager == null) {
throw new Error('Missing i18n manager. Make sure to use an <I18nContext.Provider /> somewhere in your React tree.');
}
var i18n = React.useContext(context_1.I18nParentsContext) || new i18n_1.I18n([], manager.details);
return i18n;
function useSimpleI18n(manager) {
var i18n = React.useContext(context_1.I18nParentContext) || new i18n_1.I18n([], manager.details);
return [i18n, IdentityComponent];
}
exports.useSimpleI18n = useSimpleI18n;
function IdentityComponent(_a) {
var children = _a.children;
return React.createElement(React.Fragment, null, children);
}
function shouldRegister(_a) {
var _b = _a === void 0 ? {} : _a, fallback = _b.fallback, translations = _b.translations;
return fallback != null || translations != null;
}

@@ -14,3 +14,2 @@ /// <reference types="react" />

readonly translations: TranslationDictionary[];
readonly ids?: string[] | undefined;
readonly locale: string;

@@ -31,3 +30,3 @@ readonly pseudolocalize: boolean | string;

readonly isLtrLanguage: boolean;
constructor(translations: TranslationDictionary[], { locale, currency, timezone, country, pseudolocalize, onError, }: I18nDetails, ids?: string[] | undefined);
constructor(translations: TranslationDictionary[], { locale, currency, timezone, country, pseudolocalize, onError, }: I18nDetails);
translate(id: string, options: TranslateOptions, replacements?: PrimitiveReplacementDictionary): string;

@@ -34,0 +33,0 @@ translate(id: string, options: TranslateOptions, replacements?: ComplexReplacementDictionary): React.ReactElement<any>;

@@ -24,7 +24,6 @@ "use strict";

var I18n = /** @class */ (function () {
function I18n(translations, _a, ids) {
function I18n(translations, _a) {
var locale = _a.locale, currency = _a.currency, timezone = _a.timezone, country = _a.country, _b = _a.pseudolocalize, pseudolocalize = _b === void 0 ? false : _b, onError = _a.onError;
var _this = this;
this.translations = translations;
this.ids = ids;
this.getCurrencySymbol = function (currencyCode) {

@@ -31,0 +30,0 @@ var currency = currencyCode || _this.defaultCurrency;

export { I18nManager, ExtractedTranslations } from './manager';
export { I18nContext } from './context';
export { I18n } from './i18n';
export { useI18n, useSimpleI18n } from './hooks';
export { useI18n } from './hooks';
export { withI18n, WithI18nProps } from './decorator';

@@ -6,0 +6,0 @@ export { translate } from './utilities';

@@ -11,3 +11,2 @@ "use strict";

exports.useI18n = hooks_1.useI18n;
exports.useSimpleI18n = hooks_1.useSimpleI18n;
var decorator_1 = require("./decorator");

@@ -14,0 +13,0 @@ exports.withI18n = decorator_1.withI18n;

@@ -39,2 +39,4 @@ import { I18nDetails, TranslationDictionary, MaybePromise } from './types';

private translationPromises;
private idsToUpdate;
private enqueuedUpdate?;
constructor(details: I18nDetails, initialTranslations?: ExtractedTranslations);

@@ -41,0 +43,0 @@ resolve(): Promise<void>;

@@ -15,2 +15,3 @@ "use strict";

this.translationPromises = new Map();
this.idsToUpdate = new Set();
try {

@@ -82,2 +83,3 @@ for (var _b = tslib_1.__values(Object.entries(initialTranslations)), _c = _b.next(); !_c.done; _c = _b.next()) {

var loading = false;
var hasUnresolvedTranslations = false;
var translations = ids.reduce(function (otherTranslations, id) {

@@ -93,3 +95,3 @@ var e_2, _a;

if (_this.translationPromises.has(translationId)) {
loading = true;
hasUnresolvedTranslations = true;
}

@@ -109,2 +111,5 @@ }

}
if (translationsForId.length === 0 && hasUnresolvedTranslations) {
loading = true;
}
if (!omitFallbacks) {

@@ -173,3 +178,5 @@ var fallback = _this.fallbacks.get(id);

_this.asyncTranslationIds.add(translationId);
_this.updateSubscribersForId(id);
if (result != null) {
_this.updateSubscribersForId(id);
}
})

@@ -180,3 +187,2 @@ .catch(function () {

_this.asyncTranslationIds.add(translationId);
_this.updateSubscribersForId(id);
});

@@ -205,18 +211,30 @@ this_1.translationPromises.set(translationId, promise);

I18nManager.prototype.updateSubscribersForId = function (id) {
var e_6, _a;
try {
for (var _b = tslib_1.__values(this.subscriptions), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = tslib_1.__read(_c.value, 2), subscriber = _d[0], ids = _d[1];
if (ids.includes(id)) {
subscriber(this.state(ids), this.details);
}
}
var _this = this;
this.idsToUpdate.add(id);
if (this.enqueuedUpdate != null) {
return;
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
var isBrowser = typeof window !== 'undefined';
var enqueue = isBrowser ? window.requestAnimationFrame : setImmediate;
this.enqueuedUpdate = enqueue(function () {
var e_6, _a;
delete _this.enqueuedUpdate;
var idsToUpdate = tslib_1.__spread(_this.idsToUpdate);
_this.idsToUpdate.clear();
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
for (var _b = tslib_1.__values(_this.subscriptions), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = tslib_1.__read(_c.value, 2), subscriber = _d[0], ids = _d[1];
if (ids.some(function (id) { return idsToUpdate.includes(id); })) {
subscriber(_this.state(ids), _this.details);
}
}
}
finally { if (e_6) throw e_6.error; }
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_6) throw e_6.error; }
}
});
};

@@ -223,0 +241,0 @@ return I18nManager;

{
"name": "@shopify/react-i18n",
"version": "1.1.2",
"version": "1.1.3",
"license": "MIT",

@@ -38,2 +38,3 @@ "description": "i18n utilities for React handling translations, formatting, and more.",

"@shopify/react-effect": "^3.0.1",
"@shopify/react-hooks": "^1.1.0",
"@types/hoist-non-react-statics": "^3.0.1",

@@ -40,0 +41,0 @@ "hoist-non-react-statics": "^3.0.1",

@@ -72,2 +72,4 @@ # `@shopify/react-i18n`

> **Note:** `ShareTranslations` is not guaranteed to re-render when your i18n object changes. If you render `ShareTranslations` inside of a component that might block changes to children, you will likely run into issues. To prevent this, we recommend that `ShareTranslations` should be rendered as a top-level child of the component that uses `useI18n`.
```tsx

@@ -85,9 +87,5 @@ import * as React from 'react';

return (
<Page
title={i18n.translate('ProductDetails.title')}
>
<ShareTranslations>
{children}
</ShareTranslations>
</EmptyState>
<ShareTranslations>
<Page title={i18n.translate('ProductDetails.title')}>{children}</Page>
</ShareTranslations>
);

@@ -125,22 +123,2 @@ }

If you only need access to parent translations and/ or the various formatting utilities found on the `I18n` object, you can instead use the `useSimpleI18n` hook. This hook does not support providing any internationalization details for the component itself, but is a very performant way to access i18n utilities that are tied to the global locale.
```tsx
import * as React from 'react';
import {EmptyState} from '@shopify/polaris';
import {useSimpleI18n} from '@shopify/react-i18n';
export default function NotFound() {
const i18n = useSimpleI18n();
return (
<EmptyState
heading={i18n.translate('NotFound.heading')}
action={{content: i18n.translate('Common.back'), url: '/'}}
>
<p>{i18n.translate('NotFound.content')}</p>
</EmptyState>
);
}
```
#### `i18n`

@@ -147,0 +125,0 @@

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