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

docs: React server components example and docs #1903

Closed
wants to merge 4 commits into from

Conversation

fromthemills
Copy link

@fromthemills fromthemills commented Apr 3, 2024

Description

  • Adds a new Nextjs tutorial docs
  • Adds an example using lingui 4.8.0 in Next.js

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Examples update

Fixes # (issue)

Checklist

  • I have read the CONTRIBUTING and CODE_OF_CONDUCT docs
  • I have added tests that prove my fix is effective or that my feature works
  • [] I have added the necessary documentation (if appropriate)

Copy link

vercel bot commented Apr 3, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
js-lingui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 9, 2024 9:53am

Copy link

github-actions bot commented Apr 3, 2024

size-limit report 📦

Path Size
./packages/core/dist/index.mjs 2.86 KB (0%)
./packages/detect-locale/dist/index.mjs 723 B (0%)
./packages/react/dist/index.mjs 1.67 KB (0%)
./packages/remote-loader/dist/index.mjs 7.26 KB (0%)

@andrii-bodnar andrii-bodnar changed the title React server components example and docs docs: React server components example and docs Apr 3, 2024
Copy link

codecov bot commented Apr 3, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 76.57%. Comparing base (d6b9698) to head (2b1f3a4).
Report is 16 commits behind head on main.

❗ Current head 2b1f3a4 differs from pull request most recent head c571663. Consider uploading reports for the commit c571663 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1903      +/-   ##
==========================================
- Coverage   76.65%   76.57%   -0.08%     
==========================================
  Files          81       82       +1     
  Lines        2090     2092       +2     
  Branches      533      534       +1     
==========================================
  Hits         1602     1602              
- Misses        375      377       +2     
  Partials      113      113              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@andrii-bodnar
Copy link
Contributor

andrii-bodnar commented Apr 3, 2024

Hi @fromthemills, thanks a lot for the contribution!

I just read through the PR and have some suggestions:

  • Please follow the existing Next JS examples in terms of code formatting and project structure.
  • The example is not fully complete, as the extract and compile are missing.
  • It would also be great to have a locale switcher in the example (preferably with full page reload).
  • Add a link to the Examples page.
  • Take a look at the validation issues.

@timofei-iatsenko
Copy link
Collaborator

i quickly check the example, here is my first impressions:

  1. TransNoContext probably will not be picked up by extractor
  2. TransNoContext wasn't created for direct usage
  3. We encourage using Macro, i would prefer following this way
  4. I think this tutorial should be in separate page not in the React Patterns
  5. nextjs-sc is probably not really clear name, RSC is more often used term or nexts-app-folder

@fromthemills
Copy link
Author

fromthemills commented Apr 3, 2024

  1. I think this tutorial should be in separate page not in the React Patterns

@thekip Would you like this under Tutorials or Guides?

  1. TransNoContext probably will not be picked up by extractor
  2. TransNoContext wasn't created for direct usage

True it is not picked up by the extractor. Any suggestions for how we will "recommend" to do server only translations? Just using the instance? like:

i18n._('Learn')

@andrii-bodnar
Copy link
Contributor

What about creating a separate Tutorial page? As described in #1876

@vonovak
Copy link
Collaborator

vonovak commented Apr 7, 2024

Hello and thanks for the PR!
As noted in #1876, I was going to write the NextJS tutorial, though didn't get to do it in the time I had hoped for.

I already have have a good idea of what I wanted to cover and I was planning to make it a little more comprehensive:

  • example project and documentation should use TypeScript. All our examples are in TS and this should be no different. To take this a step further, why do we need another example? The pages and app router can live together in one application. I would find it strongly preferable to not add another example if we don't need to.
  • TransNoContext shouldn't be necessary (well, it is, but not scattered across the userland code), Trans should cover everything
  • some other changes as said above, but not only that

It would also be great to have a locale switcher in the example (preferably with full page reload).

@andrii-bodnar actually the locale switcher, as far as I can tell, should demonstrate that a full page reload is not needed (why do you think it should use full page reload?).

However, when this all adds up, I fear it could take a lot of time to get aligned using the standard loop of [write code -> get a review -> address review], as each step takes time on one side or the other. So the way I see it we can (1) do the loop, or (2) merge this into a side branch of this repo, and I could take it from there and iterate toward a version that addresses the above. That way also your time and commits are reflected in the repo history. Just a suggestion - happy to do it either way.

Thank you! :)

@fromthemills
Copy link
Author

@thekip @andrii-bodnar I incorporated your feedback into the PR.

Most notable changes:

  • Added Next.js tutorial page (added some config stuff and install instruction etc.)
  • Added a nextjs example based on the original next-swc example. I tried to stay as close to that example as possible.

@vonovak I would prefer to just merge this. I think it kind of covers most things. Maybe after the merge you can refine more?

Future works

Right now for server components translations I use the t macro like below:

t(i18n)`Home`

Obviously this is not ideal but as @thekip mentioned TransNoContext wasn't created for direct usage and it also does not get picked up by the extractor. So maybe we need to work towards a TransServer component or something and make the cache functions getI18n and setI18n part of the @lingui/react package?

import { TransServer } from '@lingui/macro'
import { setI18n } from '@lingui/react'

And then maybe in a next version add some dynamic switching capabilities like the POC @thekip made

Something to think about

@vonovak
Copy link
Collaborator

vonovak commented Apr 7, 2024

TY, this is much better, though I'd still prefer to have one example over two 🤔. edit: but I guess it's okay, sorry for showing up late with my comments.

@fromthemills may I ask why you didn't use the server-side Trans, as you linked? TY :)

btw the docs import TransNoContext but don't use it. (I'll do a more thorough review later).

@fromthemills
Copy link
Author

fromthemills commented Apr 7, 2024

TY, this is much better, though I'd still prefer to have one example over two 🤔. edit: but I guess it's okay, sorry for showing up late with my comments.

No worries. True... one example might be better. But the old example used pages dir and I was not sure if I was "allowed" to alter the other example. If we want to keep both an example with pages dir and one with app dir it might be better to keep it in separate examples. Although you can use both pages and app in the same project the example would be to confusing I think. We might just rename to nextjs-pages and nextjs-app?

btw the docs import TransNoContext but don't use it. (I'll do a more thorough review later).

Nice catch, thank you. Removed them.

@fromthemills may I ask why you didn't use the server-side Trans, as you linked? TY :)

Good point. Mainly, I did not want to use the more "experimental" part of the POC with the LinguiTransRscResolver etc. Secondly I did not want to alter the original Trans component, as we still need to support client translation also. And thirdly because the extraction did not work when I define my own Trans components. But if I understand correctly you can make this work with runtimeConfigModule? Not sure... @vonovak how would you do this? What is your opinion on the "LinguiTransRscResolver" stuff of the POC?

I see possible future in that in a next version of Lingui React you might be able to setup a i18n "context" with Lingui in 2 ways:

  1. Using the LinguiProvider primary be used for client components only
  2. Using a new function something like setI18n or cacheI18n which would use the new React cache api.

Usage can than differ from client and server components

// client components only
import { I18nProvider } from '@lingui/react'
import { Trans, t } from '@lingui/macro'

<I18nProvider> // sets client context and part of js bundle
   {t`Hello`} 
   <Trans>Hello</Trans> // also part of js bundle
</I18nProvider>
// client or server components
import { setI18n } from '@lingui/react/server'
import { Trans, t } from '@lingui/macro/server'

setI18n(...) // sets server context
{t`Hello`}
<Trans>Hello</Trans> // server only not part of js bundle

After that we could than go one step further and create a new package called @lingui/rsc-webpack-resolver or something. Which would basically allow you to use Trans or t in both context and Lingui would figure out what context to use and automatically switches between the client or server component like in the POC. But still having the underlying primitives feels import to me.

import { I18nProvider } from '@lingui/react'
import { setI18n } from '@lingui/react/server'
import { Trans, t } from '@lingui/macro/resolve'

setI18n(...) // sets server context
<I18nProvider> // sets client context
   {t`Hello`} 
   <Trans>Hello</Trans> // Knows render context and switch to use "@lingui/react/server" or " '@lingui/react"
</I18nProvider>
/** @type {import('next').NextConfig} */
module.exports = {
  webpack: (config) => {
    config.resolve.plugins.push(require('@lingui/rsc-webpack-resolver');
    return config;
  },
}

@timofei-iatsenko
Copy link
Collaborator

timofei-iatsenko commented Apr 8, 2024

I recently realized that neither TransNoContext nor macro + runtimeConfigModule will not be picked up by extractor.

There are two ways to fix that, one is explicitly add TransNoContext to extractor, which is one-liner change. Or make a refactoring to make extractor more robust and future-proof and supports runtimeConfigModule out of the box. I took second option and already working on a PR.

@vonovak
Copy link
Collaborator

vonovak commented Apr 8, 2024

I'll need to double-check but for me, it seemed that using the LinguiTransRscResolver worked fine with extraction 🤔, when importing like this: import { Trans } from "@lingui/macro" .

I think it's fine to document using LinguiTransRscResolver in the docs, provided we make it clear this is an unstable api. In case of RSC, there will be demand for using lingui with RSC without the need for "use client", so because it's possible, I would document it, and if the unstable part breaks, falling back to client components is a quick fix that doesn't hurt much.

Secondly I did not want to alter the original Trans component

I didn't do any alterations there so not sure what you have in mind 🤔

It's true that I didn't use the t macro, only msg so I may have "skipped" some headaches that you may have encountered.

From your examples:

import { Trans, t } from '@lingui/macro/server'

Ideally we should only need @lingui/macro AFAICT. For t this might be a little more difficult than for though.

import { setI18n } from '@lingui/react/server'

My take is: we shouldn't add setI18n to lingui, at least not for now. We should avoid RSC-specific apis in this library. These functions should be documented but people will copy-paste them into their code. It's just a few lines so it doesn't hurt, and for us we don't need to worry about maintaining these apis. RSC is very young, stuff might change, so let's avoid having responsibility for these apis. Ofc we will document this accordingly.

@timofei-iatsenko
Copy link
Collaborator

These functions should be documented but people will copy-paste them into their code. It's just a few lines so it doesn't hurt, and for us we don't need to worry about maintaining these apis. RSC is very young, stuff might change, so let's avoid having responsibility for these apis. Ofc we will document this accordingly.

or extract a separate package, specifically for nextjs.

I think if we will go with the way of LinguiTransRscResolver we can simply create a nextjs plugin which will wrap nextjs configuration and implement necessary amendments.

@fromthemills
Copy link
Author

fromthemills commented Apr 8, 2024

My take is: we shouldn't add setI18n to lingui, at least not for now. We should avoid RSC-specific apis in this library. These functions should be documented but people will copy-paste them into their code. It's just a few lines so it doesn't hurt, and for us we don't need to worry about maintaining these apis. RSC is very young, stuff might change, so let's avoid having responsibility for these apis. Ofc we will document this accordingly.

I agree adding this to Lingui itself might be to contrived... the APIs are to unstable ATM.

I think if we will go with the way of LinguiTransRscResolver we can simply create a nextjs plugin which will wrap nextjs configuration and implement necessary amendments.

Yeah, also leaning more in this direction of @lingui/nextjs. It could expose 2 apis like below.

// next.config.js
const { withLingui }  = require('@lingui/nextjs')

// sets up swc plugin and resolver 
module.exports = withLingui({
  // Other Next.js configuration goes here
});
// page.js or layout.js
import { setI18n }  from '@lingui/nextjs'

setI18n('en')

The only thing I don't like about it is that you would not have access to the underlying primitives and you are relying on the resolver and swc plugin config (runtimeModules) to do the switching. Or maybe something like below is possible? I don't know... maybe to complicated.

import { setI18n } from '@lingui/nextjs'
import { Trans, t } from '@lingui/nextjs/macro' // always uses get18n

@timofei-iatsenko
Copy link
Collaborator

timofei-iatsenko commented Apr 8, 2024

Firstly, guys, I want to say a big thank to all of you. I really appreciated that someone take contributions that seriously and willing to discuss and help. I'm lacking this "second opinion" for most of the time.

What is your opinion on the "LinguiTransRscResolver" stuff of the POC?

This thing is actually bothered me from the beginning. I used some non-documented internals of nextjs, which might be subject of change at any time. From other side the concept is neat and gives excellent DX. We can try to reach nextjs team and ask them to make this public or at least notify them that one of the libraries relaying on that and them what they think.

Also, just to be on the same page want to share latest changes which may affect discussion here:

The only thing I don't like about it is that you would not have access to the underlying primitives and you are relying on the resolver and swc plugin config (runtimeModules) to do the switching. Or maybe something like below is possible? I don't know... maybe to complicated.

If the way with standardizing LinguiTransRscResolver will not work, we can expose underlying primitives as well.

i'm thinking about a more radical solution, what if we allow a macro to process a user defined symbol? (this will not work with babel-macro-plugin, but will work in all other compilers, babel-plugin and swc)

// config
macro: {
  {
     module: "@myApp/lingui-trans-rsc",
     export: "TransRsc"
  }
}

// will process
import {TransRsc} from "@myApp/lingui-trans-rsc"

<TransRsc>Hello</TransRsc>

// into
import {TransRsc} from "@myApp/lingui-trans-rsc"
<TransRsc id="<hash>" message="Hello"></TransRsc>

This will unblock people to use macro with custom Trans implementations (which we also provide out of the box for RSC) and not rely on the potentially unstable LinguiTransRscResolver

config.module.rules.push({
test: /\.po/,
use: [
options.defaultLoaders.babel,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this line? @lingui/loader should return a ready to use module for webpack

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, your right it is not needed. Coppied it from an example.

}
```

As you can see in the example above we slight modified the default `I18nProvider` with our own implementation. Here we pass the active message catalog as a prop. This is to avoid importing all catalogs inside the `I18nProvider` component itself and thus making them part of the client bundle. For the people who are wondering: Why we are not just passing an instance of `i18n` the original provider component? Server components can pass data to client components but the caveat is that this needs to be serializable data and `i18n` is not.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we will go with "@lingui/nextjs" may be pre-made this provider in that package?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... not 100% sure. One the one hand you would want the package to "batteries included" but you don't want to inflate the scope to much. Leaning more to "it should be included".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point, I'm not for creating @lingui/nextjs package. Let's lay the groundwork first, try to be as universal as possible and see later about adding framework-specific packages?


Finally an example of a locale switcher.

```jsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tsx

@timofei-iatsenko
Copy link
Collaborator

'll need to double-check but for me, it seemed that using the LinguiTransRscResolver worked fine with extraction 🤔, when importing like this: import { Trans } from "@lingui/macro" .

I've checked my PoC once again, and yes, the TransNoContext used in conjunction with Trans macro will work in that case, because runtimeModules defined directly as SWC plugin options and not in the Lingui Config. So when extractor launched, it knows nothing that Trans is actually replaced to TransNoContext.

@timofei-iatsenko
Copy link
Collaborator

One more thing to consider is Turbopack, the LinguiTransRscResolver might be not compatible with that thing.

@timofei-iatsenko
Copy link
Collaborator

Created an issue in NextJs repo vercel/next.js#64244

@fromthemills
Copy link
Author

Firstly, guys, I want to say a big thank to all of you. I really appreciated that someone take contributions that seriously and willing to discuss and help. I'm lacking this "second opinion" for most of the time.

Love the project ❤️

One more thing to consider is Turbopack, the LinguiTransRscResolver might be not compatible with that thing.

Dang 🫠

We recently implemented const {t} = useLingui() macro which is awesome, probably we need to have a counterpart for RSC components, that way you will not need global t at all.

We could either incorporate this into getI18n or also provide a getLingui functions which aims to be the counterpart of useLingui but for rsc.

i'm thinking about a more radical solution, what if we allow a macro to process a user defined symbol? (this will not work with babel-macro-plugin, but will work in all other compilers.

I really like this approach

@thekip I added your changes. Also took the liberty to update the current nextjs example to nextjs-pages. So we now have:

  • Next.js with app router & SWC -> examples/nextjs-app (my new example)
  • Next.js with pages router & SWC -> examples/nextjs-pages
  • Next.js with pages router & Babel -> examples/nextjs-pages-babel

How do we see this PR? Do we merge this as is? It currently covers the basics without to much of the experimental stuff. And as I said before just using client component Trans in rsc is ok for most developers for now. Using setI18n and t(i18n)'Hellow' provides an "escape hatch" for server only translations. The @lingui/nextjs might take while to get going, so...

We could wait on #1909, to include TransNoContext example?

@timofei-iatsenko
Copy link
Collaborator

Long story short, we can use react-server condition in package.json exports instead of webpack plugin. vercel/next.js#64244 (comment)

What i'm thinking right now is how to correctly implement it in lingui.

We can expose RscTrans (from my PoC) as just Trans under the react-server condition.
Also, i'm thinking of encapsulating seti18n / geti18n / RscLinguiProvider into the @lingui/react/server. It's not only about nextjs support, but every other RSC-enabled framework may use it.

Features to consider:

  • global t
  • useLingui macro hook or alternative

I want to prepare another PoC with changes I mentioned to prove the ideas.

@timofei-iatsenko
Copy link
Collaborator

Tested, that works, let's discuss public API, how i see that:

@lingui/react/server

  • setI18n(i18n: I18n)
  • getI18n(): I18n
  • TransNoContext (mostly to provide internal primitives)

@lingui/react

  • Trans - condition == react-server ? TransRSC : Trans
  • useLingui - condition == react-server ? useLinguiRsc : useLingui

I believe it would be a good idea to include i18nProvider with serializable input in @lingui/react/server and make call to seti18n() in that. So users have to only wrap root of the tree into that provider.

However, Next.js app router behavior is extremely weird. While SSR layouts executed after pages, but context inside react tree is flowing from layout to pages (means layout components executed before pages)

That means for us that react context provider in Layout will be propagated to pages, but seti18n will not. Therefore, if we will create a provider which doing context + seti18n in one piece, users will still need to put it in the layout AND in the pages.

If we will not merge provider with seti18n, user will have to put seti18n in every page (not layout), and Provider could be only on the layout level.

Both options have pros and cons.

I didn't find a way where we can set React.cache() application wide, it seems it's impossible for now.

@timofei-iatsenko
Copy link
Collaborator

Global t is not recommended to use in nextjs with RSC at all, instead geti18n + msg macro, or useLingui macro

@andrii-bodnar
Copy link
Contributor

Available in the v4.10.0 🚀

@fromthemills could you please consider the new features in the example and the article? There is an example mentioned here - #1914

@fromthemills
Copy link
Author

@andrii-bodnar @thekip Will incorporate the new changes in the docs

Copy link
Collaborator

@vonovak vonovak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we're not done here yet, just wanted to leave a few comments for the next iteration. thank you for the work! :)

Comment on lines +22 to +23
```js
//next.config.js
Copy link
Collaborator

@vonovak vonovak Apr 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```js
//next.config.js
```js title="next.config.js"

And please do the same for other files


type Props = {
locale: string
messages?: any
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

messages can be types like this:

import { type Messages } from "@lingui/core"

children: React.ReactNode
}

export function I18nProvider({ locale, messages, ...props }: Props) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest this implementation:

export function LinguiClientProvider({
  children,
  initialLocale,
  initialMessages,
}: {
  children: React.ReactNode
  initialLocale: string
  initialMessages: Messages
}) {
  const [i18n] = useState(() => {
    return setupI18n({
      locale: initialLocale,
      messages: { [initialLocale]: initialMessages },
    })
  })
  return <I18nProvider i18n={i18n}>{children}</I18nProvider>
}

with the above, depending on how users set it up, the provider might end up re-rendering and if that happens, new i18n instance would be constructed, and all Trans client components would re-render.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use a useMemo with [locale, messages] deps?

I don't really understand why it's became initial since, when language switched this provider would be called with new props

Since version 13+ Next.js allows you to use [server components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) using the app directory. Lingui can easily be used with server components. There are however some considerations to be made so we can make optimal use of server components and it's capabilities.

1. We want to avoid shipping to much js to the browser if it is not needed
2. We want to be able to easily distinguish between client component translations (part of the js bundle) and server component translations.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain why? 🤔

}
```

As you can see in the example above we slight modified the default `I18nProvider` with our own implementation. Here we pass the active message catalog as a prop. This is to avoid importing all catalogs inside the `I18nProvider` component itself and thus making them part of the client bundle. For the people who are wondering: Why we are not just passing an instance of `i18n` the original provider component? Server components can pass data to client components but the caveat is that this needs to be serializable data and `i18n` is not.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point, I'm not for creating @lingui/nextjs package. Let's lay the groundwork first, try to be as universal as possible and see later about adding framework-specific packages?

Comment on lines +180 to +182
if (locale === 'fr') {
return fr
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as you add more languages, this pattern grows not nice, I suggest using an object

https://dev.to/rjitsu/stop-using-if-else-264o

Copy link
Collaborator

@timofei-iatsenko timofei-iatsenko Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point, I'm not for creating @lingui/nextjs package

This is no longer a proposition after discovering react-server export condition.

(for some reason it will not give me an ability to left a reply under the original comment)


Since version 13+ Next.js allows you to use [server components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) using the app directory. Lingui can easily be used with server components. There are however some considerations to be made so we can make optimal use of server components and it's capabilities.

1. We want to avoid shipping to much js to the browser if it is not needed
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. We want to avoid shipping to much js to the browser if it is not needed
1. We want to avoid shipping too much js to the browser if it is not needed

@vonovak
Copy link
Collaborator

vonovak commented Apr 15, 2024

However, Next.js app router behavior is extremely weird. While SSR layouts executed after pages, but context inside react tree is flowing from layout to pages (means layout components executed before pages)

I also think that layouts are not executed for client-side route transitions, so basically I ended up wrapping all layouts and pages in withLingui which is a HOC that calls setI18n and then makes the i18n instance available everywhere. Not the best but I like it a little more than Provider everyhwere.

@andrii-bodnar
Copy link
Contributor

andrii-bodnar commented May 2, 2024

Hi @fromthemills, do you need any help with finishing this PR?

@vonovak
Copy link
Collaborator

vonovak commented May 4, 2024

Hi! I'll be happy to take this over the finish line but I'm vacationing now, so I can look into this after 22/5, unless @fromthemills plans to do that 👍.

@vonovak
Copy link
Collaborator

vonovak commented May 22, 2024

Since there's no news on this, I'll get started on this soon, probably later this week. 👍

@andrii-bodnar andrii-bodnar marked this pull request as draft May 29, 2024 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants