Skip to content
Open
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
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