Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Hot reloading not working (forces reload of app) #104

Closed
caugner opened this issue May 4, 2020 · 2 comments
Closed

Hot reloading not working (forces reload of app) #104

caugner opened this issue May 4, 2020 · 2 comments
Labels
Status: PR Welcome Welcome to Pull Request Type: Improvement Includes backwards-compatible fixes

Comments

@caugner
Copy link
Contributor

caugner commented May 4, 2020

I have followed the Hot reloading section from the vue-i18n guide to setup my src/i18n.js (locales in src/locales/*.json) as follows.

However, any change to my locale file forces a reload of the app. What am I doing wrong?

import Vue from "vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

function loadLocaleMessages() {
  const locales = require.context(
    "./locales",
    true,
    /[A-Za-z0-9-_,\s]+\.json$/i
  );
  const messages = {};
  locales.keys().forEach((key) => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i);
    if (matched && matched.length > 1) {
      const locale = matched[1];
      messages[locale] = locales(key);
    }
  });
  return messages;
}

const i18n = new VueI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || "en",
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
  messages: loadLocaleMessages(),
});

export default i18n;

if (module.hot) {
  module.hot.accept(["./locales/de"], () => {
    i18n.setLocaleMessage("de", require("./locales/de").default);
  });
}

Note: The exported object is used in the src/main.js as follows:

// ...
import i18n from "./i18n";
// ...

new Vue({
  // ...
  i18n,
  render: (h) => h(App),
}).$mount("#app");
@caugner
Copy link
Contributor Author

caugner commented May 5, 2020

@kazupon I figured it out! 🎉

The main reason why my approach didn't work was that require.context included the .json extension, whereas my module.hot.accept parameter did not.

However, the webpack wiki describes how to Hot module replace with require.context.

So this worked:

// src/i18n.js

import Vue from "vue";
import VueI18n from "vue-i18n";

Vue.use(VueI18n);

function loadMessages() {
  const context = require.context(
    "./locales",
    true,
    /[A-Za-z0-9-_,\s]+\.json$/i
  );
  const messages = {};
  context.keys().forEach((key) => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i);
    if (matched && matched.length > 1) {
      const locale = matched[1];
      messages[locale] = context(key);
    }
  });

  return { context, messages };
}

const { context, messages } = loadMessages();

const i18n = new VueI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || "en",
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
  messages,
});

if (module.hot) {
  module.hot.accept(context.id, () => {
    const { messages } = loadMessages();
    Object.keys(messages).forEach((locale) =>
      i18n.setLocaleMessage(locale, messages[locale])
    );
  });
}

export default i18n;

Update: I have now refactored the loadMessage() function as follows:

function loadMessages() {
  const context = require.context("./locales", true, /[a-z0-9-_]+\.json$/i);

  const messages = context
    .keys()
    .map((key) => ({ key, locale: key.match(/[a-z0-9-_]+/i)[0] }))
    .reduce(
      (messages, { key, locale }) => ({
        ...messages,
        [locale]: context(key),
      }),
      {}
    );

  return { context, messages };
}

Update 2: Now I have also improved the module.hot section to only update those locales that have been changed:

if (module.hot) {
  module.hot.accept(context.id, () => {
    const { messages: newMessages } = loadMessages();

    Object.keys(newMessages)
      .filter((locale) => messages[locale] !== newMessages[locale])
      .forEach((locale) => {
        messages[locale] = newMessages[locale];
        i18n.setLocaleMessage(locale, messages[locale]);
      });
  });
}

@kazupon kazupon added Status: PR Welcome Welcome to Pull Request Type: Improvement Includes backwards-compatible fixes labels May 5, 2020
@kazupon
Copy link
Member

kazupon commented May 5, 2020

close due to merged at vue-i18n docs

@kazupon kazupon closed this as completed May 5, 2020
etherdog-eth pushed a commit to etherdog-eth/vue-i18n that referenced this issue May 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Status: PR Welcome Welcome to Pull Request Type: Improvement Includes backwards-compatible fixes
Projects
None yet
Development

No branches or pull requests

2 participants