Skip to content

Localization (Internationalization)

VueToCounter provides localization functionality for handling the localization of numbers and time intervals.

The VueToCounterNumber and VueToCounterDatetimeDuration components support localization, and you can set the localization configuration through the locale property.

In most cases, you only need to set the locale property to a language code (such as en, en-US, zh, zh-CN). VueToCounter will internally call the Intl API to handle localization.

Time Interval Localization

CodeSandbox Logo


~

Click to view code
vue
<script setup>
import { ref } from "vue";
import LocaleSelect from "./LocaleSelect.vue";

const from = ref("2024-12-01T00:00:00");
const to = ref("2024-12-31T00:00:00");

function switchDatetime() {
  [from.value, to.value] = [to.value, from.value];
}

const locale = ref(navigator.language);
</script>

<template>
  <div class="text-center">
    <vue-to-counter-datetime-duration :value="[from, to]" :locale="locale" />
  </div>
  <hr />
  <div class="flex gap-4">
    <div>
      <input
        class="border border-solid p-1"
        v-model="from"
        type="datetime-local"
      />
      ~
      <input
        class="border border-solid p-1"
        v-model="to"
        type="datetime-local"
      />
    </div>
    <button class="border border-solid p-1" @click="switchDatetime">
      切换
    </button>
    <span class="flex-auto" />
    <locale-select
      class="border border-solid p-1 appearance-auto"
      v-model="locale"
    />
  </div>
</template>

<style scoped></style>
vue
<script setup>
import StackblitzLogo from "../assets/stackblitz-logo.svg";
import { ref, toRefs } from "vue";
import { getCodeStackblitzParams } from "./generate-stackblitz-params";
import sdk from "@stackblitz/sdk";
import packageInfo from "../../vue-to-counter/package.json";

const props = defineProps({
  title: {
    type: String,
    required: true,
  },
});
const { title } = toRefs(props);

const containerRef = ref();

function handleStackblitz() {
  if (!containerRef.value) return;

  const tabs = containerRef.value.querySelectorAll(".tabs > label");
  const blocks = containerRef.value.querySelectorAll(".blocks > div code");
  if (tabs.length !== blocks.length) {
    window.alert("The number of tabs and code blocks should be the same.");
    return;
  }

  const files = Array.from(tabs).map((tab, index) => ({
    filename: tab.textContent.trim(),
    content: blocks[index].textContent,
  }));

  const params = getCodeStackblitzParams(files, {
    title: `${title.value} - vue-to-counter@${packageInfo.version}`,
  });
  sdk.openProject(params, {
    openFile: "src/demo.vue",
  });
}
</script>

<template>
  <div ref="containerRef" class="demo-container">
    <div class="flex relative">
      <span class="flex-auto" />
      <span
        title="Open In Stackblitz"
        class="inline-block p-1 cursor-pointer hover:outline hover:outline-[#1389FD] outline-1"
        @click="handleStackblitz"
      >
        <img
          class="h-4 w-4 pointer-events-none"
          :src="StackblitzLogo"
          alt="CodeSandbox Logo"
        />
      </span>
    </div>
    <hr />
    <slot />
  </div>
</template>

<style lang="scss">
.demo-container {
  @apply flex flex-col justify-center border p-4 rounded-lg mt-4 text-sm;

  .vue-to-counter {
    @apply font-mono text-4xl;
  }

  .custom-block {
    @apply m-0;
  }
}
</style>

Number Localization

Specifically, the VueToCounterNumber component also needs to set the locale-number property.

  • You can set it to true, which will enable number localization with the default configuration.
  • You can also set it to options supported by Intl.NumberFormat.
CodeSandbox Logo

0110110440,,055011044


Click to view code
vue
<script setup>
import { ref } from "vue";
import LocaleSelect from "./LocaleSelect.vue";

const number = ref(114514);

function switchNumber() {
  number.value = Math.floor(Math.random() * 1000000);
}

const locale = ref(navigator.language);
</script>

<template>
  <div class="text-center">
    <vue-to-counter-number :value="number" :locale="locale" locale-number />
  </div>
  <hr />
  <div class="flex gap-4">
    <input class="border border-solid p-1" v-model="number" type="number" />
    <button class="border border-solid p-1" @click="switchNumber">切换</button>
    <span class="flex-auto" />
    <locale-select
      class="border border-solid p-1 appearance-auto"
      v-model="locale"
    />
  </div>
</template>

<style scoped></style>
vue
<script setup>
import StackblitzLogo from "../assets/stackblitz-logo.svg";
import { ref, toRefs } from "vue";
import { getCodeStackblitzParams } from "./generate-stackblitz-params";
import sdk from "@stackblitz/sdk";
import packageInfo from "../../vue-to-counter/package.json";

const props = defineProps({
  title: {
    type: String,
    required: true,
  },
});
const { title } = toRefs(props);

const containerRef = ref();

function handleStackblitz() {
  if (!containerRef.value) return;

  const tabs = containerRef.value.querySelectorAll(".tabs > label");
  const blocks = containerRef.value.querySelectorAll(".blocks > div code");
  if (tabs.length !== blocks.length) {
    window.alert("The number of tabs and code blocks should be the same.");
    return;
  }

  const files = Array.from(tabs).map((tab, index) => ({
    filename: tab.textContent.trim(),
    content: blocks[index].textContent,
  }));

  const params = getCodeStackblitzParams(files, {
    title: `${title.value} - vue-to-counter@${packageInfo.version}`,
  });
  sdk.openProject(params, {
    openFile: "src/demo.vue",
  });
}
</script>

<template>
  <div ref="containerRef" class="demo-container">
    <div class="flex relative">
      <span class="flex-auto" />
      <span
        title="Open In Stackblitz"
        class="inline-block p-1 cursor-pointer hover:outline hover:outline-[#1389FD] outline-1"
        @click="handleStackblitz"
      >
        <img
          class="h-4 w-4 pointer-events-none"
          :src="StackblitzLogo"
          alt="CodeSandbox Logo"
        />
      </span>
    </div>
    <hr />
    <slot />
  </div>
</template>

<style lang="scss">
.demo-container {
  @apply flex flex-col justify-center border p-4 rounded-lg mt-4 text-sm;

  .vue-to-counter {
    @apply font-mono text-4xl;
  }

  .custom-block {
    @apply m-0;
  }
}
</style>