adbrosaci / vue-lang-router

Vue language routing with (optional) localized URLs.
MIT License
66 stars 8 forks source link

localizePath defaultLanguage problem #14

Open SergisGit opened 3 years ago

SergisGit commented 3 years ago

let the default language == "ru" and index path == "/". if I switch language to en, reload browser and then switch to ru => index path == "/ru/"

I think it would be nice to modify the localizePath function:

function localizePath(fullPath, lang) {
  ...
  var newLang = lang == defaultLanguage ? "" : "/" + lang;
  translatedPath = newLang + (translatedPath.charAt(0) != "/" ? "/" : "") + translatedPath;
  return translatedPath + query;
}
radek-altof commented 3 years ago

Hi @SergisGit, thank you for the suggestion. However, this will fail generating proper URL for switching the language back to default one. In such a case, the language NEEDS to be present in URL. Once user would switch to some other than default language, he wouldn't be able to switch back.

SergisGit commented 3 years ago

Hi @SergisGit, thank you for the suggestion. However, this will fail generating proper URL for switching the language back to default one. In such a case, the language NEEDS to be present in URL. Once user would switch to some other than default language, he wouldn't be able to switch back.

I have no problem switching languages, but I wrote my own lang-switcher component for this. The built-in switcher seemed very strange to me.


<template>
  <div
    class="lang-switcher"
    :class="{ 'lang-switcher--active': isActive }"
    @mouseenter="open()"
    @mouseleave="close()"
  >
    <div class="lang-switcher__current">{{ locale }}</div>
    <div class="lang-switcher__list">
      <template v-for="(lang, langIndex) in translations" :key="langIndex">
        <button
          v-if="lang != locale"
          type="button"
          class="lang-switcher__btn"
          @click="setLanguage(lang)"
        >
          {{ lang }}
        </button>
      </template>
    </div>
  </div>
</template>

<script>
export default {
  name: "lang-switcher",
  data() {
    return {
      isActive: false
    };
  },
  computed: {
    locale() {
      return this.$i18n.locale;
    },
    translations() {
      return Object.keys(this._langRouter.translations);
    }
  },
  methods: {
    open() {
      this.isActive = true;
    },
    close() {
      this.isActive = false;
    },
    setLanguage(lang) {
      this.close();
      this._langRouter.loadLanguage(lang).then(() => {
        const newRoute = this.$localizePath(this.$route.fullPath, lang);
        const historyState = Object.assign({}, window.history.state, {
          current: newRoute
        });
        window.history.replaceState(historyState, "", newRoute);
        this._langRouter.forcedNewRoute.value = newRoute;
        this.$axios.defaults.headers.common["X-localization"] = lang;
      });
    }
  }
};
</script>

<style lang="less">
.lang-switcher {
  position: relative;
  &--active {
    .lang-switcher__list {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
    }
    .lang-switcher__current::after {
      transform: scale3d(1, -1, 1);
    }
  }
  &__btn,
  &__current {
    text-transform: uppercase;
    color: @white;
    font-weight: 400;
    font-size: 16px;
    line-height: 1;
    letter-spacing: 0.04em;
    white-space: nowrap;
  }
  &__current {
    position: relative;
    padding: 10px 20px 10px 10px;
    cursor: default;
    &::after {
      content: "";
      position: absolute;
      right: 0;
      margin-top: -4px;
      top: 50%;
      background-image: @arrow_down;
      background-repeat: no-repeat;
      width: 12px;
      height: 7px;
      transition: transform 0.2s;
    }
  }
  &__btn {
    padding: 10px;
    border: none;
    background: none;
    text-decoration: none;
    transition: color 0.2s;
    &:hover {
      color: @gold;
    }
  }
  &__list {
    box-sizing: border-box;
    position: absolute;
    top: 100%;
    left: 0;
    display: flex;
    flex-direction: column;
    transition: all 0.2s linear;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }
}
</style>

image