feat: save and restore the user language on the server #1181
No reviewers
Labels
No Label
area/internal-code
changes requested
confirmed
dependencies
duplicate
good first issue
help wanted
hosting
invalid
kind/bug
kind/feature
question
wontfix
No Milestone
No project
3 Participants
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: vikunja/frontend#1181
Loading…
Reference in New Issue
No description provided.
Delete Branch "feature/persist-user-language"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR persists the current user language on the server, either when the user has no language set yet or when explicitely saving it in the settings. It restores the saved language when the user logs in.
Will allow for things like localized emails in the future.
Depends on
a98119f2d6
@ -1,6 +1,8 @@
import {HTTPFactory} from '@/http-common'
import {getCurrentLanguage, saveLanguage, setLanguage} from '../../i18n'
Use
@
@ -224,0 +227,4 @@
if (info.settings.language !== '') {
saveLanguage(info.settings.language)
} else {
await ctx.dispatch('saveCurrentLanguage')
If
info.settings.language !== ''
we save the current language from vue-i8n.Why? Shouldn't that be a user action?
Basically:
=> no language selected
=> automatic language by user language
If I understood this correct this might be a side effect from some unrelated settings change.
When the user configured their browser so it automatically changes the website language to the one preferred by the user, they might never visit the language settings since the language is already correct. I still want to save the current browser language in these cases.
I don't really see a problem here because this happens right after the settings were retrieved from the server.
@ -209,3 +211,1 @@
await this.userSettingsService.update(this.settings)
this.$store.commit('auth/setUserSettings', {
...this.settings,
await this.$store.dispatch('auth/saveUserSettings', {
Remove
this.userSettingsService
+ import since it's not used now anymore.Done.
Hi konrad!
Thank you for creating a PR!
I've deployed the changes of this PR on a preview environment under this URL: https://1181-featurepersist-user-language--vikunja-frontend-preview.netlify.app
You can use this url to view the changes live and test them out.
You will need to manually connect this to an api running somehwere. The easiest to use is https://try.vikunja.io/.
Have a nice day!
@ -182,2 +183,4 @@
return this.$store.getters['lists/getListById'](this.settings.defaultListId)
},
loading() {
return this.$store.state[LOADING] && this.$store.state[LOADING_MODULE] === 'general-settings'
LOADING
andLOADING_MODULE
are both not mutations but states.=> should not use import from mutation-types.
Btw: I never got how this worked when multiple modules load at the same time.
Don't they overwrite the
loadingModule
state (loading
state wouldn't matter so much I guess)?I think there's a few more places where this is wrong as well.
They do. That's one of the issues with it but I primarily wanted a way to check whether a certain module is loading right now without exposing the
loading
property of the service. I think the proper way to do this would be to add all kinds of loading properties to the modules?How would you reccommend solving this? Adding new consts to a new file
state-type
similar to the one holding the mutation types?I have something in mind for this. But I guess it makes sense to talk about this when we get there. Will probably when we start using pinia.
Then you could not use the same
state-type
at the same time because there could be conflicts. Probably you shouldn't either way because merging them would benefit speed, but you never know when this case might happen.For now I would still remove the impor tof the mutation. For pinia this is not necessary because of the better typing.
You can also add better types to vuex but I guess this is now not worth the effort anymore. So going forward we will need to this kind of stuff either way =)
@ -206,9 +210,11 @@ export default {
setQuickAddMagicMode(this.quickAddMagicMode)
this.settings.defaultListId = this.defaultList ? this.defaultList.id : 0
The local settings should be changed only after the user settings are saved, so that in case something goes wrong we don't have a wrong local representation of the state.
But wouldn't that require a new data variable? That feels kind of clunky because then I need to synchronize it again when loading data initially from the server etc. Maybe the error message is enough to tell the user "hey something went wrond while saving and what you see in the interface isn't nessecarily what is saved"?
This was kind of solved by the default list branch.
Reworking how the settings are saved would be a different topic =)
9d66a9d4c2
to94098a66a6
I updated the stuff I was mentioning and force-pushed these changes.
But I found one more issue.
Hope the force-push was fine
@ -164,7 +162,6 @@ export default {
language: getCurrentLanguage(),
This seems wrong:
Now that we have a language field in the settings the current language should be loaded from the settings and only loaded from the browsers if a user language was not yet defined.
94098a66a6
to60baf71acf
I think it's fine, yes. Thanks for fixing the issues :)
So this PR is all done?
feat: save and restore the user langauge on the serverto feat: save and restore the user language on the serverGeneral:
Or we should create a new store module for this.
@ -224,0 +224,4 @@
commit('info', info)
commit('lastUserRefresh')
if (typeof info.settings.language !== 'undefined') {
(I rewrote this myself)
I'm not super happy with this. Especially with the location of this snippet.
As far as I got this this should just be necessary for the first time a user visits the site since after that the setting should not be undefined anymore.
Yes, but also when the user first visits the site after the new feature was introduced. We might remove this in the future.
So should we keep it then as is?
I think yes, for now at least.
@ -171,3 +168,3 @@
userSettingsService: new UserSettingsService(),
settings: {...this.$store.state.auth.settings},
id: createRandomID(),
availableLanguages: Object.entries(availableLanguages)
Rename to
availableLanguageOptions
to differentiate from the@/i18n
export with the same name.Done.
@ -221,3 +213,2 @@
await this.userSettingsService.update(settings)
this.$store.commit('auth/setUserSettings', settings)
await this.$store.dispatch('auth/saveUserSettings', {...this.settings})
this.$message.success({message: this.$t('user.settings.general.savedSuccess')})
It feels to me like this message should be in the store with the action. But since we use the same action triggered automatically in the
refreshUserInfo
this would be confusing since there would be a notification without any interaction.Definitely. AFAIK triggering the message from the store isn't as easy anyway?
Triggering message is easy. Problem is that this action is also used by the app, in this case we don't want the message to be hidden.
Maybe add a param to the action to hide the message?
I think that could work.
How do I trigger a message without access to
this.$message
? Just by importing the message handler directly?Yes, like here: https://kolaente.dev/vikunja/frontend/src/branch/main/src/store/modules/kanban.js#L356
Changed.
@dpschen What else is missing here?