🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

next-intl

Package Overview
Dependencies
Maintainers
1
Versions
377
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

next-intl - npm Package Compare versions

Comparing version

to
0.0.6-next.1

dist/useIntl.d.ts

1

dist/index.d.ts

@@ -5,1 +5,2 @@ export { default as NextIntlProvider } from './NextIntlProvider';

export { default as TranslationValues } from './TranslationValues';
export { default as useIntl } from './useIntl';

34

dist/next-intl.cjs.development.js

@@ -7,6 +7,7 @@ 'use strict';

var router = require('next/router');
var React = require('react');
var React__default = _interopDefault(React);
var reactIntl = require('react-intl');
var IntlMessageFormat = _interopDefault(require('intl-messageformat'));
var router = require('next/router');

@@ -19,8 +20,14 @@ var NextIntlContext = /*#__PURE__*/React.createContext(undefined);

messages = _ref.messages;
return React__default.createElement(NextIntlContext.Provider, {
value: {
messages: messages,
locale: locale
}
}, children);
router.useRouter();
return (// @ts-ignore
React__default.createElement(reactIntl.IntlProvider, {
locale: locale,
messages: messages
}, React__default.createElement(NextIntlContext.Provider, {
value: {
messages: messages,
locale: locale
}
}, children))
);
}

@@ -102,3 +109,7 @@

/** Use a dot to indicate a level of nesting (e.g. `namespace.nestedLabel`). */
idPath, values) {
idPath,
/** Key value pairs for values to interpolate into the message. */
values,
/** Provide custom formats for numbers, dates and times. */
formats) {
var _cachedFormatsByLocal;

@@ -126,3 +137,3 @@

messageFormat = new IntlMessageFormat(message, locale);
messageFormat = new IntlMessageFormat(message, locale, formats);

@@ -150,4 +161,9 @@ if (!cachedFormatsByLocale[locale]) {

function useIntl() {
return reactIntl.useIntl();
}
exports.NextIntlProvider = NextIntlProvider;
exports.useIntl = useIntl;
exports.useTranslations = useTranslations;
//# sourceMappingURL=next-intl.cjs.development.js.map

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

"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var r=require("react"),t=e(r),n=e(require("intl-messageformat")),o=require("next/router"),u=r.createContext(void 0);function i(e,r){var t=e;return r.split(".").forEach((function(e){t=t[e]})),t}exports.NextIntlProvider=function(e){return t.createElement(u.Provider,{value:{messages:e.messages,locale:e.locale}},e.children)},exports.useTranslations=function(e){var t=r.useContext(u),a=o.useRouter().locale,c=r.useRef({});if(!t)throw new Error;var s=t.locale||a,f=t.messages,l=r.useMemo((function(){return e?i(f,e):f}),[f,e]);return function(e,t){var o;if(!s)throw new Error;var u,a=c.current;if(null==(o=a[s])?void 0:o[e])u=a[s][e];else{var f=i(l,e);if("object"==typeof f)throw new Error;u=new n(f,s),a[s]||(a[s]={}),a[s][e]=u}return u.format(function(e){if(!e)return e;var t={};return Object.keys(e).forEach((function(n){var o=e[n];t[n]="function"==typeof o?function(e){var t=o(e);return r.isValidElement(t)?r.cloneElement(t,{key:t.key||n+String(e)}):t}:o})),t}(t))}};
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var r=require("next/router"),t=require("react"),n=e(t),o=require("react-intl"),u=e(require("intl-messageformat")),a=t.createContext(void 0);function i(e,r){var t=e;return r.split(".").forEach((function(e){t=t[e]})),t}exports.NextIntlProvider=function(e){var t=e.children,u=e.locale,i=e.messages;return r.useRouter(),n.createElement(o.IntlProvider,{locale:u,messages:i},n.createElement(a.Provider,{value:{messages:i,locale:u}},t))},exports.useIntl=function(){return o.useIntl()},exports.useTranslations=function(e){var n=t.useContext(a),o=r.useRouter().locale,s=t.useRef({});if(!n)throw new Error;var l=n.locale||o,c=n.messages,f=t.useMemo((function(){return e?i(c,e):c}),[c,e]);return function(e,r,n){var o;if(!l)throw new Error;var a,c=s.current;if(null==(o=c[l])?void 0:o[e])a=c[l][e];else{var v=i(f,e);if("object"==typeof v)throw new Error;a=new u(v,l,n),c[l]||(c[l]={}),c[l][e]=a}return a.format(function(e){if(!e)return e;var r={};return Object.keys(e).forEach((function(n){var o=e[n];r[n]="function"==typeof o?function(e){var r=o(e);return t.isValidElement(r)?t.cloneElement(r,{key:r.key||n+String(e)}):r}:o})),r}(r))}};
//# sourceMappingURL=next-intl.cjs.production.min.js.map

@@ -0,4 +1,5 @@

import { useRouter } from 'next/router';
import React, { createContext, useContext, useRef, useMemo, isValidElement, cloneElement } from 'react';
import { IntlProvider, useIntl as useIntl$1 } from 'react-intl';
import IntlMessageFormat from 'intl-messageformat';
import { useRouter } from 'next/router';

@@ -11,8 +12,14 @@ var NextIntlContext = /*#__PURE__*/createContext(undefined);

messages = _ref.messages;
return React.createElement(NextIntlContext.Provider, {
value: {
messages: messages,
locale: locale
}
}, children);
useRouter();
return (// @ts-ignore
React.createElement(IntlProvider, {
locale: locale,
messages: messages
}, React.createElement(NextIntlContext.Provider, {
value: {
messages: messages,
locale: locale
}
}, children))
);
}

@@ -96,3 +103,7 @@

/** Use a dot to indicate a level of nesting (e.g. `namespace.nestedLabel`). */
idPath, values) {
idPath,
/** Key value pairs for values to interpolate into the message. */
values,
/** Provide custom formats for numbers, dates and times. */
formats) {
var _cachedFormatsByLocal;

@@ -124,3 +135,3 @@

messageFormat = new IntlMessageFormat(message, locale);
messageFormat = new IntlMessageFormat(message, locale, formats);

@@ -148,3 +159,7 @@ if (!cachedFormatsByLocale[locale]) {

export { NextIntlProvider, useTranslations };
function useIntl() {
return useIntl$1();
}
export { NextIntlProvider, useIntl, useTranslations };
//# sourceMappingURL=next-intl.esm.js.map

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

import { Formats } from 'intl-messageformat';
import { ReactNode } from 'react';

@@ -10,2 +11,2 @@ /**

*/
export default function useTranslations(path?: string): (idPath: string, values?: Record<string, string | number | boolean | Date | ((children: ReactNode) => ReactNode) | null | undefined> | undefined) => string | number | boolean | {} | import("react").ReactElement<any, string | ((props: any) => import("react").ReactElement<any, string | any | (new (props: any) => import("react").Component<any, any, any>)> | null) | (new (props: any) => import("react").Component<any, any, any>)> | import("react").ReactNodeArray | import("react").ReactPortal | (string | number | boolean | {} | import("react").ReactElement<any, string | ((props: any) => import("react").ReactElement<any, string | any | (new (props: any) => import("react").Component<any, any, any>)> | null) | (new (props: any) => import("react").Component<any, any, any>)> | import("react").ReactNodeArray | import("react").ReactPortal | null)[] | null;
export default function useTranslations(path?: string): (idPath: string, values?: Record<string, string | number | boolean | Date | ((children: ReactNode) => ReactNode) | null | undefined> | undefined, formats?: Partial<Formats> | undefined) => string | number | boolean | {} | import("react").ReactElement<any, string | ((props: any) => import("react").ReactElement<any, string | any | (new (props: any) => import("react").Component<any, any, any>)> | null) | (new (props: any) => import("react").Component<any, any, any>)> | import("react").ReactNodeArray | import("react").ReactPortal | (string | number | boolean | {} | import("react").ReactElement<any, string | ((props: any) => import("react").ReactElement<any, string | any | (new (props: any) => import("react").Component<any, any, any>)> | null) | (new (props: any) => import("react").Component<any, any, any>)> | import("react").ReactNodeArray | import("react").ReactPortal | null)[] | null;
{
"name": "next-intl",
"version": "0.0.5",
"version": "0.0.6-next.1",
"sideEffects": false,

@@ -15,5 +15,5 @@ "author": "Jan Amann <jan@amann.me>",

"build": "tsdx build",
"test": "tsdx test",
"test": "TZ=Europe/Berlin tsdx test",
"lint": "eslint src test && tsc",
"prepublish": "yarn build && yarn lint"
"prepublish": "yarn build"
},

@@ -28,3 +28,4 @@ "main": "dist/index.js",

"dependencies": {
"intl-messageformat": "^9.3.18"
"intl-messageformat": "^9.3.18",
"react-intl": "^5.10.4"
},

@@ -31,0 +32,0 @@ "peerDependencies": {

@@ -5,12 +5,18 @@ # next-intl

Minimal, but complete solution for managing internationalization in Next.js apps.
Minimal, but complete solution for managing internationalization in Next.js apps. 🌐
## The problem
This library complements the [internationalized routing](https://nextjs.org/docs/advanced-features/i18n-routing) capabilities of Next.js by managing translations and providing them to components.
Next.js has built-in support for [internationalized routing](https://nextjs.org/docs/advanced-features/i18n-routing), but doesn't have an opinion about how you should handle your translations.
## Features
## This solution
- Based on battle-tested building blocks from [Format.JS](https://formatjs.io/) (used by `react-intl`), this library is a thin wrapper around high-quality, lower-level APIs for i18n.
- I18n is an essential part of the user experience, therefore this library doesn't compromise on flexibility and never leaves you behind when you need to fine tune a translation. Messages use the proven [ICU syntax](https://formatjs.io/docs/core-concepts/icu-syntax) which covers interpolation, numbers, dates, times, plurals, ordinal pluralization, label selection based on enums and rich text.
- The bundle size comes in at [32.2kb (9.3kb gzipped)](https://bundlephobia.com/result?p=next-intl) which is the tradeoff that's necessary for supporting all the mentioned internationalisation features.
- A hooks-only API ensures that you can use the same API for `children` as well as for attributes which expect strings.
- Integrates with both static as well as server side rendering capabilities of Next.js.
This library provides a minimal, but complete solution that fills in the missing pieces.
## What does it look like?
This library is based on the premise that messages can be grouped by namespaces (typically a component name).
```jsx

@@ -39,10 +45,2 @@ function LatestFollower({user}) {

## Features
- Based on battle-tested building blocks from [Format.JS](https://formatjs.io/) (used by `react-intl`), this library is a thin wrapper around high-quality, lower-level APIs for i18n.
- I18n is an essential part of the user experience, therefore this library doesn't compromise on flexibility and never leaves you behind when you need to fine tune a translation. Messages use the proven [ICU syntax](https://formatjs.io/docs/core-concepts/icu-syntax) which covers interpolation, numbers, dates, times, plurals, ordinal pluralization, label selection based on enums and rich text.
- The bundle size comes in at [32.2kb (9.2kb gzipped)](https://bundlephobia.com/result?p=next-intl) which is the tradeoff that's necessary for the flexibility of the library.
- A hooks-only API ensures that you can use the same API for `children` as well as for attributes which expect strings.
- Integrates with both static as well as server side rendering capabilities of Next.js.
## Installation

@@ -70,4 +68,4 @@

// the desired one based on the `locale` received from Next.js. You
// can also separate your messages further (e.g. by page) and read
// them based on the current route.
// can also separate your messages by page and fetch them in `getStaticProps`
// in your page which will make them available on `pageProps` in the `App`.
const messages = locale ? require(`messages/${locale}.json`) : undefined

@@ -87,3 +85,5 @@

{
// The recommended approach is to group messages by components.
// The recommended approach is to group messages by components and
// embrace them as the primary unit of code organization in your app.
# based on the assumption that messages are relevant for components
"Component": {

@@ -95,7 +95,19 @@ "static": "Hello",

// See https://formatjs.io/docs/core-concepts/icu-syntax/#number-type
"number": "{price, number, ::currency/EUR}",
// Static number formats
// See also https://formatjs.io/docs/core-concepts/icu-syntax/#number-type
"percent": "Percent: {value, number, percent}",
// When formatting numbers, you can pass a custom formatter name which can
// be provided and configured by the call site within the component.
// See also https://formatjs.io/docs/core-concepts/icu-syntax/#number-type
"price": "Price: {price, number, currency}",
// See https://formatjs.io/docs/intl-messageformat#datetime-skeleton
"date": "{now, date, medium}",
// Similar to number formatting, you can provide a custom formatter
// from the call site within the component.
"date": "Date: {now, date, medium}",
// See https://formatjs.io/docs/intl-messageformat#datetime-skeleton
// Same mechanism as date formatting.
"time": "Time: {now, time, short}",

@@ -147,9 +159,25 @@ // See https://formatjs.io/docs/core-concepts/icu-syntax/#plural-format

const t = useTranslations('Component');
return (
<p>{t('static')}</p>
<p>{t('interpolation', {name: 'Jane'})}</p>
<p>{t('number', {price: 31918.231})}</p>
<p>{t('percent', {percent: 0.2})}</p>
<p>
{t(
'price',
{price: 31918.231},
// When custom formats are used, you can supply them via the third parameter
{
number: {
currency: {
style: 'currency',
currency: 'EUR'
}
}
)}
</p>
<p>{t('date', {date: new Date('2020-11-20T10:36:01.516Z')})}</p>
<p>{t('time', {time: new Date('2020-11-20T10:36:01.516Z')})}</p>
<p>{t('plural', {date: new Date('2020-11-20T10:36:01.516Z')})}</p>
<p>{t('selectordinal', {year: 1})}</p>
<p>{t('selectordinal', {year: 11})}</p>
<p>

@@ -182,2 +210,31 @@ {t('richText', {

If you're formatting dates, numbers and times that are not embedded within a message, you can use a separate hook:
<!-- https://formatjs.io/docs/react-intl/api#formatdisplayname -->
```js
import {useIntl} from 'next-intl';
function Component() {
const intl = useIntl();
const dateTime = new Date('2020-11-20T10:36:01.516Z')
return (
<>
{intl.formatDate(dateTime, {year: 'numeric', month: 'numeric', day: 'numeric'})}
{intl.formatTime(dateTime, {hour: 'numeric', minute: 'numeric'})}
{intl.formatNumber(499.90, {style: 'currency', currency: 'USD'})}
<>
);
}
```
## FAQ
How is this different from using `react-intl`?
- Built around the concept of namespaces.
- No split between components and imperative APIS – only hooks.
- No extraction, descriptions, automatic ids.
## Known tradeoffs

@@ -189,10 +246,8 @@

- There are smaller libraries for internationalisation, but they typically cover less features than Format.JS. However if your performance budget doesn't allow for the size of this library, you might be better off with an alternative.
- If you're using `getInitialProps` in a custom `App` component you [opt-out of automatic static optimization](https://github.com/vercel/next.js/blob/master/errors/opt-out-auto-static-optimization.md#opt-out-of-automatic-static-optimization). However, pages that use `getStaticProps` are still statically optimized (even if `getStaticProps` is essentially a no-op – only the presence matters).
- No descriptions are used which could make it harder for translaters to localize messages. Related to this, AST-based extraction from `react-intl` is not possible. `react-intl` is generally more targeted toward larger applications and workflows with translators. This library might be more reasonable for apps where the developer sets up translations based a design for example.
- If you're using `getInitialProps` in a custom `App` component you [opt-out of automatic static optimization](https://github.com/vercel/next.js/blob/master/errors/opt-out-auto-static-optimization.md#opt-out-of-automatic-static-optimization). However, pages that use `getStaticProps` are still statically optimized (even if `getStaticProps` is essentially a no-op – only the presence matters). Alternatively you can return the messages in `getStaticProps` of a page component and use the `pageProps` in `App` to configure the provider.
- No descriptions are used which could make it harder for translaters to localize messages. Related to this, AST-based extraction from `react-intl` is not possible. `react-intl` is generally more targeted towards larger applications and workflows with translators. This library might be more reasonable for apps where the developer sets up translations based on a design for example.
## TODO
- Cache format result?
- Pass currency to number? (if currency is sensitive to locale, use the messages)
- Relative time
- Check other features of react-intl
- Performance: Cache format result? Use fast-memoize like react-intl?
- Relative time. Should this be a component? Can update over time.Ccan accept an optional now.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet