kazupon / vue-i18n

:globe_with_meridians: Internationalization plugin for Vue.js
https://kazupon.github.io/vue-i18n/
MIT License
7.28k stars 861 forks source link

v-t attributes in a <router-link /> element does not translate when changing $i18n.locale #399

Open Kansuler opened 6 years ago

Kansuler commented 6 years ago

vue & vue-i18n version

Vue 2.5.17-beta.0 Vue-i18n 7.6.0

Steps to reproduce

<template v-for="category in CATEGORIES">
    <router-link :to="{}" class="category" :key="category.category">
        <div class="column title-description">
            <div class="title" v-t="category.category">
            <div class="description" v-t="category.category + '_description'" />
        </div>
    </router-link>
</template>

What is Expected?

When I change $i18n.locale all v-t attributes should be translated.

What is actually happening?

The translations doesn't render. If I change at least one of the v-t attributes to interpolation with $t it actually works, even on the v-t attributes.

Code sample that works perfectly:

<template v-for="category in CATEGORIES">
    <router-link :to="{}" class="category" :key="category.category">
        <div class="column title-description">
            <div class="title">{{ $t(category.category) }}</div>
            <div class="description" v-t="category.category + '_description'" />
        </div>
    </router-link>
</template>
Kansuler commented 6 years ago

Upgraded to Vue-i18n 8.0.0 and the situation is the same.

RonyVidaur commented 6 years ago

can we take a look at the CATEGORIES object?

Kansuler commented 6 years ago

Of course. I've experienced this problem twice.

{
  "CATEGORIES": [
    {
      "category": "forum_category_announcement",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-comment-alt-exclamation"
    },
    {
      "category": "forum_category_admin_board",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-crown"
    },
    {
      "category": "forum_category_general",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-feather-alt"
    },
    {
      "category": "forum_category_board_games",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-chess-board"
    },
    {
      "category": "forum_category_fantasy_sci_fi",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-bolt"
    },
    {
      "category": "forum_category_real_life",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-glasses-alt"
    },
    {
      "category": "forum_category_drakjakt",
      "threads": 0,
      "can_create_thread": true,
      "icon": "fa-bug"
    }
  ]
}
Kansuler commented 6 years ago

Actually, I did some experiments and the problem doesn't occur in an v-for loop, but rather if the v-t tags are used in a element from the vue-router plugin.

Here is a link of a working code example that prevents translations to occur in a <router-link/> element. Not sure if this problem is caused by vue-i18n or vue-router

https://codesandbox.io/s/5m33l939zn

RonyVidaur commented 6 years ago

Hi, I was testing your example and it seems that changing it to <p class="title" >{{ $t(${category.category}) }}</p> instead of using a div with the v-t Directive solves the problem. Not sure why though, maybe it has something to do with what a child of a router-link can or cannot be.

Kansuler commented 6 years ago

The difference is that if you have one $t method with interpolation inside it reacts to the $i18n.locale change, but if everything is v-t attribute, it does not react. Doesn't mater what type of element it is.

Rouche commented 6 years ago

I also have this problem. But it happens inside a <router-view /> of a Vuetify application. None of the v-t are working. Outside seems ok.

<template>
    <div id="app">
        <v-app>
            <app-navigation></app-navigation>
            <v-container grid-list-xs grid-list-sm gird-list-md>
                <router-view></router-view>
            </v-container>
            <div>
                <!-- this one is working -->
                <span v-t="'title'"></span>
            </div>
        </v-app>
    </div>
</template>

routes


const verifyLocale: NavigationGuard = (to, from, next) => {

    loadLanguageAsync(to.params.locale).then( (): void => {
        next();

    }).catch( (): void => {
        next(`/${i18n.locale}`);
    });
};

const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,

    routes: [
        {
            path: '/',
            redirect: `/${i18n.locale}`,
        },
        {
            path: '/:locale',
            component: Locale,
            beforeEnter: verifyLocale,

            children: [
                {
                    path: '',
                    name: 'dashboard',
                    component: Dashboard,
                    beforeEnter: ifAuthenticated,
                },
                {
                    path: 'login',
                    name: 'login',
                    component: Login,
                    beforeEnter: ifNotAuthenticated,
                },
                {
                    path: '*',
                    redirect: `/${i18n.locale}`,
                },
            ],
        },
    ],
});
router.beforeEach(verifyLocale);

export default router;
DorianGrey commented 6 years ago

Seeing a similar issue on my playground application. It seems that the language update isnt' immediately adopted for elements using the v-t directive. However, it gets updated the new time the component is re-rendered. In case of the playground app mentioned above: changing the language (here: via the top-right button) does not update the texts in the menu and header, until I toggle the menu again, or perform any route change (some texts are actually adopted - those are using $t, mostly in places where v-t could not be used).