diff --git a/src/components/molecules/BattlesuitCard.tsx b/src/components/molecules/BattlesuitCard.tsx index 6493e0d5..e2c0c599 100644 --- a/src/components/molecules/BattlesuitCard.tsx +++ b/src/components/molecules/BattlesuitCard.tsx @@ -1,14 +1,12 @@ /** @jsxImportSource theme-ui */ import { Box, Card, Text, Flex } from '@theme-ui/components' -import { useRouter } from 'next/router' import { assetsBucketBaseUrl } from '../../lib/consts' import { BattlesuitData } from '../../lib/honkai3rd/battlesuits' -import { translate } from '../../lib/i18n' import PageLink from '../atoms/PageLink' import SquareImageBox from '../atoms/SquareImageBox' interface BattlesuitCardProps { - battlesuit: Pick + battlesuit: Pick hidden?: boolean size?: 'sm' | 'default' href?: string @@ -22,14 +20,6 @@ const BattlesuitCard = ({ href, m, }: BattlesuitCardProps) => { - const { locale } = useRouter() - - const battlesuitName = translate( - locale, - { 'ko-KR': battlesuit.krName }, - battlesuit.name - ) - if (href == null) { href = `/honkai3rd/battlesuits/${battlesuit.id}` } @@ -50,7 +40,7 @@ const BattlesuitCard = ({ @@ -62,7 +52,7 @@ const BattlesuitCard = ({ whiteSpace: 'nowrap', }} > - {battlesuitName} + {battlesuit.name} @@ -84,7 +74,7 @@ const BattlesuitCard = ({ > @@ -97,7 +87,7 @@ const BattlesuitCard = ({ textAlign: 'center', }} > - {battlesuitName} + {battlesuit.name} diff --git a/src/lib/honkai3rd/battlesuits.ts b/src/lib/honkai3rd/battlesuits.ts index 9cf7d982..868729fc 100644 --- a/src/lib/honkai3rd/battlesuits.ts +++ b/src/lib/honkai3rd/battlesuits.ts @@ -1,8 +1,6 @@ export interface BattlesuitSkill { name: string - krName?: string description: string - krDescription?: string requiredRank?: string } @@ -23,7 +21,6 @@ export interface BattlesuitData { id: string version?: string name: string - krName?: string type: string valkyrie: string features: string[] diff --git a/src/pages/honkai3rd/battlesuits/[battlesuitId].tsx b/src/pages/honkai3rd/battlesuits/[battlesuitId].tsx index 37476c12..ec22112a 100644 --- a/src/pages/honkai3rd/battlesuits/[battlesuitId].tsx +++ b/src/pages/honkai3rd/battlesuits/[battlesuitId].tsx @@ -59,12 +59,6 @@ const BattlesuitShowPage = ({ const { t } = useTranslation() const { locale } = useRouter() - const battlesuitName = translate( - locale, - { ['ko-KR']: battlesuit.krName }, - battlesuit.name - ) - const { label: valkyrieLabel, krLabel } = valkyries.find( (aValkyrie) => aValkyrie.value === battlesuit.valkyrie ) || { label: battlesuit.valkyrie, krLabel: battlesuit.valkyrie } @@ -85,7 +79,7 @@ const BattlesuitShowPage = ({ return ( - {battlesuitName} + {battlesuit.name} {battlesuitName} {battlesuit.sp != null && ( )} @@ -290,7 +277,7 @@ export async function getStaticProps({ params, locale, }: NextPageContext & { params: { battlesuitId: string } }) { - const battlesuit = getBattlesuitById(params.battlesuitId)! + const battlesuit = getBattlesuitById(params.battlesuitId, locale)! const { weaponIds, stigmataIds } = (battlesuit.equipment || []).reduce<{ weaponIds: string[] stigmataIds: string[] @@ -336,13 +323,11 @@ export async function getStaticPaths() { interface BattlesuitSkillGroupCardProps { heading: string skillGroup: BattlesuitSkillGroup - locale?: string } const BattlesuitSkillGroupCard = ({ heading, skillGroup, - locale, }: BattlesuitSkillGroupCardProps) => { return ( @@ -353,39 +338,21 @@ const BattlesuitSkillGroupCard = ({ }} > - {translate( - locale, - { 'ko-KR': skillGroup.core.krName }, - skillGroup.core.name - )} + {skillGroup.core.name} {heading} - {translate( - locale, - { 'ko-KR': skillGroup.core.krDescription }, - skillGroup.core.description - )} + {skillGroup.core.description} {skillGroup.subskills.map((subskill) => { - const skillName = translate( - locale, - { 'ko-KR': subskill.krName }, - subskill.name - ) - const skillDescription = translate( - locale, - { 'ko-KR': subskill.krDescription }, - subskill.description - ) return ( - {skillName} + {subskill.name} {subskill.requiredRank != null ? ( /^[0-9]/.test(subskill.requiredRank) ? ( - {skillDescription} + {subskill.description} ) diff --git a/src/pages/honkai3rd/battlesuits/index.tsx b/src/pages/honkai3rd/battlesuits/index.tsx index 53c52145..087e3a6d 100644 --- a/src/pages/honkai3rd/battlesuits/index.tsx +++ b/src/pages/honkai3rd/battlesuits/index.tsx @@ -1,6 +1,5 @@ /** @jsxImportSource theme-ui */ import { Box, Heading, Flex, Button } from '@theme-ui/components' -import { pick } from 'ramda' import { useCallback, useMemo, useState } from 'react' import FilterButton from '../../../components/atoms/FilterButton' import Breadcrumb from '../../../components/organisms/Breadcrumb' @@ -21,7 +20,7 @@ import Honkai3rdLayout from '../../../components/layouts/Honkai3rdLayout' type BattlesuitListItemData = Pick< BattlesuitData, - 'id' | 'name' | 'krName' | 'features' | 'type' | 'valkyrie' + 'id' | 'name' | 'features' | 'type' | 'valkyrie' > interface BattlesuitListPageProps { @@ -171,12 +170,15 @@ export default BattlesuitListPage export async function getStaticProps({ locale }: NextPageContext) { return { props: { - battlesuits: listBattlesuits().map((battlesuit) => - pick( - ['id', 'name', 'krName', 'features', 'type', 'valkyrie'], - battlesuit - ) - ), + battlesuits: listBattlesuits().map((battlesuit) => { + return { + id: battlesuit.id, + name: battlesuit.name, + features: battlesuit.features, + type: battlesuit.type, + valikyrie: battlesuit.valkyrie, + } + }), ...(await getI18NProps(locale)), }, } diff --git a/src/pages/honkai3rd/elysian-realm/battlesuits/[battlesuitId].tsx b/src/pages/honkai3rd/elysian-realm/battlesuits/[battlesuitId].tsx index 45540925..4cf3ac3e 100644 --- a/src/pages/honkai3rd/elysian-realm/battlesuits/[battlesuitId].tsx +++ b/src/pages/honkai3rd/elysian-realm/battlesuits/[battlesuitId].tsx @@ -5,8 +5,7 @@ import Breadcrumb from '../../../../components/organisms/Breadcrumb' import { BattlesuitData } from '../../../../lib/honkai3rd/battlesuits' import { generateI18NPaths, getI18NProps } from '../../../../server/i18n' import { getBattlesuitById } from '../../../../server/data/honkai3rd/battlesuits' -import { translate, useTranslation } from '../../../../lib/i18n' -import { useRouter } from 'next/router' +import { useTranslation } from '../../../../lib/i18n' import Head from '../../../../components/atoms/Head' import { assetsBucketBaseUrl } from '../../../../lib/consts' import Honkai3rdLayout from '../../../../components/layouts/Honkai3rdLayout' @@ -38,18 +37,10 @@ const BattlesuitShowPage = ({ signetSet, }: BattlesuitShowPageProps) => { const { t } = useTranslation() - const { locale } = useRouter() - - const battlesuitName = translate( - locale, - { ['ko-KR']: battlesuit.krName }, - battlesuit.name - ) - return ( - {battlesuitName} + {battlesuit.name} {battlesuitName} interface BattlesuitListPageProps { @@ -182,7 +182,7 @@ export async function getStaticProps({ locale }: NextPageContext) { }) return { props: { - battlesuitMap: getBattlesuitMapByIds(erBattlesuitIds), + battlesuitMap: getBattlesuitMapByIds(erBattlesuitIds, locale), supportBattlesuits, remembranceSigils, ...(await getI18NProps(locale)), diff --git a/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx b/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx index 7368ad06..a5ce0d37 100644 --- a/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx +++ b/src/pages/honkai3rd/prints/battlesuits/[battlesuitId].tsx @@ -25,8 +25,7 @@ import { getBattlesuitById, listBattlesuits, } from '../../../../server/data/honkai3rd/battlesuits' -import { translate, useTranslation } from '../../../../lib/i18n' -import { useRouter } from 'next/router' +import { useTranslation } from '../../../../lib/i18n' import { assetsBucketBaseUrl } from '../../../../lib/consts' import { WeaponData } from '../../../../lib/honkai3rd/weapons' import { getWeaponMapByIds } from '../../../../server/data/honkai3rd/weapons' @@ -50,17 +49,10 @@ const BattlesuitShowPage = ({ stigmataMap, }: BattlesuitShowPageProps) => { const { t } = useTranslation() - const { locale } = useRouter() - - const battlesuitName = translate( - locale, - { ['ko-KR']: battlesuit.krName }, - battlesuit.name - ) return ( - {battlesuitName} + {battlesuit.name} {battlesuitName} {battlesuit.sp != null && ( )} @@ -228,7 +213,7 @@ export async function getStaticProps({ params, locale, }: NextPageContext & { params: { battlesuitId: string } }) { - const battlesuit = getBattlesuitById(params.battlesuitId)! + const battlesuit = getBattlesuitById(params.battlesuitId, locale)! const { weaponIds, stigmataIds } = (battlesuit.equipment || []).reduce<{ weaponIds: string[] stigmataIds: string[] @@ -274,13 +259,11 @@ export async function getStaticPaths() { interface BattlesuitSkillGroupCardProps { heading: string skillGroup: BattlesuitSkillGroup - locale?: string } const BattlesuitSkillGroupCard = ({ heading, skillGroup, - locale, }: BattlesuitSkillGroupCardProps) => { return ( @@ -291,39 +274,21 @@ const BattlesuitSkillGroupCard = ({ }} > - {translate( - locale, - { 'ko-KR': skillGroup.core.krName }, - skillGroup.core.name - )} + {skillGroup.core.name} {heading} - {translate( - locale, - { 'ko-KR': skillGroup.core.krDescription }, - skillGroup.core.description - )} + {skillGroup.core.description} {skillGroup.subskills.map((subskill) => { - const skillName = translate( - locale, - { 'ko-KR': subskill.krName }, - subskill.name - ) - const skillDescription = translate( - locale, - { 'ko-KR': subskill.krDescription }, - subskill.description - ) return ( - {skillName} + {subskill.name} {subskill.requiredRank != null ? ( /^[0-9]/.test(subskill.requiredRank) ? ( - {skillDescription} + {subskill.description} ) diff --git a/src/pages/honkai3rd/prints/weapons/[weaponId].tsx b/src/pages/honkai3rd/prints/weapons/[weaponId].tsx index 404ec948..73d153c0 100644 --- a/src/pages/honkai3rd/prints/weapons/[weaponId].tsx +++ b/src/pages/honkai3rd/prints/weapons/[weaponId].tsx @@ -147,7 +147,8 @@ export async function getStaticProps({ const battlesuitMap = getBattlesuitMapByIds( weapon != null && weapon.battlesuits != null ? weapon.battlesuits.map(({ id }) => id) - : [] + : [], + locale ) const weaponIds = [] diff --git a/src/pages/honkai3rd/versions/[versionId].tsx b/src/pages/honkai3rd/versions/[versionId].tsx index 9fa98c71..21bf09d9 100644 --- a/src/pages/honkai3rd/versions/[versionId].tsx +++ b/src/pages/honkai3rd/versions/[versionId].tsx @@ -57,11 +57,7 @@ const VersionShowPage = ({ 'versions.version' )} ${versionName} / ${t('versions.new-battlesuits')}: ${battlesuits .map((battlesuit) => { - return translate( - locale, - { 'ko-KR': battlesuit.krName }, - battlesuit.name - ) + return battlesuit.name }) .join(',')} / ${t('versions.new-weapons')}: ${weapons .map((weapon) => { @@ -113,12 +109,6 @@ const VersionShowPage = ({ {battlesuits.map((battlesuit) => { - const battlesuitName = translate( - locale, - { 'ko-KR': battlesuit.krName }, - battlesuit.name - ) - return ( - {battlesuitName} + {battlesuit.name} @@ -232,7 +222,7 @@ export async function getStaticProps({ const versionData = getVersion(params.versionId)! const battlesuits = versionData.newBattlesuits.map((battlesuitId) => { - return getBattlesuitById(battlesuitId) + return getBattlesuitById(battlesuitId, locale) }) const weapons = versionData.newWeapons.map((weaponId) => { return getWeaponById(weaponId) diff --git a/src/pages/honkai3rd/versions/index.tsx b/src/pages/honkai3rd/versions/index.tsx index a9f6e070..d39a3fcd 100644 --- a/src/pages/honkai3rd/versions/index.tsx +++ b/src/pages/honkai3rd/versions/index.tsx @@ -103,12 +103,6 @@ const VersionIndexPage = ({ {currentVersionNewBattlesuits.map((battlesuit) => { - const battlesuitName = translate( - locale, - { 'ko-KR': battlesuit.krName }, - battlesuit.name - ) - return ( - {battlesuitName} + {battlesuit.name} diff --git a/src/scripts/migrations/battlesuits.ts b/src/scripts/migrations/battlesuits.ts index 959540a9..89294e28 100644 --- a/src/scripts/migrations/battlesuits.ts +++ b/src/scripts/migrations/battlesuits.ts @@ -22,6 +22,7 @@ const order = [ 'basic', 'sp', 'core', + 'subskills', 'description', 'krDescription', 'requiredRank', diff --git a/src/server/data/honkai3rd/battlesuits.ts b/src/server/data/honkai3rd/battlesuits.ts index 12bd97da..c52078a2 100644 --- a/src/server/data/honkai3rd/battlesuits.ts +++ b/src/server/data/honkai3rd/battlesuits.ts @@ -1,152 +1,67 @@ -import { readdirSync, readFileSync, readJsonFileSync } from '../fs' -import { compareVersion } from '../../../lib/string' -import { - BattlesuitData, - BattlesuitSkillGroup, -} from '../../../lib/honkai3rd/battlesuits' +import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits' +import fs from 'fs' +import path from 'path' +import yaml from 'yaml' +import { omit } from 'ramda' -const battlesuitsFileNameList = readdirSync('honkai3rd/battlesuits') -const battlesuitDataList = battlesuitsFileNameList - .map((fileName) => { - const filePathname = 'honkai3rd/battlesuits/' + fileName - const data = readJsonFileSync(filePathname) as BattlesuitData +let parsedData: any = null - const krDataFilePath = `honkai3rd/ko-KR/battlesuits/${data.id}.md` - try { - const krData = parseSkillData(readFileSync(krDataFilePath).toString()) +export function listBattlesuits(locale?: string): BattlesuitData[] { + if (parsedData == null) { + parsedData = yaml.parse( + fs + .readFileSync( + path.join(process.cwd(), 'data/honkai3rd/battlesuits.yaml') + ) + .toString('utf-8') + ) + } + const battlesuits = parsedData - data.krName = krData.name - assignKrDataToSkill(data.leader, krData.leader) - assignKrDataToSkill(data.passive, krData.passive) - assignKrDataToSkill(data.evasion, krData.evasion) - assignKrDataToSkill(data.special, krData.special) - assignKrDataToSkill(data.ultimate, krData.ultimate) - assignKrDataToSkill(data.basic, krData.basic) - if (data.sp != null && krData.sp != null) { - assignKrDataToSkill(data.sp, krData.sp) - } - } catch (error) { - console.warn('Failed to read', krDataFilePath) - console.warn(error) - } - return data + const localized = (battlesuits as any[]).map((battlesuit) => { + return { + ...omit(['krName', 'krDescription'], battlesuit), + name: locale === 'ko-KR' ? battlesuit.krName : battlesuit.name, + leader: localizeSkillGroup(battlesuit.leader), + passive: localizeSkillGroup(battlesuit.passive), + evasion: localizeSkillGroup(battlesuit.evasion), + special: localizeSkillGroup(battlesuit.special), + ultimate: localizeSkillGroup(battlesuit.ultimate), + basic: localizeSkillGroup(battlesuit.basic), + sp: battlesuit.sp != null ? localizeSkillGroup(battlesuit.sp) : null, + } as any }) - .sort((a, b) => { - let compareResult = compareVersion(b.version || '0.0', a.version || '0.0') - if (compareResult !== 0) { - return compareResult + + return localized + + function localizeSkillGroup(skillGroup: any) { + return { + core: localizeSkill(skillGroup.core), + subskills: skillGroup.subskills.map((subskill: any) => + localizeSkill(subskill) + ), } - compareResult = a.name - .replace(/ \(.\)/, '') - .localeCompare(b.name.replace(/ \(.\)/, '')) + } - return compareResult - }) -const battlesuitMap = battlesuitDataList.reduce((map, stigmata) => { - map.set(stigmata.id, stigmata) - return map -}, new Map()) - -export function listBattlesuits() { - return battlesuitDataList + function localizeSkill(skill: any) { + return { + ...omit(['krName', 'krDescription'], skill), + name: locale === 'ko-KR' ? skill.krName : skill.name, + description: locale === 'ko-KR' ? skill.krDescription : skill.description, + } + } } -export function getBattlesuitById(id: string) { - return battlesuitMap.get(id) +export function getBattlesuitById(id: string, locale?: string) { + return listBattlesuits(locale).find((battlesuit) => battlesuit.id === id) } -export function getBattlesuitMapByIds(idList: string[]) { +export function getBattlesuitMapByIds(idList: string[], locale?: string) { return idList.reduce<{ [key: string]: BattlesuitData }>((map, id) => { - const battlesuit = getBattlesuitById(id) + const battlesuit = getBattlesuitById(id, locale) if (battlesuit != null) { map[id] = battlesuit } return map }, {}) } - -function parseSkillData(rawData: string) { - const [ - nameSection, - leaderSection, - passiveSection, - evasionSection, - specialSection, - ultimateSection, - basicSection, - spSection, - ] = rawData.split('\n## ') - - const name = nameSection.replace('#', '').trim() - - return { - name, - leader: parseSkillSection(leaderSection), - passive: parseSkillSection(passiveSection), - evasion: parseSkillSection(evasionSection), - special: parseSkillSection(specialSection), - ultimate: parseSkillSection(ultimateSection), - basic: parseSkillSection(basicSection), - sp: spSection != null ? parseSkillSection(spSection) : undefined, - } -} - -function parseSkillSection(rawData: string) { - const [coreSection, ...subskillSections] = rawData.split('\n### ') - - const [coreName, ...descriptionLines] = coreSection.trim().split('\n') - - return { - core: { - name: coreName, - description: descriptionLines.join('\n').trim(), - }, - subskills: subskillSections.map((subskillSection) => { - const [subskillName, ...subskillDescriptionLines] = subskillSection - .trim() - .split('\n') - - return { - name: subskillName, - description: subskillDescriptionLines.join('\n').trim(), - } - }), - } -} - -function assignKrDataToSkill( - skillGroup: BattlesuitSkillGroup, - krDataSkillGroup: BattlesuitSkillGroup -) { - if (krDataSkillGroup == null || krDataSkillGroup.core == null) { - throw new Error(`No translation for ${skillGroup.core.name}`) - } - try { - skillGroup.core.krName = krDataSkillGroup.core.name - skillGroup.core.krDescription = krDataSkillGroup.core.description.replace( - /\\\*/g, - '*' - ) - } catch (error) { - throw new Error( - `Failed to assign ${skillGroup.core.name}(${(error as Error).message})` - ) - } - skillGroup.subskills.forEach((subskill, index) => { - try { - subskill.krName = krDataSkillGroup.subskills[index].name - subskill.krDescription = krDataSkillGroup.subskills[ - index - ].description.replace(/\\\*/g, '*') - } catch (error) { - if (krDataSkillGroup.subskills[index] == null) { - throw new Error( - `No translation for ${skillGroup.core.name} / ${subskill.name}` - ) - } - throw new Error( - `Failed to assign ${skillGroup.core.name}(${(error as Error).message})` - ) - } - }) -} diff --git a/src/server/data/honkai3rd/elysianRealm.ts b/src/server/data/honkai3rd/elysianRealm.ts index c54d8bec..2daceb66 100644 --- a/src/server/data/honkai3rd/elysianRealm.ts +++ b/src/server/data/honkai3rd/elysianRealm.ts @@ -81,7 +81,7 @@ export const krSignetGroupMap = signetGroups.reduce<{ const name = group.id === 'elysia' - ? `${getBattlesuitById(setType)!.krName} 전용 각인` + ? `${getBattlesuitById(setType, 'ko-KR')!.name} 전용 각인` : `${setType === 'nexus' ? '증폭 각인' : '일반 각인'}${ setIndex != null ? ` ${setIndex}` : '' }` @@ -115,7 +115,7 @@ export function getSignetGroupById(id: string, locale = 'en-US') { export function getSupportBattlesuits(locale?: string) { return supportBattlesuitIds.map((battlesuitId) => { - const battlesuit = getBattlesuitById(battlesuitId)! + const battlesuit = getBattlesuitById(battlesuitId, locale)! const { skillName, description, @@ -138,7 +138,6 @@ export function getSupportBattlesuits(locale?: string) { .slice(2) .split('\n\n') - localizedName = battlesuit.krName! localizedSkillName = krSkillName localizedDescription = krDescriptionLines.join('\n').trim() }