-
-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Propose new APIs from using i18n outside of components
- Loading branch information
Showing
12 changed files
with
259 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
import type {useLocale as useLocaleType} from 'use-intl'; | ||
import getLocale from '../server/getLocale'; | ||
import getLocaleFromHeader from '../server/getLocaleFromHeader'; | ||
|
||
export default function useLocale( | ||
// eslint-disable-next-line no-empty-pattern | ||
...[]: Parameters<typeof useLocaleType> | ||
): ReturnType<typeof useLocaleType> { | ||
return getLocale(); | ||
return getLocaleFromHeader(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,21 @@ | ||
import {cookies, headers} from 'next/headers'; | ||
import {cache} from 'react'; | ||
import {COOKIE_LOCALE_NAME, HEADER_LOCALE_NAME} from '../shared/constants'; | ||
import getLocaleFromHeader from './getLocaleFromHeader'; | ||
|
||
const getLocale = cache(() => { | ||
let locale; | ||
let hasWarned = false; | ||
|
||
try { | ||
// A header is only set when we're changing the locale, | ||
// otherwise we reuse an existing one from the cookie. | ||
const requestHeaders = headers(); | ||
if (requestHeaders.has(HEADER_LOCALE_NAME)) { | ||
locale = requestHeaders.get(HEADER_LOCALE_NAME); | ||
} else { | ||
locale = cookies().get(COOKIE_LOCALE_NAME)?.value; | ||
} | ||
} catch (error) { | ||
if ( | ||
error instanceof Error && | ||
(error as any).digest === 'DYNAMIC_SERVER_USAGE' | ||
) { | ||
throw new Error( | ||
'Usage of next-intl APIs in Server Components is currently only available for dynamic rendering (i.e. no `generateStaticParams`).\n\nSupport for static rendering is under consideration, please refer to the roadmap: https://next-intl-docs.vercel.app/docs/next-13/server-components#roadmap', | ||
{cause: error} | ||
); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
export default function getLocale() { | ||
if (!hasWarned) { | ||
console.warn(` | ||
\`getLocale\` is deprecated. Please use the \`locale\` parameter from Next.js instead: | ||
if (!locale) { | ||
throw new Error( | ||
'Unable to find `next-intl` locale, have you configured the middleware?`' | ||
); | ||
} | ||
// app/[locale]/layout.tsx | ||
export async function generateMetadata({locale}) { | ||
// Use \`locale\` here | ||
} | ||
return locale; | ||
}); | ||
Learn more: https://next-intl-docs.vercel.app/docs/next-13/server-components#using-internationalization-outside-of-components | ||
`); | ||
hasWarned = true; | ||
} | ||
|
||
export default getLocale; | ||
return getLocaleFromHeader(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import {cookies, headers} from 'next/headers'; | ||
import {cache} from 'react'; | ||
import {COOKIE_LOCALE_NAME, HEADER_LOCALE_NAME} from '../shared/constants'; | ||
|
||
const getLocaleFromHeader = cache(() => { | ||
let locale; | ||
|
||
try { | ||
// A header is only set when we're changing the locale, | ||
// otherwise we reuse an existing one from the cookie. | ||
const requestHeaders = headers(); | ||
if (requestHeaders.has(HEADER_LOCALE_NAME)) { | ||
locale = requestHeaders.get(HEADER_LOCALE_NAME); | ||
} else { | ||
locale = cookies().get(COOKIE_LOCALE_NAME)?.value; | ||
} | ||
} catch (error) { | ||
if ( | ||
error instanceof Error && | ||
(error as any).digest === 'DYNAMIC_SERVER_USAGE' | ||
) { | ||
throw new Error( | ||
'Usage of next-intl APIs in Server Components is currently only available for dynamic rendering (i.e. no `generateStaticParams`).\n\nSupport for static rendering is under consideration, please refer to the roadmap: https://next-intl-docs.vercel.app/docs/next-13/server-components#roadmap', | ||
{cause: error} | ||
); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
|
||
if (!locale) { | ||
throw new Error( | ||
'Unable to find `next-intl` locale, have you configured the middleware?`' | ||
); | ||
} | ||
|
||
return locale; | ||
}); | ||
|
||
export default getLocaleFromHeader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* eslint-disable import/default */ | ||
|
||
import {cache} from 'react'; | ||
import type Formats from 'use-intl/dist/src/core/Formats'; | ||
import type TranslationValues from 'use-intl/dist/src/core/TranslationValues'; | ||
import createBaseTranslator, { | ||
getMessagesOrError | ||
} from 'use-intl/dist/src/core/createBaseTranslator'; | ||
import {CoreRichTranslationValues} from 'use-intl/dist/src/core/createTranslatorImpl'; | ||
import MessageKeys from 'use-intl/dist/src/core/utils/MessageKeys'; | ||
import NamespaceKeys from 'use-intl/dist/src/core/utils/NamespaceKeys'; | ||
import NestedKeyOf from 'use-intl/dist/src/core/utils/NestedKeyOf'; | ||
import NestedValueOf from 'use-intl/dist/src/core/utils/NestedValueOf'; | ||
import getConfig from './getConfig'; | ||
|
||
async function getTranslatorImpl< | ||
NestedKey extends NamespaceKeys< | ||
IntlMessages, | ||
NestedKeyOf<IntlMessages> | ||
> = never | ||
>( | ||
opts: {namespace?: NestedKey} & Omit< | ||
Parameters<typeof createBaseTranslator>[0], | ||
'cachedFormatsByLocale' | ' messagesOrError' | 'namespace' | ||
> | ||
): // Explicitly defining the return type is necessary as TypeScript would get it wrong | ||
Promise<{ | ||
// Default invocation | ||
< | ||
TargetKey extends MessageKeys< | ||
NestedValueOf< | ||
{'!': IntlMessages}, | ||
[NestedKey] extends [never] ? '!' : `!.${NestedKey}` | ||
>, | ||
NestedKeyOf< | ||
NestedValueOf< | ||
{'!': IntlMessages}, | ||
[NestedKey] extends [never] ? '!' : `!.${NestedKey}` | ||
> | ||
> | ||
> | ||
>( | ||
key: TargetKey, | ||
values?: TranslationValues, | ||
formats?: Partial<Formats> | ||
): string; | ||
|
||
// `rich` | ||
rich< | ||
TargetKey extends MessageKeys< | ||
NestedValueOf< | ||
{'!': IntlMessages}, | ||
[NestedKey] extends [never] ? '!' : `!.${NestedKey}` | ||
>, | ||
NestedKeyOf< | ||
NestedValueOf< | ||
{'!': IntlMessages}, | ||
[NestedKey] extends [never] ? '!' : `!.${NestedKey}` | ||
> | ||
> | ||
> | ||
>( | ||
key: TargetKey, | ||
values?: CoreRichTranslationValues, | ||
formats?: Partial<Formats> | ||
): string; | ||
|
||
// `raw` | ||
raw< | ||
TargetKey extends MessageKeys< | ||
NestedValueOf< | ||
{'!': IntlMessages}, | ||
[NestedKey] extends [never] ? '!' : `!.${NestedKey}` | ||
>, | ||
NestedKeyOf< | ||
NestedValueOf< | ||
{'!': IntlMessages}, | ||
[NestedKey] extends [never] ? '!' : `!.${NestedKey}` | ||
> | ||
> | ||
> | ||
>( | ||
key: TargetKey | ||
): any; | ||
}> { | ||
const config = await getConfig(); | ||
|
||
const messagesOrError = getMessagesOrError({ | ||
messages: config.messages as any, | ||
namespace: opts.namespace, | ||
onError: config.onError | ||
}); | ||
|
||
// We allow to resolve rich text formatting here, but the types forbid it when | ||
// `getTranslations` is used directly. Supporting rich text is important when | ||
// the react-server implementation calls into this function. | ||
// @ts-ignore | ||
return createBaseTranslator({ | ||
...config, | ||
...opts, | ||
messagesOrError | ||
}); | ||
} | ||
|
||
export default cache(getTranslatorImpl); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import baseRedirect from '../shared/redirect'; | ||
import getLocale from './getLocale'; | ||
import getLocaleFromHeader from './getLocaleFromHeader'; | ||
|
||
export default function redirect(pathname: string) { | ||
const locale = getLocale(); | ||
const locale = getLocaleFromHeader(); | ||
return baseRedirect(pathname, locale); | ||
} |