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

Port for Remix? #78

Closed
ryexley opened this issue Jan 13, 2022 · 14 comments · Fixed by #81
Closed

Port for Remix? #78

ryexley opened this issue Jan 13, 2022 · 14 comments · Fixed by #81
Labels
enhancement New feature or request

Comments

@ryexley
Copy link

ryexley commented Jan 13, 2022

I really like this library, we've used it with great success in our next.js apps. I've been very interested in using Remix lately, and was wondering how difficult it would be to port this simple, elegant solution over to support Remix as well. Have you done anything with Remix yet at all @amannn??

@ryexley ryexley added the enhancement New feature or request label Jan 13, 2022
@amannn
Copy link
Owner

amannn commented Jan 13, 2022

Hey @ryexley,

Great to hear that you like next-intl! I've been following Remix a bit, but haven't played with it yet.

The integration with Next.js is in fact really slim: The only thing it does is reading a preconfigured locale and passing it to a provider. 99% of the library works the same in regular React apps, if you make use of use-intl.

No idea if Remix has a concept of configuring a locale? If so we could think about a remix-intl package, but otherwise you should be able to use use-intl in your Remix app with all the supported APIs.

@ryexley
Copy link
Author

ryexley commented Jan 13, 2022

@amannn - I would love to start this conversation. I'm not real familiar with, internally, how next.js makes locale information available to the app, but I do know that configuring next-intl, if I'm not mistaken, requires the addition of (or, perhaps just takes advantage of this?) the i18n key in the next.config.js file. Remix apps have the remix.config.js file which appears to be similar. I wonder if a potential remix-intl could take advantage of this similarly?

@amannn
Copy link
Owner

amannn commented Jan 13, 2022

The only thing next-intl really does apart from re-exporting everything from use-intl is adding the NextIntlProvider. You can have a look at the implementation here: https://github.com/amannn/next-intl/blob/main/packages/next-intl/src/NextIntlProvider.tsx.

So if Remix exposes a locale similarly, I think remix-intl would provide a RemixIntlProvider. If not, I think you can just go with use-intl and set the locale yourself on IntlProvider 🙂.

@ryexley
Copy link
Author

ryexley commented Jan 13, 2022

I will look into that. Thanks!

@amannn
Copy link
Owner

amannn commented Jan 13, 2022

Great, let me know how it goes!

@ryexley
Copy link
Author

ryexley commented Jan 13, 2022

I was able to get a bit of a hacky implementation working. Wasn't able to figure out how to get Remix to dynamically resolve and load the translation file from the config settings, but I did get the IntlProvider to work with a statically imported translation file. This will work for now. I would really like to figure out a way to get it to be more dynamic/elegant, but for now, this is working. Thanks again for the great lib.

@amannn
Copy link
Owner

amannn commented Jan 14, 2022

Nice job! Is the loader of a Remix route potentially a good place to fetch and return the right messages?

@ryexley
Copy link
Author

ryexley commented Jan 17, 2022

I ended up doing this in entry.server.tsx and entry.client.tsx, as it was recommended that this would be the most appropriate place to do such a thing. I'm still just manually importing my single translation file, rather than dynamically resolving the selected/detected language, as I've still not figured out a good way to do this yet. Remix doesn't seem to have any support for any kind of dynamic import, which makes this pretty difficult. This works fine for me for right now, as we only do support one language, and just prefer to use an i18n lib for the sake of centralizing the management of all boilerplate text, but, there are plans in the future to support other languages, so this is something I would eventually prefer to figure out how to do better.

@amannn
Copy link
Owner

amannn commented Jan 19, 2022

I've now added a Remix example, maybe it's helpful to you 🙂.

https://github.com/amannn/next-intl/tree/main/packages/example-remix

@ryexley
Copy link
Author

ryexley commented Jan 19, 2022

Ooohhhh thanks @amannn!! I love that your example has the util functions for dynamically evaluating the language and resolving the language files by reading from the file system, that's what I was needing in my solution. The only suggestion I would make for it would be to actually wrap the IntlProvider around the entries in both entry.client.tsx and entry.server.tsx, rather than around the <Outlet /> in root.tsx, as that is what I've done, and was told that would be the most appropriate place for that kind of thing in a remix app. Did you already try that? Run into issues with it?

@ryexley
Copy link
Author

ryexley commented Jan 19, 2022

Also, I've been wondering this. Is there a way to get a translator function outside of a hook, like, for use on the server side?

@amannn
Copy link
Owner

amannn commented Jan 19, 2022

Great to hear if this is helpful! 🙂

The only suggestion I would make for it would be to actually wrap the IntlProvider around the entries in both entry.client.tsx and entry.server.tsx, rather than around the in root.tsx, as that is what I've done, and was told that would be the most appropriate place for that kind of thing in a remix app.

Can you elaborate on why that would be a good idea? On the client, if you don't import the messages directly into the bundle, you'd have to fetch them asynchronously before you're able to render and therefore this would delay the time to interactive. The loader that can be used in root.tsx seems like just the right mechanism for this, as it loads as soon as possible and the data is immediately passed to the client code.

Also, I've been wondering this. Is there a way to get a translator function outside of a hook, like, for use on the server side?

There's currently an open issue about this, but I didn't have the time to look into this yet: #47

@ryexley
Copy link
Author

ryexley commented Jan 21, 2022

Can you elaborate on why that would be a good idea?

I don't fully grok how entry.client.tsx and entry.server.tsx work, but I asked the question in the Remix Discord help channel, and was advised that those would be the most appropriate place to put the IntlProvider, and it seems to be working well for me.

@amannn
Copy link
Owner

amannn commented Jan 24, 2022

As far as I understand hose files are the entry points for the client and server respectively, i.e. the first thing that runs in the given environment. They definitely allow you to wrap the tree, but I'd suggest to not do anything async in the client side entry point, as it will delay the client side render. So for a use case of importing messages from one locale statically this will work just fine, but once you have multiple locales and need dynamic imports, an unnecessary delay will be introduced.

By wrapping the tree in root.tsx using a loader you can avoid this.

Note to myself: Maybe something that would be interesting for a potential remix-intl is integrating with Remix cookies to remember a resolved language. It's very little integration code though, not sure yet if it's a good idea and also we'd have to handle different "strategies" then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants