Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support serializable formats #982

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/next-intl/src/react-server/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// Replaced exports from the `react` package
export {default as useLocale} from './useLocale';
export {default as useTranslations} from './useTranslations';
export {default as useFormats} from './useFormats';
export {default as useFormatter} from './useFormatter';
export {default as useNow} from './useNow';
export {default as useTimeZone} from './useTimeZone';
Expand Down
11 changes: 11 additions & 0 deletions packages/next-intl/src/react-server/useFormats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type {useFormats as useFormatsType} from 'use-intl';
import {getFormatsFromConfig} from '../server/react-server/getFormats';
import useConfig from './useConfig';

export default function useFormats(
// eslint-disable-next-line no-empty-pattern
...[]: Parameters<typeof useFormatsType>
): ReturnType<typeof useFormatsType> {
const config = useConfig('useFormats');
return getFormatsFromConfig(config);
}
2 changes: 2 additions & 0 deletions packages/next-intl/src/server/react-client/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
getRequestConfig as getRequestConfig_type,
getFormatter as getFormatter_type,
getFormats as getFormats_type,
getNow as getNow_type,
getTimeZone as getTimeZone_type,
getMessages as getMessages_type,
Expand Down Expand Up @@ -28,6 +29,7 @@ export function getRequestConfig(
): ReturnType<typeof getRequestConfig_type> {
return notSupported('getRequestConfig');
}
export const getFormats = notSupported('getFormats') as typeof getFormats_type;
export const getFormatter = notSupported(
'getFormatter'
) as typeof getFormatter_type;
Expand Down
28 changes: 28 additions & 0 deletions packages/next-intl/src/server/react-server/getFormats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {cache} from 'react';
import type {Formats} from 'use-intl';
import getConfig from './getConfig';
import resolveLocaleArg from './resolveLocaleArg';

export function getFormatsFromConfig(
config: Awaited<ReturnType<typeof getConfig>>
): Partial<Formats> {
if (!config.formats) {
throw new Error(
'No formats found. Have you configured them correctly? See https://next-intl-docs.vercel.app/docs/configuration#formats'
);
}
return config.formats;
}

async function getFormatsCachedImpl(locale: string) {
const config = await getConfig(locale);
return getFormatsFromConfig(config);
}
const getFormatsCached = cache(getFormatsCachedImpl);

export default async function getFormats(opts?: {
locale?: string;
}): Promise<Partial<Formats>> {
const locale = await resolveLocaleArg(opts);
return getFormatsCached(locale);
}
1 change: 1 addition & 0 deletions packages/next-intl/src/server/react-server/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

export {default as getRequestConfig} from './getRequestConfig';
export {default as getFormats} from './getFormats';
export {default as getFormatter} from './getFormatter';
export {default as getNow} from './getNow';
export {default as getTimeZone} from './getTimeZone';
Expand Down
3 changes: 3 additions & 0 deletions packages/next-intl/test/react-server/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import {describe, expect, vi, it} from 'vitest';
import {
createTranslator,
useFormats,
useFormatter,
useLocale,
useMessages,
Expand Down Expand Up @@ -48,6 +49,7 @@ describe('performance', () => {

const t = useTranslations('Component');
const format = useFormatter();
const formats = useFormats();
const locale = useLocale();
const messages = useMessages();
const now = useNow();
Expand All @@ -56,6 +58,7 @@ describe('performance', () => {
<>
{now.toISOString()}
{JSON.stringify(messages)}
{JSON.stringify(formats)}
{locale}
{format.number(1000)}
{t('title')}
Expand Down
1 change: 1 addition & 0 deletions packages/use-intl/src/react/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {default as IntlProvider} from './IntlProvider';
export {default as useTranslations} from './useTranslations';
export {default as useFormats} from './useFormats';
export {default as useLocale} from './useLocale';
export {default as useNow} from './useNow';
export {default as useTimeZone} from './useTimeZone';
Expand Down
16 changes: 16 additions & 0 deletions packages/use-intl/src/react/useFormats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {type Formats} from '../core';
import useIntlContext from './useIntlContext';

export default function useFormats(): Partial<Formats> {
const context = useIntlContext();

if (!context.formats) {
throw new Error(
process.env.NODE_ENV !== 'production'
? 'No formats found. Have you configured them correctly? See https://next-intl-docs.vercel.app/docs/configuration#formats'
: undefined
);
}

return context.formats;
}
40 changes: 40 additions & 0 deletions packages/use-intl/test/react/useFormats.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {render, screen} from '@testing-library/react';
import React from 'react';
import {it, expect} from 'vitest';
import {IntlProvider, useFormats} from '../../src';

function Component() {
const formats = useFormats();
return (
<>
{JSON.stringify(formats)}
{/* The returned value can be passed to the provider */}
<IntlProvider formats={formats} locale="de">
<p />
</IntlProvider>
</>
);
}

it('returns formats when they are configured', () => {
render(
<IntlProvider
formats={{dateTime: {onlyHours: {hour: 'numeric'}}}}
locale="de"
>
<Component />
</IntlProvider>
);

screen.getByText('{"dateTime":{"onlyHours":{"hour":"numeric"}}}');
});

it('throws when no formats are configured', () => {
expect(() =>
render(
<IntlProvider locale="de">
<Component />
</IntlProvider>
)
).toThrow('No formats found.');
});
Loading