feat(player,shared): 内置球员头像名称支持三语显示
This commit is contained in:
@@ -1,7 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { BUILTIN_PLAYERS, playerAvatarUrl } from '@thebet365/shared';
|
import {
|
||||||
|
BUILTIN_PLAYERS,
|
||||||
|
playerAvatarUrl,
|
||||||
|
getPlayerDisplayName,
|
||||||
|
formatPlayerMeta,
|
||||||
|
getPlayerSearchTokens,
|
||||||
|
} from '@thebet365/shared';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: string | null;
|
modelValue: string | null;
|
||||||
@@ -11,18 +17,13 @@ const emit = defineEmits<{
|
|||||||
'update:modelValue': [value: string | null];
|
'update:modelValue': [value: string | null];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
|
|
||||||
const filtered = computed(() => {
|
const filtered = computed(() => {
|
||||||
const q = keyword.value.trim().toLowerCase();
|
const q = keyword.value.trim().toLowerCase();
|
||||||
if (!q) return BUILTIN_PLAYERS;
|
if (!q) return BUILTIN_PLAYERS;
|
||||||
return BUILTIN_PLAYERS.filter(
|
return BUILTIN_PLAYERS.filter((p) => getPlayerSearchTokens(p).some((token) => token.includes(q)));
|
||||||
(p) =>
|
|
||||||
p.name.toLowerCase().includes(q) ||
|
|
||||||
p.country.toLowerCase().includes(q) ||
|
|
||||||
p.position.toLowerCase().includes(q),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function select(key: string) {
|
function select(key: string) {
|
||||||
@@ -51,9 +52,13 @@ function select(key: string) {
|
|||||||
:class="{ active: modelValue === player.id }"
|
:class="{ active: modelValue === player.id }"
|
||||||
@click="select(player.id)"
|
@click="select(player.id)"
|
||||||
>
|
>
|
||||||
<img :src="playerAvatarUrl(player.id) ?? ''" :alt="player.name" class="picker-photo" />
|
<img
|
||||||
<span class="picker-name">{{ player.name }}</span>
|
:src="playerAvatarUrl(player.id) ?? ''"
|
||||||
<span class="picker-meta">{{ player.position }} · {{ player.country }}</span>
|
:alt="getPlayerDisplayName(player, locale)"
|
||||||
|
class="picker-photo"
|
||||||
|
/>
|
||||||
|
<span class="picker-name">{{ getPlayerDisplayName(player, locale) }}</span>
|
||||||
|
<span class="picker-meta">{{ formatPlayerMeta(player, locale) }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ export const PARLAY_MAX_LEGS = 5;
|
|||||||
export * from './betting-rules';
|
export * from './betting-rules';
|
||||||
export * from './locale';
|
export * from './locale';
|
||||||
export * from './builtinPlayers';
|
export * from './builtinPlayers';
|
||||||
|
export * from './playerLocale';
|
||||||
|
|
||||||
export interface ApiResponse<T = unknown> {
|
export interface ApiResponse<T = unknown> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
|
|||||||
350
packages/shared/src/playerLocale.ts
Normal file
350
packages/shared/src/playerLocale.ts
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
import { resolveTranslationFallback } from './locale';
|
||||||
|
import type { BuiltinPlayer } from './builtinPlayers';
|
||||||
|
|
||||||
|
export type PlayerPositionCode = 'FW' | 'MF' | 'DF' | 'GK';
|
||||||
|
|
||||||
|
type LocaleText = Partial<Record<string, string>>;
|
||||||
|
|
||||||
|
export type PlayerLocaleMeta = {
|
||||||
|
name: LocaleText;
|
||||||
|
position: PlayerPositionCode;
|
||||||
|
country: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PLAYER_POSITION_LABELS: Record<PlayerPositionCode, LocaleText> = {
|
||||||
|
FW: { 'zh-CN': '前锋', 'en-US': 'Forward', 'ms-MY': 'Penyerang' },
|
||||||
|
MF: { 'zh-CN': '中场', 'en-US': 'Midfielder', 'ms-MY': 'Pemain Tengah' },
|
||||||
|
DF: { 'zh-CN': '后卫', 'en-US': 'Defender', 'ms-MY': 'Pertahan' },
|
||||||
|
GK: { 'zh-CN': '守门员', 'en-US': 'Goalkeeper', 'ms-MY': 'Penjaga Gol' },
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PLAYER_COUNTRY_LABELS: Record<string, LocaleText> = {
|
||||||
|
ARG: { 'zh-CN': '阿根廷', 'en-US': 'Argentina', 'ms-MY': 'Argentina' },
|
||||||
|
ESP: { 'zh-CN': '西班牙', 'en-US': 'Spain', 'ms-MY': 'Sepanyol' },
|
||||||
|
CRO: { 'zh-CN': '克罗地亚', 'en-US': 'Croatia', 'ms-MY': 'Croatia' },
|
||||||
|
URU: { 'zh-CN': '乌拉圭', 'en-US': 'Uruguay', 'ms-MY': 'Uruguay' },
|
||||||
|
TUR: { 'zh-CN': '土耳其', 'en-US': 'Turkey', 'ms-MY': 'Turki' },
|
||||||
|
USA: { 'zh-CN': '美国', 'en-US': 'USA', 'ms-MY': 'Amerika Syarikat' },
|
||||||
|
BRA: { 'zh-CN': '巴西', 'en-US': 'Brazil', 'ms-MY': 'Brazil' },
|
||||||
|
POR: { 'zh-CN': '葡萄牙', 'en-US': 'Portugal', 'ms-MY': 'Portugal' },
|
||||||
|
ENG: { 'zh-CN': '英格兰', 'en-US': 'England', 'ms-MY': 'England' },
|
||||||
|
FRA: { 'zh-CN': '法国', 'en-US': 'France', 'ms-MY': 'Perancis' },
|
||||||
|
NED: { 'zh-CN': '荷兰', 'en-US': 'Netherlands', 'ms-MY': 'Belanda' },
|
||||||
|
GER: { 'zh-CN': '德国', 'en-US': 'Germany', 'ms-MY': 'Jerman' },
|
||||||
|
NOR: { 'zh-CN': '挪威', 'en-US': 'Norway', 'ms-MY': 'Norway' },
|
||||||
|
MEX: { 'zh-CN': '墨西哥', 'en-US': 'Mexico', 'ms-MY': 'Mexico' },
|
||||||
|
EGY: { 'zh-CN': '埃及', 'en-US': 'Egypt', 'ms-MY': 'Mesir' },
|
||||||
|
SWE: { 'zh-CN': '瑞典', 'en-US': 'Sweden', 'ms-MY': 'Sweden' },
|
||||||
|
COL: { 'zh-CN': '哥伦比亚', 'en-US': 'Colombia', 'ms-MY': 'Colombia' },
|
||||||
|
MAR: { 'zh-CN': '摩洛哥', 'en-US': 'Morocco', 'ms-MY': 'Maghribi' },
|
||||||
|
BEL: { 'zh-CN': '比利时', 'en-US': 'Belgium', 'ms-MY': 'Belgium' },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** key = BuiltinPlayer.id(文件名去掉 .jpg) */
|
||||||
|
export const PLAYER_LOCALE_META: Record<string, PlayerLocaleMeta> = {
|
||||||
|
'何塞·曼努埃尔·洛佩斯-前锋-阿根廷': {
|
||||||
|
name: { 'zh-CN': '何塞·曼努埃尔·洛佩斯', 'en-US': 'José Manuel López', 'ms-MY': 'José Manuel López' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ARG',
|
||||||
|
},
|
||||||
|
'佩德里-中场-西班牙': {
|
||||||
|
name: { 'zh-CN': '佩德里', 'en-US': 'Pedri', 'ms-MY': 'Pedri' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'ESP',
|
||||||
|
},
|
||||||
|
'卢卡·莫德里奇-中场-克罗地亚': {
|
||||||
|
name: { 'zh-CN': '卢卡·莫德里奇', 'en-US': 'Luka Modrić', 'ms-MY': 'Luka Modrić' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'CRO',
|
||||||
|
},
|
||||||
|
'华金·皮克雷斯-中场-乌拉圭': {
|
||||||
|
name: { 'zh-CN': '华金·皮克雷斯', 'en-US': 'Joaquín Piquerez', 'ms-MY': 'Joaquín Piquerez' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'URU',
|
||||||
|
},
|
||||||
|
'乔治亚·德·阿拉斯凯塔-中场-乌拉圭': {
|
||||||
|
name: { 'zh-CN': '乔治亚·德·阿拉斯凯塔', 'en-US': 'Giorgian de Arrascaeta', 'ms-MY': 'Giorgian de Arrascaeta' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'URU',
|
||||||
|
},
|
||||||
|
'乌古尔坎·卡基尔-守門員-土耳其': {
|
||||||
|
name: { 'zh-CN': '乌古尔坎·卡基尔', 'en-US': 'Uğurcan Çakır', 'ms-MY': 'Uğurcan Çakır' },
|
||||||
|
position: 'GK',
|
||||||
|
country: 'TUR',
|
||||||
|
},
|
||||||
|
'亚历杭德罗·曾德哈斯-前锋-美国': {
|
||||||
|
name: { 'zh-CN': '亚历杭德罗·曾德哈斯', 'en-US': 'Alejandro Zendejas', 'ms-MY': 'Alejandro Zendejas' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'USA',
|
||||||
|
},
|
||||||
|
'恩德里克-前锋-巴西': {
|
||||||
|
name: { 'zh-CN': '恩德里克', 'en-US': 'Endrick', 'ms-MY': 'Endrick' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'克里斯蒂亚诺·罗纳尔多-前锋-葡萄牙': {
|
||||||
|
name: { 'zh-CN': '克里斯蒂亚诺·罗纳尔多', 'en-US': 'Cristiano Ronaldo', 'ms-MY': 'Cristiano Ronaldo' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'POR',
|
||||||
|
},
|
||||||
|
'克里斯蒂安·罗梅罗-后卫-阿根廷': {
|
||||||
|
name: { 'zh-CN': '克里斯蒂安·罗梅罗', 'en-US': 'Cristian Romero', 'ms-MY': 'Cristian Romero' },
|
||||||
|
position: 'DF',
|
||||||
|
country: 'ARG',
|
||||||
|
},
|
||||||
|
'内马尔-前锋-巴西': {
|
||||||
|
name: { 'zh-CN': '内马尔', 'en-US': 'Neymar', 'ms-MY': 'Neymar' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'凯南·耶尔德兹-前锋-土耳其': {
|
||||||
|
name: { 'zh-CN': '凯南·耶尔德兹', 'en-US': 'Kenan Yıldız', 'ms-MY': 'Kenan Yıldız' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'TUR',
|
||||||
|
},
|
||||||
|
'卡塞米罗-中场-巴西': {
|
||||||
|
name: { 'zh-CN': '卡塞米罗', 'en-US': 'Casemiro', 'ms-MY': 'Casemiro' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'卢卡斯·帕奎塔-中场-巴西': {
|
||||||
|
name: { 'zh-CN': '卢卡斯·帕奎塔', 'en-US': 'Lucas Paquetá', 'ms-MY': 'Lucas Paquetá' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'基利安·姆巴佩-前锋-法国': {
|
||||||
|
name: { 'zh-CN': '基利安·姆巴佩', 'en-US': 'Kylian Mbappé', 'ms-MY': 'Kylian Mbappé' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'FRA',
|
||||||
|
},
|
||||||
|
'孟菲斯·德派-前锋-荷兰': {
|
||||||
|
name: { 'zh-CN': '孟菲斯·德派', 'en-US': 'Memphis Depay', 'ms-MY': 'Memphis Depay' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'NED',
|
||||||
|
},
|
||||||
|
'奥斯曼·登贝莱-前锋-法国': {
|
||||||
|
name: { 'zh-CN': '奥斯曼·登贝莱', 'en-US': 'Ousmane Dembélé', 'ms-MY': 'Ousmane Dembélé' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'FRA',
|
||||||
|
},
|
||||||
|
'布鲁诺·吉马良斯-中场-巴西': {
|
||||||
|
name: { 'zh-CN': '布鲁诺·吉马良斯', 'en-US': 'Bruno Guimarães', 'ms-MY': 'Bruno Guimarães' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'布鲁诺·费尔南德斯-中场-葡萄牙': {
|
||||||
|
name: { 'zh-CN': '布鲁诺·费尔南德斯', 'en-US': 'Bruno Fernandes', 'ms-MY': 'Bruno Fernandes' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'POR',
|
||||||
|
},
|
||||||
|
'布卡约·萨卡-前锋-英格兰': {
|
||||||
|
name: { 'zh-CN': '布卡约·萨卡', 'en-US': 'Bukayo Saka', 'ms-MY': 'Bukayo Saka' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ENG',
|
||||||
|
},
|
||||||
|
'德尼兹·居尔-前锋-土耳其': {
|
||||||
|
name: { 'zh-CN': '德尼兹·居尔', 'en-US': 'Deniz Gül', 'ms-MY': 'Deniz Gül' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'TUR',
|
||||||
|
},
|
||||||
|
'德尼兹·温达夫-前锋-德国': {
|
||||||
|
name: { 'zh-CN': '德尼兹·温达夫', 'en-US': 'Deniz Undav', 'ms-MY': 'Deniz Undav' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'GER',
|
||||||
|
},
|
||||||
|
'拉斐尔·迪亚斯·贝洛利-前锋-巴西': {
|
||||||
|
name: { 'zh-CN': '拉斐尔·迪亚斯·贝洛利', 'en-US': 'Raphinha', 'ms-MY': 'Raphinha' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'拉明·亚马尔-前锋-西班牙': {
|
||||||
|
name: { 'zh-CN': '拉明·亚马尔', 'en-US': 'Lamine Yamal', 'ms-MY': 'Lamine Yamal' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ESP',
|
||||||
|
},
|
||||||
|
'朱利安·阿尔瓦雷斯-前锋-阿根廷': {
|
||||||
|
name: { 'zh-CN': '朱利安·阿尔瓦雷斯', 'en-US': 'Julián Álvarez', 'ms-MY': 'Julián Álvarez' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ARG',
|
||||||
|
},
|
||||||
|
'梅西-前锋-阿根廷': {
|
||||||
|
name: { 'zh-CN': '梅西', 'en-US': 'Lionel Messi', 'ms-MY': 'Lionel Messi' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ARG',
|
||||||
|
},
|
||||||
|
'迈克尔·奥利塞-前锋-法国': {
|
||||||
|
name: { 'zh-CN': '迈克尔·奥利塞', 'en-US': 'Michael Olise', 'ms-MY': 'Michael Olise' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'FRA',
|
||||||
|
},
|
||||||
|
'穆罕默德·萨拉赫-前锋-埃及': {
|
||||||
|
name: { 'zh-CN': '穆罕默德·萨拉赫', 'en-US': 'Mohamed Salah', 'ms-MY': 'Mohamed Salah' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'EGY',
|
||||||
|
},
|
||||||
|
'维尼修斯·儒尼奥尔-前锋-巴西': {
|
||||||
|
name: { 'zh-CN': '维尼修斯·儒尼奥尔', 'en-US': 'Vinícius Júnior', 'ms-MY': 'Vinícius Júnior' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'维克托·哲凯赖什-前锋-瑞典': {
|
||||||
|
name: { 'zh-CN': '维克托·哲凯赖什', 'en-US': 'Viktor Gyökeres', 'ms-MY': 'Viktor Gyökeres' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'SWE',
|
||||||
|
},
|
||||||
|
'圣地亚哥·吉梅内斯-前锋-墨西哥': {
|
||||||
|
name: { 'zh-CN': '圣地亚哥·吉梅内斯', 'en-US': 'Santiago Giménez', 'ms-MY': 'Santiago Giménez' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'MEX',
|
||||||
|
},
|
||||||
|
'埃德森·阿尔瓦雷斯-后卫-墨西哥': {
|
||||||
|
name: { 'zh-CN': '埃德森·阿尔瓦雷斯', 'en-US': 'Edson Álvarez', 'ms-MY': 'Edson Álvarez' },
|
||||||
|
position: 'DF',
|
||||||
|
country: 'MEX',
|
||||||
|
},
|
||||||
|
'埃贝雷奇·埃泽-中场-英格兰': {
|
||||||
|
name: { 'zh-CN': '埃贝雷奇·埃泽', 'en-US': 'Eberechi Eze', 'ms-MY': 'Eberechi Eze' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'ENG',
|
||||||
|
},
|
||||||
|
'埃尔林·哈兰德-前锋-挪威': {
|
||||||
|
name: { 'zh-CN': '埃尔林·哈兰德', 'en-US': 'Erling Haaland', 'ms-MY': 'Erling Haaland' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'NOR',
|
||||||
|
},
|
||||||
|
'蒂博·库尔图瓦-守門員-比利时': {
|
||||||
|
name: { 'zh-CN': '蒂博·库尔图瓦', 'en-US': 'Thibaut Courtois', 'ms-MY': 'Thibaut Courtois' },
|
||||||
|
position: 'GK',
|
||||||
|
country: 'BEL',
|
||||||
|
},
|
||||||
|
'曼努埃尔·诺伊尔-守門員-德国': {
|
||||||
|
name: { 'zh-CN': '曼努埃尔·诺伊尔', 'en-US': 'Manuel Neuer', 'ms-MY': 'Manuel Neuer' },
|
||||||
|
position: 'GK',
|
||||||
|
country: 'GER',
|
||||||
|
},
|
||||||
|
'祖德·贝林厄姆-中场-英格兰': {
|
||||||
|
name: { 'zh-CN': '祖德·贝林厄姆', 'en-US': 'Jude Bellingham', 'ms-MY': 'Jude Bellingham' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'ENG',
|
||||||
|
},
|
||||||
|
'伦纳特·卡尔-中场-德国': {
|
||||||
|
name: { 'zh-CN': '伦纳特·卡尔', 'en-US': 'Lennart Karl', 'ms-MY': 'Lennart Karl' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'GER',
|
||||||
|
},
|
||||||
|
'费德里科·巴尔韦德-中场-乌拉圭': {
|
||||||
|
name: { 'zh-CN': '费德里科·巴尔韦德', 'en-US': 'Federico Valverde', 'ms-MY': 'Federico Valverde' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'URU',
|
||||||
|
},
|
||||||
|
'贾马尔·慕斯拉-中场-德国': {
|
||||||
|
name: { 'zh-CN': '贾马尔·慕斯拉', 'en-US': 'Jamal Musiala', 'ms-MY': 'Jamal Musiala' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'GER',
|
||||||
|
},
|
||||||
|
'路易斯·迪亚斯-前锋-哥伦比亚': {
|
||||||
|
name: { 'zh-CN': '路易斯·迪亚斯', 'en-US': 'Luis Díaz', 'ms-MY': 'Luis Díaz' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'COL',
|
||||||
|
},
|
||||||
|
'阿什拉夫·哈基米-后卫-摩洛哥': {
|
||||||
|
name: { 'zh-CN': '阿什拉夫·哈基米', 'en-US': 'Achraf Hakimi', 'ms-MY': 'Achraf Hakimi' },
|
||||||
|
position: 'DF',
|
||||||
|
country: 'MAR',
|
||||||
|
},
|
||||||
|
'阿利松·贝克尔-守門員-巴西': {
|
||||||
|
name: { 'zh-CN': '阿利松·贝克尔', 'en-US': 'Alisson Becker', 'ms-MY': 'Alisson Becker' },
|
||||||
|
position: 'GK',
|
||||||
|
country: 'BRA',
|
||||||
|
},
|
||||||
|
'阿尔达·居莱尔-前锋-土耳其': {
|
||||||
|
name: { 'zh-CN': '阿尔达·居莱尔', 'en-US': 'Arda Güler', 'ms-MY': 'Arda Güler' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'TUR',
|
||||||
|
},
|
||||||
|
'马西斯·拉扬·切尔基-中场-法国': {
|
||||||
|
name: { 'zh-CN': '马西斯·拉扬·切尔基', 'en-US': 'Rayan Cherki', 'ms-MY': 'Rayan Cherki' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'FRA',
|
||||||
|
},
|
||||||
|
'马库斯·拉什福德-前锋-英格兰': {
|
||||||
|
name: { 'zh-CN': '马库斯·拉什福德', 'en-US': 'Marcus Rashford', 'ms-MY': 'Marcus Rashford' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ENG',
|
||||||
|
},
|
||||||
|
'哈里·凯恩-前锋-英格兰': {
|
||||||
|
name: { 'zh-CN': '哈里·凯恩', 'en-US': 'Harry Kane', 'ms-MY': 'Harry Kane' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ENG',
|
||||||
|
},
|
||||||
|
'尼科·威廉斯-前锋-西班牙': {
|
||||||
|
name: { 'zh-CN': '尼科·威廉斯', 'en-US': 'Nico Williams', 'ms-MY': 'Nico Williams' },
|
||||||
|
position: 'FW',
|
||||||
|
country: 'ESP',
|
||||||
|
},
|
||||||
|
'巴勃罗·加维-中场-西班牙': {
|
||||||
|
name: { 'zh-CN': '巴勃罗·加维', 'en-US': 'Pablo Gavi', 'ms-MY': 'Pablo Gavi' },
|
||||||
|
position: 'MF',
|
||||||
|
country: 'ESP',
|
||||||
|
},
|
||||||
|
'吉列尔莫·奥乔亚-守門員-墨西哥': {
|
||||||
|
name: { 'zh-CN': '吉列尔莫·奥乔亚', 'en-US': 'Guillermo Ochoa', 'ms-MY': 'Guillermo Ochoa' },
|
||||||
|
position: 'GK',
|
||||||
|
country: 'MEX',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function mapPositionFromZh(position: string): PlayerPositionCode {
|
||||||
|
if (position.includes('守') || position.includes('门') || position.includes('門')) return 'GK';
|
||||||
|
if (position.includes('后') || position.includes('後')) return 'DF';
|
||||||
|
if (position.includes('中')) return 'MF';
|
||||||
|
return 'FW';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlayerLocaleMeta(player: BuiltinPlayer): PlayerLocaleMeta {
|
||||||
|
const meta = PLAYER_LOCALE_META[player.id];
|
||||||
|
if (meta) return meta;
|
||||||
|
return {
|
||||||
|
name: { 'zh-CN': player.name },
|
||||||
|
position: mapPositionFromZh(player.position),
|
||||||
|
country: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlayerDisplayName(player: BuiltinPlayer, locale: string): string {
|
||||||
|
const meta = getPlayerLocaleMeta(player);
|
||||||
|
return resolveTranslationFallback(meta.name, locale) || player.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlayerPositionLabel(player: BuiltinPlayer, locale: string): string {
|
||||||
|
const meta = getPlayerLocaleMeta(player);
|
||||||
|
const labels = PLAYER_POSITION_LABELS[meta.position];
|
||||||
|
return resolveTranslationFallback(labels, locale) || player.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlayerCountryLabel(player: BuiltinPlayer, locale: string): string {
|
||||||
|
const meta = getPlayerLocaleMeta(player);
|
||||||
|
if (!meta.country) return player.country;
|
||||||
|
const labels = PLAYER_COUNTRY_LABELS[meta.country];
|
||||||
|
return resolveTranslationFallback(labels ?? {}, locale) || player.country;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlayerSearchTokens(player: BuiltinPlayer): string[] {
|
||||||
|
const meta = getPlayerLocaleMeta(player);
|
||||||
|
const tokens = new Set<string>();
|
||||||
|
for (const value of Object.values(meta.name)) {
|
||||||
|
if (value) tokens.add(value.toLowerCase());
|
||||||
|
}
|
||||||
|
for (const loc of ['zh-CN', 'en-US', 'ms-MY']) {
|
||||||
|
tokens.add(getPlayerPositionLabel(player, loc).toLowerCase());
|
||||||
|
tokens.add(getPlayerCountryLabel(player, loc).toLowerCase());
|
||||||
|
}
|
||||||
|
tokens.add(player.name.toLowerCase());
|
||||||
|
tokens.add(player.position.toLowerCase());
|
||||||
|
tokens.add(player.country.toLowerCase());
|
||||||
|
return [...tokens];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatPlayerMeta(player: BuiltinPlayer, locale: string): string {
|
||||||
|
return `${getPlayerPositionLabel(player, locale)} · ${getPlayerCountryLabel(player, locale)}`;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user