i18next / i18next-http-backend

i18next-http-backend is a backend layer for i18next using in Node.js, in the browser and for Deno.
MIT License
443 stars 67 forks source link

HTTP Backend's reload doesn't work after initial failed fetch #142

Closed tomdardev closed 2 months ago

tomdardev commented 2 months ago

Hello all, I believe I have identified an issue with the HTTP Backend's reload behaviour.

🐛 Bug Report

The bug seems to specifically happen when an HTTP request fails.

To Reproduce

codesandbox

Essentially, after a failed fetch I have no way of actually forcing a reload of the key (except by setting a reload interval which for a few reasons is not an option for us)

Expected behavior

There should be some way to force a fetch of failed resources.

Your Environment

Same as in the code sandbox: "i18next": "22.5.1", "i18next-http-backend": "2.5.2", "react": "17.0.2", "react-dom": "17.0.2", "react-i18next": "12.3.1", "react-scripts": "^5.0.0", "typescript": "4.4.4"

tomdardev commented 2 months ago

On a side note: the typescript definition for the HttpBackendOptions seems incorrect. The documentation hints at the callback accepting a null value which is not reflected in the definition.

adrai commented 2 months ago

depends on the status code: https://github.com/i18next/i18next-http-backend/blob/master/lib/index.js#L75

regarding the ts definition, feel free to provide a PR

tomdardev commented 2 months ago

Thank you for the quick response, I will provide a PR for the fixed ts definition in the coming days.

From my understanding and what I'm seeing in the product and also another code sandbox that I created here (purely looking at the log output), the status code only controls retry behavior, i.e. that if an error occurs the backend will retry the request after an interval.

In my case however I need to be able to control when the request is sent again. Just a retry mechanism is not good enough just by itself.

Why is it that as long as all requests are successful, any call to the i18n.reloadResources function results in another fetch of the data by the http backend but as soon as a request results in an error and the retries also don't succeed, any subsequent call to i18n.reloadResources results in nothing happening?

In the example of the codesandbox from this comment, unless you hit the toggle button in the time window where the retries are happening, there seems to be no way to load the translations after the retries are done

jamuhl commented 2 months ago

as i18next does not reload failed requests: https://github.com/i18next/i18next/blob/master/src/BackendConnector.js#L54

I leave it open if i18next should load those if reload flag in option is set or if permanently failed requests (after retry) should be handled by devs

personally I don't know cases were reloading just a failed namespace makes sense...most time either it fails all or nothing...but @tomdarshan might describe his use case in more details

tomdardev commented 2 months ago

My use case specifically is a web app (for an executable application, not a website) which features a login prompt. The user is first presented with the login prompt after loading the page (this is where the requests run into a 401, since no authentication details have been set yet but the translation endpoints are also protected).

If there was a way to delay the initial loading of translations, that would also be fine for my use case. It's currently looking like I'm gonna be removing protection from the translation endpoints to avoid the issue.

This wouldn't eliminate the root of the issue entirely though. Although I have to admit that errors would become exceedingly rare. With the current options essentially any other errors which are not resolved by the retries would lead to the same issue of untranslated keys again.

One could imagine a scenario where the client/host is having connectivity issues temporarily after the initial page load but stubbornly keeps attempting to log in. In a case where this does work after a few tries since connectivity has been restored, he would then also be stuck with untranslated keys until he is annoyed enough to reload the page. I'm sure that with enough imagination there is plenty of edge cases like this.

It's not that the severity of these is extreme or that they would happen commonly but that they could be guarded against by allowing the reload of failed namespaces or in general some more control over the lifecycle of i18n translations.

adrai commented 2 months ago

If you want, you can delay the init of i18next... Or have 2 i18next instances (one with some inline translations (maybe only english) initialized before login... and a second one (with http-backend) initialized after login.

tomdardev commented 2 months ago

I see, thank you for the information. In that case that would also solve my immediate problem.

Personally as a dev I would still like to have a little more control over what happens when an error is encountered, but this is not a big topic for me and I'm not willing to further delve into why things are the way they are and what they should be like at the moment.

I've put forth a PR for the typescript definition change. So from my end please feel free to close this issue. (I'm not very familiar with Github and your policies. I'm not sure if I'm supposed to link the PR to this ticket and how to do it/if I can)