Skip to content

Fix multiple changeLanguage calls may resolve to a wrong language#2298

Merged
adrai merged 1 commit into
i18next:masterfrom
waivital:changelanguage-call-order
Apr 15, 2025
Merged

Fix multiple changeLanguage calls may resolve to a wrong language#2298
adrai merged 1 commit into
i18next:masterfrom
waivital:changelanguage-call-order

Conversation

@waivital

@waivital waivital commented Apr 10, 2025

Copy link
Copy Markdown
Contributor

Fix #1605

Checklist

  • only relevant code is changed (make a diff before you submit the PR)
  • run tests npm run test
  • tests are included
  • commit message and code follows the Developer's Certification of Origin

Checklist (for documentation change)

  • only relevant documentation part is changed (make a diff before you submit the PR)
  • motivation/reason is provided
  • commit message and code follows the Developer's Certification of Origin

@coveralls

coveralls commented Apr 10, 2025

Copy link
Copy Markdown

Coverage Status

coverage: 95.886% (+0.003%) from 95.883%
when pulling 6617013 on waivital:changelanguage-call-order
into 59498ae on i18next:master.

@adrai

adrai commented Apr 10, 2025

Copy link
Copy Markdown
Member

this PR will increase the package by approx. 3kb... this will undo all our efforts at v24 to reduce the bundle size... fyi: @VIKTORVAV99

@adrai

adrai commented Apr 10, 2025

Copy link
Copy Markdown
Member

maybe this is already sufficient?
image

@waivital

Copy link
Copy Markdown
Contributor Author

@adrai Oh, you are right, this is indeed much simpler, and the test case still passed.

@waivital waivital force-pushed the changelanguage-call-order branch from f4e4474 to 94e4e7b Compare April 11, 2025 02:52
@adrai

adrai commented Apr 11, 2025

Copy link
Copy Markdown
Member

I think the new option is not necessary. Please remove it.
We just do it always.

@waivital

waivital commented Apr 11, 2025

Copy link
Copy Markdown
Contributor Author

But it may introducing breaking changes. If someone relies on the old behavior, their code might stop working after the upgrade.

And another concern is here

i18next/src/i18next.js

Lines 348 to 354 in 94e4e7b

if (this.isLanguageChangingTo === lng) {
setLngProps(l);
this.translator.changeLanguage(l);
this.isLanguageChangingTo = undefined;
}
this.emit('languageChanged', l);
this.logger.log('languageChanged', l);

The languageChanged event no longer represents the real language changed event. To fix that, maybe here need to reject the outdated defer and pass an error to the callback.

@adrai

adrai commented Apr 11, 2025

Copy link
Copy Markdown
Member

The old behaviour is not reliable by itself... so this does not matter.

@waivital

Copy link
Copy Markdown
Contributor Author

I still feel that it is a bit too hasty to change it directly, after all, this problem has existed for so long. Lots of project already adopted with i18next's old behaviour.

@adrai

adrai commented Apr 11, 2025

Copy link
Copy Markdown
Member

The old wrong behaviour occurs only if the changeLanguage is used in a wrong way. So this is a fix after all... But if you think this is breaking we will release a new major release... no problem. But I don't like to introduce a new option because of a "bug" or "wrong usage" behaviour.

@adrai

adrai commented Apr 11, 2025

Copy link
Copy Markdown
Member

But it may introducing breaking changes. If someone relies on the old behavior, their code might stop working after the upgrade.

And another concern is here

i18next/src/i18next.js

Lines 348 to 354 in 94e4e7b

if (this.isLanguageChangingTo === lng) {
setLngProps(l);
this.translator.changeLanguage(l);
this.isLanguageChangingTo = undefined;
}
this.emit('languageChanged', l);
this.logger.log('languageChanged', l);

The languageChanged event no longer represents the real language changed event. To fix that, maybe here need to reject the outdated defer and pass an error to the callback.

feel free to optimize this... an alternative to a "reject" could be also an additional parameter that illustrates that a subsequent changeLanguage call has "overwritten" this one...

btw: this is even better in my opinion:
image

And since we can make a major release, we can just keep it like that (no reject, etc...) and document this new behaviour in the changelog and in the migration guide.

@waivital

waivital commented Apr 11, 2025

Copy link
Copy Markdown
Contributor Author

Make sense to me, I'll look into this a bit later.

@waivital waivital force-pushed the changelanguage-call-order branch from 94e4e7b to 6617013 Compare April 12, 2025 04:24
@waivital

Copy link
Copy Markdown
Contributor Author

I was thinking if we could optimize the changeLanguage function. It seems to involve three things: detect the language using a detector if language not provided, normalize the detected language, and load the language resources then set the related state. Maybe we can separate these steps to make the process clearer.

I created a new branch for this idea, if it looks good, I'll create a new PR for it.
https://github.com/waivital/i18next/commits/optimize-changelanguge-function/

@jamuhl

jamuhl commented Apr 12, 2025

Copy link
Copy Markdown
Member

I was thinking if we could optimize the changeLanguage function. It seems to involve three things: detect the language using a detector if language not provided, normalize the detected language, and load the language resources then set the related state. Maybe we can separate these steps to make the process clearer.

I created a new branch for this idea, if it looks good, I'll create a new PR for it. https://github.com/waivital/i18next/commits/optimize-changelanguge-function/

Not sure if I like the idea - changeLanguage does no detection with that change -> leads to a breaking version for no real benefit. Also adding detectLanguage and normalizeLng to public API seems to be unnecessary - at least for me it just adds more clutter.

@waivital

Copy link
Copy Markdown
Contributor Author

I was thinking if we could optimize the changeLanguage function. It seems to involve three things: detect the language using a detector if language not provided, normalize the detected language, and load the language resources then set the related state. Maybe we can separate these steps to make the process clearer.
I created a new branch for this idea, if it looks good, I'll create a new PR for it. https://github.com/waivital/i18next/commits/optimize-changelanguge-function/

Not sure if I like the idea - changeLanguage does no detection with that change -> leads to a breaking version for no real benefit. Also adding detectLanguage and normalizeLng to public API seems to be unnecessary - at least for me it just adds more clutter.

It's ok if detectLanguage and normalizeLng are public API or private API for me, it just a quick demo for the idea. I think the benefit of this change is that changeLanguage now does just one thing—find the matched language and load the related resources. If the language isn't found, it informs the user that there’s an issue with the configuration.

@adrai

adrai commented Apr 12, 2025

Copy link
Copy Markdown
Member

I also don't like that change... For example, there are scenarios out there, where there is a lng passed via options but also a language detector...
And also that new thrown error there might be an issue "in the wild"...
So without these things, it's just splitting the content of the changeLanguage function into multiple functions... (no real benefit in userland)
So I would say we merge this PR only to fix the order of changeLanguage calls...

@waivital

Copy link
Copy Markdown
Contributor Author

Sure, we can discuss more on that later. 😄

@adrai adrai merged commit 200da27 into i18next:master Apr 15, 2025
@adrai

adrai commented Apr 15, 2025

Copy link
Copy Markdown
Member

included in v25

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiple changeLanguage call may result in wrong order

4 participants