Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions examples/next-pages/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export default {
'missing.translation.in.fr': 'This should work',
'cows#one': 'A cow',
'cows#other': '{count} cows',
'scope2.test': 'A scope',
'scope2.more.test': 'A more scoped ',
} as const;

// We can also write locales using nested objects
Expand Down
21 changes: 21 additions & 0 deletions examples/next-pages/pages/ssr-ssg-scoped.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { GetServerSideProps } from 'next';
import { getLocaleProps, useCurrentLocale, useI18n } from '../locales';

export const getServerSideProps: GetServerSideProps = getLocaleProps(['scope2']);
// export const getStaticProps: GetStaticProps = getLocaleProps();

export default function SSR() {
const t = useI18n();
const locale = useCurrentLocale();

return (
<div>
<h1>SSR / SSG</h1>
<p>
Current locale: <span>{locale}</span>
</p>
<p>Hello: {t('scope2.test')}</p>
<p>Hello: {t('scope2.more.test')}</p>
</div>
);
}
52 changes: 51 additions & 1 deletion packages/next-international/__tests__/get-locale-props.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('getLocaleProps', () => {
fr: () => import('./utils/fr'),
});

const props = await getLocaleProps(() => ({
const props = await getLocaleProps(undefined, () => ({
props: {
hello: 'world',
},
Expand All @@ -66,3 +66,53 @@ describe('getLocaleProps', () => {
});
});
});

it('should return scoped locale with when scope defined in params getStaticProps', async () => {
const { getLocaleProps } = createI18n({
en: () => import('./utils/en'),
fr: () => import('./utils/fr'),
});

const props = await getLocaleProps(['namespace'])({
locale: 'en',
defaultLocale: 'en',
locales: ['en', 'fr'],
});

expect(props).toEqual({
props: {
locale: {
'namespace.hello': 'Hello',
'namespace.subnamespace.hello': 'Hello',
'namespace.subnamespace.hello.world': 'Hello World!',
'namespace.subnamespace.weather': "Today's weather is {weather}",
'namespace.subnamespace.user.description': '{name} is {years} years old',
},
},
});

it('should return scoped locale with when scope defined in params getStaticProps', async () => {
const { getLocaleProps } = createI18n({
en: () => import('./utils/en'),
fr: () => import('./utils/fr'),
});

const props = await getLocaleProps(['namespace.subnamespace'])({
locale: 'en',
defaultLocale: 'en',
locales: ['en', 'fr'],
});

expect(props).toEqual({
props: {
locale: {
'namespace.subnamespace.hello': 'Hello',
'namespace.subnamespace.hello.world': 'Hello World!',
'namespace.subnamespace.weather': "Today's weather is {weather}",
'namespace.subnamespace.user.description': '{name} is {years} years old',
locale: en,
},
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { BaseLocale, Scopes } from 'international-types';

export const filterLocalesByNameSpace = <Locale extends BaseLocale, Scope extends Scopes<Locale>>(
locale: Locale,
scopes?: Scope[],
): Locale => {
if (!scopes?.length) return locale;

return Object.entries(locale).reduce((prev, [name, value]) => {
if (scopes.some(scope => name.startsWith(scope))) {
const k = name as keyof Locale;
prev[k] = value as Locale[string];
}

return prev;
}, {} as Locale);
};
11 changes: 7 additions & 4 deletions packages/next-international/src/pages/create-get-locale-props.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { ImportedLocales } from 'international-types';
import type { BaseLocale, ImportedLocales, Scopes } from 'international-types';
import type { GetStaticProps, GetServerSideProps } from 'next';
import { error } from '../helpers/log';
import { flattenLocale } from '../common/flatten-locale';
import { filterLocalesByNameSpace } from '../common/filter-locales-by-namespace';

export function createGetLocaleProps(locales: ImportedLocales) {
return function getLocaleProps<
T extends { [key: string]: any },
GetProps extends GetStaticProps<T> | GetServerSideProps<T>,
>(initialGetProps?: GetProps) {
Scope extends Scopes<BaseLocale>,
>(scopes?: Scope[], initialGetProps?: GetProps) {
return async (context: any) => {
const initialResult = await initialGetProps?.(context);

Expand All @@ -18,13 +20,14 @@ export function createGetLocaleProps(locales: ImportedLocales) {
}

const load = locales[context.locale];

const allLocale = flattenLocale((await load()).default);
const scopedLocale = filterLocalesByNameSpace(allLocale, scopes);
return {
...initialResult,
props: {
// @ts-expect-error Next `GetStaticPropsResult` doesn't have `props`
...initialResult?.props,
locale: flattenLocale((await load()).default),
locale: scopedLocale,
},
};
};
Expand Down