-
-
Notifications
You must be signed in to change notification settings - Fork 251
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
Enable passing messages to 'useTranslations' without context #507
Comments
Hey, thank you so much for this interesting question! I'm really curious, is there any public information available about the project you're working on? Optionally passing
That's really interesting! I'm currently collecting thoughts in regard to this in #1, but haven't started working on it yet. Can you provide details how this would work with your project?
Is there anything in
I'd also be curious to see where this is going! In the localization management docs we currently mention Crowdin In-Context, which seems to be similar to what you're aiming for. Would be really cool to hear a bit more about your project. If there are no downsides, I'm more than happy to support it! |
Hey @amannn, here is information about the project:
The project is still in early development, but this should give you a rough idea about what the project will look like. In regards to #1, my current intention is for translations to be split up into namespaces. Using the Pages Router, each page specifies the namespaces it requires: Page.getInitialProps = async (ctx) => {
// Only include the messages for the 'foo' and 'bar' namespaces
const strings = await getStrings(ctx, [ "foo", "bar" ]);
return { strings };
} Consuming these namespace-specific messages in import { useTranslations } from "next-intl";
const t = useTranslations("foo");
t("key");
// OR
import { useTranslations } from "next-intl";
const t = useTranslations();
t("foo.key"); While in the App Router:
// Wrapping a Client Component
import { ClientComponentProvider } from "@streave/next/next-intl/server";
<ClientComponentProvider locale={locale} namespaces={["foo"]}>
<ClientComponent />
</ClientComponentProvider> // Using async hooks in Server Components
import { useTranslations } from "@streave/next/next-intl/server";
const t = await useTranslations("server-component", { locale });
Aside from this specific issue (#507), no, I've found |
Oh wow, cool project! So in regard to #1, you'd still configure all the namespaces manually, right? Are you interested in potentially providing an automatic way for this or are you fine with the manual approach? Generally it seems like there's quite some overlap between the RSC support for We've bikeshedded over APIs like I have to say though that this is also a source of frustration, because due to the implementation, What is currently only briefly mentioned in the Streave docs is the loading translations part. Do you have public plans for the loading translations part in Streave? I'm digging a bit more into these topics because I'm trying to figure out where next-intl and Streave overlap and where they complement each other. |
This is not publicly documented yet, but the The When using the file system (i.e. tracking translations in Git), this syncing/mapping work is not applicable. The async import { createTranslator } from "next-intl";
export async function useTranslations(namespace: string, options: { locale: string }) {
const { locale } = options;
const strings = await getStrings({ locale }, [namespace]);
const translator = createTranslator({
locale,
namespace,
messages: stringsToNextIntlMessages([strings]),
});
return translator;
} Ideally, I would like the implementation to become: // could also be imported, e.g. from 'next-intl/withoutContext' to avoid
// adding options to the main 'useTranslations' hook
import { useTranslations as useNextIntlTranslations } from "next-intl";
export async function useTranslations(namespace: string, options: { locale: string }) {
const { locale } = options;
const strings = await getStrings({ locale }, [namespace]);
const messages = stringsToNextIntlMessages([strings]);
return useNextIntlTranslations(namespace, { locale, messages })
} (The exact interface is not terribly important for this purpose. The ability to pass messages directly to This hook is being used in the |
That prefetching and revalidation with What I currently don't understand is why You should be able to use If you do that, users of
My concern with this is that we're going for a non-async hook in Does that make sense? Would be curious to hear your perspective! |
I explored that, but it conflicts with how I want the revalidation behavior and DX of For example, if I load a page which calls The experience I want is something like:
Because This is the core reason behind why Ideally, I would like to avoid wrapping import { useTranslations } from "next-intl"
import { getMessages } from "@streave/next/next-intl/server"
const messages = await getMessages("namespace", { locale });
const t = useTranslations("namespace", { messages, locale }); The main problem here is the repetition. To avoid it, we could explore adding an import { useAsyncTranslations } from "next-intl"
import { getMessages } from "@streave/next/next-intl/server"
const t = useAsyncTranslations("namespace", { locale, getMessages }); The async function useAsyncTranslations(...) {
const messages = await getMessages({ namespace, locale });
return useTranslations(namespace, { locale, messages });
} Which provides Doing this would avoid wrapping Does something along these lines make sense? I would love to hear your thoughts |
Hey, sorry for the late response! I'm unfortunately quite busy this week and don't have so much time for digging deeper into this. In regard to your initial question: The RSC beta versions that are being published for It's intended as an internal API but I guess you could use it for your use case since it has the capability of returning a I hope this helps for the time being, would be happy to continue this conversation when I have more time! |
Exposing |
A quick heads up: In Some background: #406 (comment) |
Is your feature request related to a problem? Please describe.
Context
I'm currently developing a library that makes integrating i18n libraries into Next.js apps easier. It's not intended to replace libraries like
i18next
andnext-intl
. Instead it supplements them by, for example:These features are out-of-scope for
next-intl
itself, but I believe they could be useful for users ofnext-intl
.Problem
useTranslations
currently reads the messages fromuseIntlContext
, which is using React contexts.This works great in Client Components, but
useTranslations
cannot be used in Server Components because of its usage of React contexts.(
useTranslationsImpl
also uses React context to read various configuration information such as locale, timezone, etc)To avoid React contexts, I took a look at using
createTranslator
:This works great when just using
t()
, butt.rich()
does not allow the use of React nodes:The
next-intl
documentation does document these limitations on this page, including the workaround (which is using Client Components). It mentions that these limitations will apply untilcreateServerContext
is.Describe the solution you'd like
I would like to be able to circumvent React contexts by passing the required data to
useTranslations
manually.This would enable the use of
useTranslations
in Server Components.As an example,
react-i18next
supports this by exposingreact-i18next/TransWithoutContext
:next-intl
could do a similar thing:Alternatively,
createTranslator
could be updated to not require the return value to be a string (an option could be added to enable that, or a different function e.g.createReactTranslator
could be added).I would be more than willing to implement one of these and create a PR.
Describe alternatives you've considered
It's possible to work around this issue by using Client Components, as documented.
The text was updated successfully, but these errors were encountered: