feat(i18n): 支持多语言切换的国家选择器组件

This commit is contained in:
scout 2025-01-13 14:00:35 +08:00
parent d642228daa
commit 76194063a6

View File

@ -1,8 +1,10 @@
<script setup> <script setup>
import {ref} from 'vue'; import {ref, computed, watch} from 'vue';
import pinyin from 'pinyin'; import pinyin from 'pinyin';
import countryCode from './data/index.js'; import countryCode from './data/index.js';
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
const value = ref(''); const value = ref('');
const alphabet = [ const alphabet = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
@ -12,27 +14,41 @@ const alphabet = [
function groupByPinyinInitial(data) { function groupByPinyinInitial(data) {
const grouped = {}; const grouped = {};
data.forEach(country => { data.forEach(country => {
const initial = pinyin(country.cn, {style: pinyin.STYLE_FIRST_LETTER})[0][0].toUpperCase(); //
const countryName = locale.value === 'zh-CN' ? country.cn :
locale.value === 'zh-TW' ? country.tw :
locale.value === 'ja-JP' ? country.ja :
country.en;
const initial = locale.value === 'ja-JP' ? '' :
locale.value === 'zh-CN' || locale.value === 'zh-TW' ?
pinyin(countryName, {style: pinyin.STYLE_FIRST_LETTER})[0][0].toUpperCase() :
countryName.charAt(0).toUpperCase();
if (!grouped[initial]) { if (!grouped[initial]) {
grouped[initial] = []; grouped[initial] = [];
} }
grouped[initial].push(country); grouped[initial].push({
...country,
displayName: countryName
});
}); });
return grouped; return grouped;
} }
const groupedCountries = ref([]) const groupedCountries = ref([])
const initData=()=>{ const initData = () => {
groupedCountries.value = groupByPinyinInitial(countryCode); groupedCountries.value = groupByPinyinInitial(countryCode);
} }
const searchCountry = computed(() => { const searchCountry = computed(() => {
if (!value.value) { if (!value.value) {
return groupedCountries.value; return groupedCountries.value;
} }
return Object.keys(groupedCountries.value).reduce((filtered, initial) => { return Object.keys(groupedCountries.value).reduce((filtered, initial) => {
const countries = groupedCountries.value[initial].filter(country => const countries = groupedCountries.value[initial].filter(country =>
country.cn.includes(value.value) country.displayName.toLowerCase().includes(value.value.toLowerCase())
); );
if (countries.length > 0) { if (countries.length > 0) {
filtered[initial] = countries; filtered[initial] = countries;
@ -40,27 +56,47 @@ const searchCountry = computed(() => {
return filtered; return filtered;
}, {}); }, {});
}); });
const showIndexBar = computed(() => locale.value !== 'ja-JP')
initData() initData()
//
watch(locale, () => {
initData()
})
</script> </script>
<template> <template>
<div> <div>
<van-sticky> <van-sticky>
<van-search v-model="value" placeholder="请输入国家和地区"/> <van-search v-model="value" :placeholder="t('countryRegion.searchPlaceholder')"/>
</van-sticky> </van-sticky>
<van-index-bar sticky :sticky-offset-top="55" :index-list="alphabet"> <van-index-bar
v-if="showIndexBar"
sticky
:sticky-offset-top="55"
:index-list="alphabet"
>
<template v-for="(countries, index) in searchCountry" :key="index"> <template v-for="(countries, index) in searchCountry" :key="index">
<van-index-anchor <van-index-anchor
:index="index" :index="index"
></van-index-anchor> ></van-index-anchor>
<van-cell v-for="country in countries" :key="country.code" :title="country.cn"> <van-cell v-for="country in countries" :key="country.code" :title="country.displayName">
<div class="pr-[25px]"> +{{ country.zone }}</div> <div class="pr-[25px]"> +{{ country.zone }}</div>
</van-cell> </van-cell>
</template> </template>
</van-index-bar> </van-index-bar>
<van-back-top right="15vw" bottom="10vh"/>
<div v-else>
<van-cell v-for="country in Object.values(searchCountry).flat()"
:key="country.code"
:title="country.displayName">
<div class="pr-[25px]"> +{{ country.zone }}</div>
</van-cell>
</div>
<van-back-top v-if="showIndexBar" right="15vw" bottom="10vh"/>
</div> </div>
</template> </template>