-
Notifications
You must be signed in to change notification settings - Fork 0
Developer Guide
s12kuma01 edited this page Sep 2, 2025
·
2 revisions
LangPack Studioの開発環境構築、ビルド方法について説明します。
# Node.js 18以上が必要
node --version # v18.0.0以上
# nvmを使用する場合
nvm install 18
nvm use 18git --version # 任意のバージョンgit clone https://github.com/Sumire-Labs/LangPack-Studio.git
cd LangPack-Studionpm installnpm run devブラウザで http://localhost:8080 にアクセスして開発版を確認できます。
LangPack-Studio/
├── src/ # ソースコード
│ ├── components/ # Reactコンポーネント
│ │ ├── redesign/ # 新UI設計のコンポーネント
│ │ │ ├── views/ # 各ビュー(ステップ)のコンポーネント
│ │ │ ├── Header.tsx # アプリケーションヘッダー
│ │ │ ├── Sidebar.tsx # サイドバーナビゲーション
│ │ │ └── WelcomeScreen.tsx # ウェルカム画面
│ │ └── [legacy]/ # 旧UIコンポーネント
│ ├── utils/ # ユーティリティ関数
│ │ ├── fileParser.ts # ファイル解析機能
│ │ ├── resourcePackGenerator.ts # リソースパック生成
│ │ └── translationService.ts # 翻訳サービス
│ ├── types/ # TypeScript型定義
│ ├── AppNew.tsx # メインアプリケーション(新版)
│ ├── App.tsx # メインアプリケーション(旧版)
│ └── main.tsx # エントリーポイント
├── public/ # 静的ファイル
├── electron/ # Electron関連ファイル
├── dist/ # ビルド出力
├── wiki-docs/ # Wiki文書
├── package.json # プロジェクト設定
├── tsconfig.json # TypeScript設定
├── vite.config.ts # Vite設定
└── README.md # プロジェクト説明
- React 18: UIライブラリ
- TypeScript: 型安全な開発
- Material-UI v5: UIコンポーネントライブラリ
- Emotion: CSS-in-JS
- React Dropzone: ファイルドラッグ&ドロップ
- Vite: 高速な開発サーバー・ビルドツール
- Electron: デスクトップアプリケーション化
- Axios: HTTP クライアント
- 各種翻訳API: Google, DeepL, Azure, OpenAI, LibreTranslate
- JSZip: ZIP ファイル生成
- File API: ブラウザでのファイル処理
npm run dev # 開発サーバー起動
npm run build # 本番用ビルド
npm run preview # ビルド結果のプレビューnpm run electron:dev # Electron開発版
npm run electron:build # Electron配布用パッケージ作成npm run test # ユニットテスト実行
npm run test:watch # テストのウォッチモード
npm run test:coverage # カバレッジレポート生成npm run lint # ESLintによるコードチェック
npm run lint:fix # 自動修正可能なエラーの修正
npm run format # Prettierによるコード整形src/
├── components/
│ └── __tests__/ # コンポーネントテスト
├── utils/
│ └── __tests__/ # ユーティリティテスト
└── __tests__/ # 統合テスト
// utils/__tests__/fileParser.test.ts
import { parseJsonFile, parseLangFile } from '../fileParser'
describe('fileParser', () => {
test('should parse JSON file correctly', () => {
const content = '{"key": "value"}'
const result = parseJsonFile(content)
expect(result.entries).toHaveLength(1)
expect(result.entries[0].key).toBe('key')
expect(result.entries[0].value).toBe('value')
})
test('should handle invalid JSON', () => {
const content = 'invalid json'
expect(() => parseJsonFile(content)).toThrow()
})
})// components/__tests__/Header.test.tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { ThemeProvider, createTheme } from '@mui/material/styles'
import Header from '../redesign/Header'
const renderWithTheme = (component: React.ReactElement) => {
const theme = createTheme()
return render(
<ThemeProvider theme={theme}>
{component}
</ThemeProvider>
)
}
describe('Header', () => {
test('should toggle dark mode', () => {
const mockToggle = jest.fn()
renderWithTheme(
<Header
darkMode={false}
onToggleDarkMode={mockToggle}
onReset={() => {}}
/>
)
const darkModeButton = screen.getByLabelText(/ダークモード/i)
fireEvent.click(darkModeButton)
expect(mockToggle).toHaveBeenCalledTimes(1)
})
})# バンドルサイズ分析
npm run analyze
# Tree shakingの確認
npm run build -- --analyze// ✅ useMemoで計算結果をキャッシュ
const expensiveValue = useMemo(() => {
return heavyCalculation(data)
}, [data])
// ✅ useCallbackで関数をキャッシュ
const handleClick = useCallback(() => {
// クリック処理
}, [dependency])// ✅ React.memoで不要な再レンダリングを防ぐ
export const ExpensiveComponent = React.memo<Props>(({ data }) => {
return <div>{/* レンダリング内容 */}</div>
})