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
~
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.
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>