fix: 아이템/몹 번역 분리

- 아이템 통계: items + blocks 테이블 사용 (달걀 → 달걀)
- 몹 통계: entities 테이블 사용 (달걀 → 던져진 달걀)
- 번역 덮어쓰기 버그 수정
This commit is contained in:
caadiq 2025-12-24 00:53:29 +09:00
parent e5823d140e
commit 527ac1e51b
2 changed files with 24 additions and 12 deletions

View file

@ -12,7 +12,12 @@ const dbPool = mysql.createPool({
}); });
// 캐시 데이터 // 캐시 데이터
let translationsCache = {}; let translationsCache = {
blocks: {}, // 블록 번역
items: {}, // 아이템 번역
entities: {}, // 엔티티 번역
itemsAndBlocks: {}, // 아이템 통계용 (items + blocks)
};
let iconsCache = {}; // { "type:name": iconUrl } - 타입별로 구분 let iconsCache = {}; // { "type:name": iconUrl } - 타입별로 구분
let gamerulesCache = {}; let gamerulesCache = {};
@ -35,23 +40,28 @@ async function loadTranslations() {
); );
// 캐시 초기화 // 캐시 초기화
translationsCache = {}; translationsCache = { blocks: {}, items: {}, entities: {}, all: {} };
iconsCache = {}; iconsCache = {};
// blocks, items, entities를 캐시에 저장 (type:name 형식으로 구분) // 타입별로 분리하여 저장
blocks.forEach((row) => { blocks.forEach((row) => {
translationsCache[row.name] = row.name_ko; translationsCache.blocks[row.name] = row.name_ko;
if (row.icon) iconsCache[`block:${row.name}`] = row.icon; if (row.icon) iconsCache[`block:${row.name}`] = row.icon;
}); });
items.forEach((row) => { items.forEach((row) => {
translationsCache[row.name] = row.name_ko; translationsCache.items[row.name] = row.name_ko;
if (row.icon) iconsCache[`item:${row.name}`] = row.icon; if (row.icon) iconsCache[`item:${row.name}`] = row.icon;
}); });
entities.forEach((row) => { entities.forEach((row) => {
translationsCache[row.name] = row.name_ko; translationsCache.entities[row.name] = row.name_ko;
if (row.icon) iconsCache[`entity:${row.name}`] = row.icon; if (row.icon) iconsCache[`entity:${row.name}`] = row.icon;
}); });
// 아이템 통계용 캐시 (items + blocks, 아이템 우선)
translationsCache.itemsAndBlocks = {};
Object.assign(translationsCache.itemsAndBlocks, translationsCache.blocks);
Object.assign(translationsCache.itemsAndBlocks, translationsCache.items);
// gamerules 캐시 // gamerules 캐시
gamerulesCache = {}; gamerulesCache = {};
gamerules.forEach((row) => { gamerules.forEach((row) => {

View file

@ -120,8 +120,10 @@ const PlayerStatsPage = ({ isMobile = false }) => {
const firstPlayed = formatDate(playerDetail?.firstJoin); const firstPlayed = formatDate(playerDetail?.firstJoin);
const lastPlayed = formatDate(playerDetail?.lastLeave > 0 ? playerDetail?.lastLeave : playerDetail?.lastJoin); const lastPlayed = formatDate(playerDetail?.lastLeave > 0 ? playerDetail?.lastLeave : playerDetail?.lastJoin);
// (DB ) // - (items + blocks)
const translate = (id) => translations[id] || id.replace(/_/g, ' '); const translateItem = (id) => translations.itemsAndBlocks?.[id] || translations.items?.[id] || translations.blocks?.[id] || id.replace(/_/g, ' ');
// - (entities)
const translateMob = (id) => translations.entities?.[id] || id.replace(/_/g, ' ');
// () // ()
const sortedItems = stats?.items const sortedItems = stats?.items
@ -131,7 +133,7 @@ const PlayerStatsPage = ({ isMobile = false }) => {
...stat, ...stat,
total: (stat.mined || 0) + (stat.used || 0) + (stat.pickedUp || 0) + (stat.crafted || 0) total: (stat.mined || 0) + (stat.used || 0) + (stat.pickedUp || 0) + (stat.crafted || 0)
})) }))
.sort((a, b) => translate(a.id).localeCompare(translate(b.id), 'ko')) .sort((a, b) => translateItem(a.id).localeCompare(translateItem(b.id), 'ko'))
: []; : [];
// () // ()
@ -142,7 +144,7 @@ const PlayerStatsPage = ({ isMobile = false }) => {
...stat, ...stat,
total: (stat.killed || 0) + (stat.killedBy || 0) total: (stat.killed || 0) + (stat.killedBy || 0)
})) }))
.sort((a, b) => translate(a.id).localeCompare(translate(b.id), 'ko')) .sort((a, b) => translateMob(a.id).localeCompare(translateMob(b.id), 'ko'))
: []; : [];
return ( return (
@ -307,7 +309,7 @@ const PlayerStatsPage = ({ isMobile = false }) => {
<div className="max-h-[400px] overflow-y-auto custom-scrollbar"> <div className="max-h-[400px] overflow-y-auto custom-scrollbar">
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{sortedItems.map((item) => ( {sortedItems.map((item) => (
<ItemStatRow key={item.id} item={item} translate={translate} icons={icons} /> <ItemStatRow key={item.id} item={item} translate={translateItem} icons={icons} />
))} ))}
</div> </div>
</div> </div>
@ -331,7 +333,7 @@ const PlayerStatsPage = ({ isMobile = false }) => {
<div className="max-h-[400px] overflow-y-auto custom-scrollbar"> <div className="max-h-[400px] overflow-y-auto custom-scrollbar">
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{sortedMobs.map((mob) => ( {sortedMobs.map((mob) => (
<MobStatRow key={mob.id} mob={mob} translate={translate} icons={icons} /> <MobStatRow key={mob.id} mob={mob} translate={translateMob} icons={icons} />
))} ))}
</div> </div>
</div> </div>