i18n icon indicating copy to clipboard operation
i18n copied to clipboard

local message are not available in asyncData using `i18n.t()` using vue-i18n-loader

Open mrleblanc101 opened this issue 4 years ago • 10 comments
trafficstars

Version

@nuxtjs/i18n: nuxt:

Nuxt configuration

Please change to [x] if relevant for this issue:

  • [x] Applies to a site deployed to a static server (site generated with nuxt generate)
  • [x] Applies to a site deployed to a server with a Node backend

@nuxtjs/i18n configuration

Reproduction Link

Coming soon

Steps to reproduce

  • Create a component
  • Add local message using vue-i18n-loader or the option API
  • In your asyncData, using i18n.t or app.i18n.t, the message is not found
  • If you use global message, it work

What is Expected?

  • Local message should also be available as they dont need the instance to be mounted to work since they have no dependancy

What is actually happening?

  • Only global message are available

mrleblanc101 avatar Sep 27 '21 19:09 mrleblanc101

Here is a simplified exemple while I prepare a repro. I need to send my translation to layout component using Vuex.

Component:

<script>
export default {
    layout: 'onboarding',
    asyncData({ store, app }) {
        store.commit('onboarding/setOnboardingDetails', {
            title: app.i18n.t('page_title'),
        });
    },
    head() {
        return {
            title: this.$t('page_title'),
        };
    },
};
</script>

<i18n lang="json">
{
    "fr": {
        "page_title": "Introduction",
    },
    "en": {
        "page_title": "Onboarding",
    }
}
</i18n>

Layout:

<template>
    <div class="layout is-onboarding-layout">
        <h1 v-if="details.title" class="onboarding-title">{{ details.title }}</h1>
        <nuxt id="content" class="onboarding-content cell small-12 large-auto" />
    </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
    computed: {
        ...mapState('onboarding', ['details']),
    },
};
</script>

mrleblanc101 avatar Sep 27 '21 19:09 mrleblanc101

Oh wow. That's one obvious bug that took forever to find :)

@kazupon not sure how familiar you are with Nuxt already but maybe you have some ideas here.

  • vue-i18n-loader stores component locales inside the component - https://github.com/intlify/vue-i18n-loader/blob/d1814dae9986088fd4d4d159d88c36f14bd5dbd0/src/index.ts#L45-L46
  • it only merges the locales and creates local vue-i18n instance once the component is created so after asyncData invocation
  • We could find the component and the related data within asyncData one way or another (maybe not in a pretty way) but then there is a challenge of creating a local (extended) vue-i18n instance just for asyncData and then figuring out when to forget it again.
  • This all seems like quite a challenge unless I'm missing something (could be since I thought about it for only few minutes).

rchl avatar Sep 27 '21 20:09 rchl

Alright we are not crazy 😝 We kinda found out a year ago on another project but we were not too familiar with the plugin and we were using local message inside the option API. We ended up moving all these message as global message and didn't think much about it.

But now we moved to vue-i18n-loader and I was refactoring some code on another project and I was hopping the move the text inside the relevant component so that it's easier to find and I figured out it can't be right that local message aren't available inside asyncData.

mrleblanc101 avatar Sep 27 '21 20:09 mrleblanc101

@rchl Thanks for looking into the issue! I will try to reproduce the issue in my environment first. After that, I'll do some more research on my end. This issue is a good opportunity to understand inside of nuxt. :)

kazupon avatar Sep 28 '21 04:09 kazupon

+1 here. Feels like this should already be baked in especially with this being a Nuxt.js specific implementation of vue-i18n.

Does anyone have any workarounds for the moment? Main use case here is error messages (inside of context.error).

adamchipperfield avatar Oct 05 '21 12:10 adamchipperfield

To be fair, I've just realized that it's a bit of an anti-pattern to translate in asyncData already as then the translations would not be reactive - wouldn't update when user changes the locale on the client side.

Better approach would be to pass the translation keys around and resolve those within the contexts that are reactive.

rchl avatar Oct 06 '21 09:10 rchl

Changing the locale re-run asyncData, no ? 🤔 Otherwise how does it fetch my async content in the other language ? It's not "reactive" but the text would still be updated in the correct language

mrleblanc101 avatar Oct 06 '21 12:10 mrleblanc101

Also since it already work if you use global message, i don't see why that would be an anti-pattern. It's just logical that you would be able to access local message even if the instance is not created yet since the message have no dependancy on the instance. Otherwise if it's so bad you should expose i18n in asyncData at all.

mrleblanc101 avatar Oct 06 '21 13:10 mrleblanc101

Yes good point.

rchl avatar Oct 06 '21 13:10 rchl

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 08 '22 22:01 stale[bot]