Skip to content

D3 POC

  1. i18n 라이브러리를 최소한으로 설정해서 만들어본 다국어 프로젝트
  2. 중국 프로젝트를 진행중이라 중국어와 한국어로 다국어 설정
  1. vite 프로젝트 생성

    Terminal window
    pnpm create vite
    |
    o Project name:
    | poc-d3
    |
    o Select a framework:
    | React
    |
    o Select a variant:
    | TypeScript + SWC
    |
    o Scaffolding project in D:\study\poc-d3...
    |
    — Done. Now run:
    cd poc-d3
    pnpm install
    pnpm run dev
  2. git 저장소 설정

    Terminal window
    cd poc-d3
    git init
  • storybook

    Terminal window
    pnpm create storybook@latest
  • d3

    Terminal window
    pnpm add d3
    pnpm add -D @types/d3
  • @types/node

    Terminal window
    pnpm install --save-dev @types/node
  • TailwindCSS

    Terminal window
    pnpm install tailwindcss @tailwindcss/vite
  • DaisyUI

    Terminal window
    pnpm add -D daisyui@latest
  • Prettier

    Terminal window
    pnpm add --save-dev --save-exact prettier
    pnpm install -D prettier-plugin-tailwindcss
  • vite-tsconfig-paths

    Terminal window
    pnpm add -D vite-tsconfig-paths
  • .prettierrc.cjs
  • eslint.config.js
  • tsconfig.app.json
  • vite.config.ts
  • src/index.css
  • Directorysrc
    • Directoryhook
      • index.ts
      • useLocale.ts
    • Directorylocales
      • i18n.ts
      • Directoryko
        • main_ko.json
      • Directoryzh
        • main_zh.json
    • Directoryutils
      • index.ts
  • App.tsx
  • main.tsx
src/locales/ko/main_ko.json
{
"apple": "사과",
"banana": "바나나",
"cherry": "체리"
}
src/locales/zh/main_zh.json
{
"apple": "苹果",
"banana": "香蕉",
"cherry": "樱桃"
}
src/locales/i18n.ts
import i18n from 'i18next'
import {initReactI18next} from 'react-i18next'
import mainKo from './ko/main_ko.json'
import mainZh from './zh/main_zh.json'
const resources = {
ko: {
translation: mainKo,
},
zh: {
translation: mainZh,
},
}
i18n.use(initReactI18next).init({
resources,
lng: 'ko',
fallbackLng: 'ko',
interpolation: {
escapeValue: false,
},
})
export default i18n
src/utils/index.ts
export const isNull = <T>(value: T): boolean => value === undefined || value === null
export const createArray = (count: number): number[] =>
[...Array(count).keys()].map((i) => i)
export const range = (start: number, end: number): number[] => {
if (end > start) {
return createArray(end - start).map((i) => i + start)
}
return []
}
export const applyParam = (value: string, params?: string[]) => {
let buffer = value
if (params && params.length > 0) {
range(0, params.length).forEach((i) => {
const key = `{${i}}`
buffer = buffer.replace(key, params[i])
})
}
return buffer
}
src/hook/useLocale.ts
import {applyParam, isNull} from '@/utils'
import {useTranslation} from 'react-i18next'
export const useLocale = () => {
const {i18n, t} = useTranslation()
const getLanguage = () => i18n.language
const changeLanguage = (langCd: string) => {
i18n.changeLanguage(langCd)
}
const getMessage = (key: string, params: string[]) => {
if (isNull(t)) {
return ''
}
const buffer = t(key)
return applyParam(buffer, params)
}
return {
getLanguage,
changeLanguage,
getMessage,
}
}
src/hook/index.ts
export * from './useLocale'
src/App.tsx
import './App.css'
import {useLocale} from '@/hook'
import {useEffect} from 'react'
const App = () => {
const {getMessage, getLanguage, changeLanguage} = useLocale()
useEffect(() => {
const language = getLanguage()
if (language !== 'ko' && language !== 'zh') {
changeLanguage('zh')
}
}, [])
return (
<div className="flex h-screen w-screen flex-col bg-white">
<div className="m-2">
<button className="btn btn-primary mr-3" onClick={() => changeLanguage('ko')}>
한국어
</button>
<button className="btn btn-primary mr-3" onClick={() => changeLanguage('zh')}>
중국어
</button>
</div>
<div>
<div className="text-black">{getMessage('apple', [])}</div>
<div className="text-black">{getMessage('banana', [])}</div>
<div className="text-black">{getMessage('cherry', [])}</div>
</div>
</div>
)
}
export default App
src/main.tsx
import {StrictMode} from 'react'
import {createRoot} from 'react-dom/client'
import './index.css'
import App from './App.tsx'
import {I18nextProvider} from 'react-i18next'
import i18n from './locales/i18n.ts'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
</StrictMode>,
)