Added Permission check before setting Preferred Language#5943
Added Permission check before setting Preferred Language#5943parasharrajat wants to merge 5 commits into
Conversation
| .then(() => { | ||
| if (preferredLocale) { | ||
| // Betas are only present when user is Logined | ||
| if (Permissions.canUseInternationalization([]) && preferredLocale) { |
There was a problem hiding this comment.
Moved to review early. I wanted to have feedback on this piece of the code.
In reality, we don't have beta access when the user is logged out but I used this check instead of isDevelopment as it seems more meaningful.
There was a problem hiding this comment.
Ah hmm not sure how isDevelopment relates here. I think if we are logging out it maybe makes sense to just clear the preferredLocale? Why are we trying to persist it? Maybe @iwiznia knows.
There was a problem hiding this comment.
If I have selected spanish locale and log out (or get logged out), then I want to see the login screen in spanish, not english. In any case it's fine to only check for the betas in the UI, if a user not on the beta sets the locale manually via developer console or something, then it's ok if the localization feature works for them,
There was a problem hiding this comment.
Permissions.canUseInternationalization([]) internally also checks for isDevelopment.
There was a problem hiding this comment.
We can check for isDevelopment if we want, but I don't think it's necessary
There was a problem hiding this comment.
It's needed. Otherwise, the user will be locked in one language. If we are not showing a LocalePicker on the login page in staging then the language should not change to Spanish at all after logout, if the logged-in user was using spanish.
We determine whether the locale picker is shown or not, is via beta permissions check so I have used the same here.
There was a problem hiding this comment.
I think this check is confusing. Calling canUseInternationalization passing an empty betas list is just a confusing way to check isDevelopment() in this case? I think we should completely remove this check from here
There was a problem hiding this comment.
Hmm. It can be. I will test this way.
| Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); | ||
| } | ||
| }); | ||
| if (Permissions.canUseInternationalization(this.props.betas)) { |
There was a problem hiding this comment.
I think this is a race condition for a fresh login. How can we guarantee that this.props.betas is set? We are calling User.getBetas() after so surely this won't work.
There was a problem hiding this comment.
Same comment here, we don't need to check for the betas here, let's only check when presenting the UI to change the language.
There was a problem hiding this comment.
But, we need to check that. For example,
- a user with beta access login, changed the language to Spanish.
- He logs out.
- Page is still in Spanish.
- Now he logs in with another normal user without beta.
- Langauge is set to Spanish but there is no option to change and this user speaks English.
This is the issue we are trying to solve with PR.
Well, yeah there is a race condition here. I look into it.
There was a problem hiding this comment.
That's an edge case we don't really care about in any scenario other than us testing things, so I think it's fine.
There was a problem hiding this comment.
wait, are you saying the issue we are fixing is an edge case? 😕
There was a problem hiding this comment.
Just checked the issue (should've done it before) and yes, I think so. But not sure if that will be a problem for QA... I guess not because they can still log in to an account with the beta, change the language to english then log out and log in with the gmail account which is not in the beta.
| .then(() => { | ||
| if (preferredLocale) { | ||
| // Betas are only present when user is Logined | ||
| if (Permissions.canUseInternationalization([]) && preferredLocale) { |
There was a problem hiding this comment.
Ah hmm not sure how isDevelopment relates here. I think if we are logging out it maybe makes sense to just clear the preferredLocale? Why are we trying to persist it? Maybe @iwiznia knows.
| Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); | ||
| } | ||
| }); | ||
| if (Permissions.canUseInternationalization(this.props.betas)) { |
There was a problem hiding this comment.
Looking to get some help in choosing the right technique for removing the race condition.
- Create a key
ONYXKEYS.IS_LOADING_BETASset to false when beta is loaded. - When this is set to true, run the above logic.
Subscribing to Onyx.beta here seems unnecessary to me as we only want to run one thing once. so I can abstract this code to a separate function and use Onyx.connect in the local scope.
What do you say? @marcaaron
|
This is ready for review. Currently, I have used the Onyx approach for unlocking the race conditions as we are following a rule that actions should not have then chains #6093. But I will argue that using a |
|
I think the If you want to see the Onyx approach, then see the second last commit |
iwiznia
left a comment
There was a problem hiding this comment.
I think I got lost on what we are trying to do on this PR... 😕
| .then(() => { | ||
| if (preferredLocale) { | ||
| // Betas are only present when user is Logined | ||
| if (Permissions.canUseInternationalization([]) && preferredLocale) { |
There was a problem hiding this comment.
I think this check is confusing. Calling canUseInternationalization passing an empty betas list is just a confusing way to check isDevelopment() in this case? I think we should completely remove this check from here
| PersonalDetails.fetchPersonalDetails(); | ||
| User.getUserDetails(); | ||
| User.getBetas(); | ||
| User.fetchBetasAndSetPreferredLocale(this.props.preferredLocale); |
There was a problem hiding this comment.
I don't get why we are setting the preferredLocale here, the user is logging in, their locale can't change in this flow.
There was a problem hiding this comment.
Could you please clarify this for me? I didn't get it.
I think, if the user does not have access to betas then we don't want the language to be changed from En as the locale is a beta feature.
There was a problem hiding this comment.
Could you please clarify this for me? I didn't get it.
I don't get why we need to set a locale here nor where the value from the locale will come. The only place where the user can set the locale is from the preferences page, no?
I think, if the user does not have access to betas then we don't want the language to be changed from En as the locale is a beta feature.
The way I see it, regardless of the beta, the locale should be what's in preferred locale or english if nothing is set in preferred locale.
There was a problem hiding this comment.
Here, the locale is picked from Onyx if the user has set a locale from the login page picker.

I am following the existing code. Just added a check for beta so that we can break the loop if the user does not have localization beta access.
The way I see it, regardless of the beta, the locale should be what's in preferred locale or english if nothing is set in the preferred locale.
Yup, it does but with one exception that it also picks the locale preference from the login page.
There was a problem hiding this comment.
If we kill the login page language selection , would that mean we can remove this?
There was a problem hiding this comment.
Then we will have to remove the extra code.
| * Fetches betas and User's preferred Locale, then set the app locale. | ||
| * @param {String} currentPreferredLocale | ||
| */ | ||
| function fetchBetasAndSetPreferredLocale(currentPreferredLocale) { |
There was a problem hiding this comment.
I'm having trouble figuring out why we are combining these. It's not obvious from looking at the code so I don't think it's the right solution to the problem.
If I'm understanding correctly, there is some race condition where we want to "set preferred locale" but only if we are on the beta and the betas have not loaded yet...?
This seems very easy to fix at the API layer by just returning the preferred locale if the user is on the beta and do the check in the server. So basically have something like API.User_GetPreferredLocale() and then this would become:
API.User_GetPreferredLocale()
.then(({preferredLocale}) => {
Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale);
});There was a problem hiding this comment.
Another POV is that we should never prevent getting or setting this NVP depending on the beta.
But in order to use it we should have the correct beta.
| ) { | ||
| setLocale(currentPreferredLocale); | ||
| } else { | ||
| Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, preferredLocale); |
There was a problem hiding this comment.
What's the difference between setLocale() and Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, value) 🤔 ?
marcaaron
left a comment
There was a problem hiding this comment.
I think maybe it would be better handle some things at the API layer than combine "get betas" and "get preferred locale" into one synchronous check. That will set up a weird practice where anything that requires the beta to load first will need be put into the "wait for the betas" method.
Heh I'm not sure this is the right interpretation of that rule. We still do not want to encourage promise chains or time dependent code. Anything that can happen in parallel should happen in parallel. What is the race condition? I've seen it mentioned a few times, but don't have a good understanding of what it is. |
|
I will follow up on each comment one by one shortly. But looking at the comments I think we need to discuss a solution before jumping on the implementation. |
|
Ok, things are moving fast #6177 is also trying to fix this. But looks like in a good way. |
|
Now, I think we don't need the changes hereafter https://github.com/Expensify/App/pull/6177/files. |
Details
Fixed Issues
$ #5286
Tests | QA Steps
Tested On
Screenshots
Web
Mobile Web
Desktop
iOS
Android