anhuiqiang 1 týždeň pred
rodič
commit
664e531d4c

+ 114 - 114
README.md

@@ -1,207 +1,207 @@
 # AuraK
 
-AuraK は、マルチテナント対応のインテリジェント AI ナレッジベースプラットフォームです。React + NestJS をベースにしたフルスタックの RAG (検索拡張生成) システムで、外部 API、RBAC、テナント分離をサポートします。
+AuraK is a multi-tenant intelligent AI knowledge base platform. Built with React + NestJS, it's a full-stack RAG (Retrieval-Augmented Generation) system with external API support, RBAC, and tenant isolation.
 
-## ✨ 特徴
+## ✨ Features
 
-- 🔐 **ユーザーシステム**: ユーザー登録、ログイン、権限管理を完備
-- 🤖 **マルチモデル対応**: OpenAI 互換インターフェース + Google Gemini ネイティブサポート
-- 📚 **インテリジェント・ナレッジベース**: ドキュメントのアップロード、チャンク分割、ベクトル化、ハイブリッド検索
-- 💬 **ストリーミング会話**: 処理状況と生成内容をリアルタイムに表示
-- 🔍 **引用追跡**: 回答の根拠となるドキュメントのソースと関連セグメントを明確に表示
-- 🌍 **多言語対応**: 日本語、中国語、英語のインターフェースおよびAI回答に対応
-- 👁️ **ビジョン機能**: 画像処理をサポートするマルチモーダルモデルに対応
-- ⚙️ **柔軟な設定**: ユーザー独自のAPIキーと推論パラメータのカスタマイズが可能
-- 🎯 **デュアルモード処理**: 高速モード (Tika) + 高精度モード (Vision Pipeline)
-- 💰 **コスト管理**: ユーザーの利用枠(クォータ)管理とコスト見積もり
+- 🔐 **User System**: Complete user registration, login, and permission management
+- 🤖 **Multi-Model Support**: OpenAI-compatible interfaces + Google Gemini native support
+- 📚 **Intelligent Knowledge Base**: Document upload, chunking, vectorization, hybrid search
+- 💬 **Streaming Chat**: Real-time display of processing status and generated content
+- 🔍 **Citation Tracking**: Clear display of source documents and related segments for answers
+- 🌍 **Multi-Language Support**: Japanese, Chinese, and English for interface and AI responses
+- 👁️ **Vision Capabilities**: Supports multimodal models for image processing
+- ⚙️ **Flexible Configuration**: User-specific API keys and inference parameter customization
+- 🎯 **Dual-Mode Processing**: Fast mode (Tika) + High-precision mode (Vision Pipeline)
+- 💰 **Cost Management**: User quota management and cost estimation
 
-## 🏗️ 技術スタック
+## 🏗️ Tech Stack
 
-### フロントエンド
+### Frontend
 
-- **フレームワーク**: React 19 + TypeScript + Vite
-- **スタイリング**: Tailwind CSS
-- **アイコン**: Lucide React
-- **状態管理**: React Context
+- **Framework**: React 19 + TypeScript + Vite
+- **Styling**: Tailwind CSS
+- **Icons**: Lucide React
+- **State Management**: React Context
 
-### バックエンド
+### Backend
 
-- **フレームワーク**: NestJS + TypeScript
-- **AI フレームワーク**: LangChain
-- **データベース**: SQLite (メタデータ) + Elasticsearch (ベクトルストレージ)
-- **ファイル処理**: Apache Tika + Vision Pipeline
-- **認証**: JWT
-- **ドキュメント変換**: LibreOffice + ImageMagick
+- **Framework**: NestJS + TypeScript
+- **AI Framework**: LangChain
+- **Database**: SQLite (metadata) + Elasticsearch (vector storage)
+- **File Processing**: Apache Tika + Vision Pipeline
+- **Authentication**: JWT
+- **Document Conversion**: LibreOffice + ImageMagick
 
-## 🏢 内网部署
+## 🏢 Internal Network Deployment
 
-本系统支持在内网环境中部署。主要修改包括:
+This system supports deployment in internal networks. Main modifications include:
 
-- **外部资源**: 已将 KaTeX CSS 从外部 CDN 移至本地资源
-- **AI模型**: 支持配置内网AI模型服务,无需访问外部API
-- **构建配置**: Dockerfiles 可配置使用内网镜像源
+- **External Resources**: KaTeX CSS moved from external CDN to local resources
+- **AI Models**: Supports configuring internal AI model services without external API access
+- **Build Configuration**: Dockerfiles can be configured to use internal image registries
 
-有关详细配置说明,请参阅 [内网部署指南](INTERNAL_DEPLOYMENT_GUIDE.md)。
+See [Internal Deployment Guide](INTERNAL_DEPLOYMENT_GUIDE.md) for detailed configuration instructions.
 
-## 🚀 クイックスタート
+## 🚀 Quick Start
 
-### 前提条件
+### Prerequisites
 
 - Node.js 18+
 - Yarn
 - Docker & Docker Compose
 
-### 1. プロジェクトのクローン
+### 1. Clone the Project
 
 ```bash
 git clone <repository-url>
 cd simple-kb
 ```
 
-### 2. 依存関係のインストール
+### 2. Install Dependencies
 
 ```bash
 yarn install
 ```
 
-### 3. 基本サービスの起動
+### 3. Start Basic Services
 
 ```bash
 docker-compose up -d elasticsearch tika libreoffice
 ```
 
-### 4. 環境変数の設定
+### 4. Configure Environment Variables
 
 ```bash
-# バックエンドの環境設定
+# Backend environment setup
 cp server/.env.sample server/.env
-# server/.env ファイルを編集(APIキーなどを設定)
+# Edit server/.env file (set API keys, etc.)
 
-# フロントエンドの環境設定
+# Frontend environment setup
 cp web/.env.example web/.env
-# web/.env ファイルを編集(必要に応じてフロントエンド設定を変更)
+# Edit web/.env file (modify frontend settings as needed)
 ```
 
-設定の詳細については、`server/.env.sample` と `web/.env.example` ファイル内のコメントを参照してください。
+See the comments in `server/.env.sample` and `web/.env.example` for detailed configuration.
 
-### 5. 開発サーバーの起動
+### 5. Start Development Server
 
 ```bash
 yarn dev
 ```
 
-<http://localhost:5173> にアクセスして開始してください!
+Access http://localhost:5173 to get started!
 
-## 📖 利用ガイド
+## 📖 User Guide
 
-### 1. ユーザー登録/ログイン
+### 1. User Registration/Login
 
-- 初回利用時はアカウント登録が必要です。
-- 各ユーザーは独立したナレッジベースとモデル設定を持ちます。
+- Account registration is required for first-time use.
+- Each user has their own independent knowledge base and model settings.
 
-### 2. AIモデルの設定
+### 2. AI Model Configuration
 
-- 「モデル管理」からAIモデルを追加します。
-- OpenAI、DeepSeek、Claude などの互換インターフェースをサポートしています。
-- Google Gemini ネイティブインターフェースをサポートしています。
-- LLM、Embedding、Rerank モデルを設定可能です。
+- Add AI models from "Model Management".
+- Supports OpenAI, DeepSeek, Claude and other compatible interfaces.
+- Supports Google Gemini native interface.
+- Configure LLM, Embedding, and Rerank models.
 
-### 3. ドキュメントのアップロード
+### 3. Document Upload
 
-- PDF, Word, PPT, Excel など、多様なフォーマットに対応しています。
-- 高速モード (テキストのみ) または高精度モード (画像・テキスト混合) を選択可能です。
-- ドキュメントのチャンクサイズとオーバーラップを調整可能です。
-- ベクトル化に使用する Embedding モデルを選択します。
+- Supports various formats: PDF, Word, PPT, Excel, etc.
+- Choose between Fast mode (text-only) or High-precision mode (image + text mixed).
+- Adjustable chunk size and overlap for documents.
+- Select embedding model for vectorization.
 
-### 4. インテリジェントQ&Aの開始
+### 4. Start Intelligent Q&A
 
-- アップロードしたドキュメントに基づいて質問応答を行います。
-- 検索と生成のプロセスをリアルタイムで確認できます。
-- 回答の出典や関連ドキュメントの断片を確認できます。
+- Ask questions based on uploaded documents.
+- View search and generation process in real-time.
+- Check answer sources and related document fragments.
 
-## 🔧 設定の説明
+## 🔧 Configuration Guide
 
-### モデル設定
+### Model Settings
 
-- **LLM モデル**: 対話生成に使用 (例: GPT-4, Gemini-1.5-Pro)
-- **Embedding モデル**: ドキュメントのベクトル化に使用 (例: text-embedding-3-small)
-- **Rerank モデル**: 検索結果の再ランキングに使用 (オプション)
+- **LLM Model**: Used for dialogue generation (e.g., GPT-4, Gemini-1.5-Pro)
+- **Embedding Model**: Used for document vectorization (e.g., text-embedding-3-small)
+- **Rerank Model**: Used for re-ranking search results (optional)
 
-### 推論パラメータ
+### Inference Parameters
 
-- **Temperature**: 回答のランダム性を制御 (0-1)
-- **Max Tokens**: 最大出力長
-- **Top K**: 検索するドキュメントセグメントの数
-- **類似度しきい値**: 低い関連性のコンテンツをフィルタリング
+- **Temperature**: Controls answer randomness (0-1)
+- **Max Tokens**: Maximum output length
+- **Top K**: Number of document segments to search
+- **Similarity Threshold**: Filters low-relevance content
 
-## 📁 プロジェクト構造
+## 📁 Project Structure
 
 ```
 simple-kb/
-├── web/                 # フロントエンド・アプリケーション
-│   ├── components/      # React コンポーネント
-│   ├── services/        # API サービス
+├── web/                 # Frontend application
+│   ├── components/      # React components
+│   ├── services/        # API services
 │   ├── contexts/        # React Context
-│   └── utils/          # ユーティリティ関数
-├── server/             # バックエンド・アプリケーション
+│   └── utils/          # Utility functions
+├── server/             # Backend application
 │   ├── src/
-│   │   ├── auth/       # 認証モジュール
-│   │   ├── chat/       # チャットモジュール
-│   │   ├── knowledge-base/ # ナレッジベースモジュール
-│   │   ├── model-config/   # モデル設定モジュール
-│   │   └── user/       # ユーザーモジュール
-│   └── data/           # データストレージ
-├── docs/               # プロジェクトドキュメント
-└── docker-compose.yml  # Docker 設定
+│   │   ├── auth/       # Authentication module
+│   │   ├── chat/       # Chat module
+│   │   ├── knowledge-base/ # Knowledge base module
+│   │   ├── model-config/   # Model configuration module
+│   │   └── user/       # User module
+│   └── data/           # Data storage
+├── docs/               # Project documentation
+└── docker-compose.yml  # Docker configuration
 ```
 
-## 📚 ドキュメント
+## 📚 Documentation
 
-- [システム設計ドキュメント](docs/DESIGN.md)
-- [現在の実装状況](docs/CURRENT_IMPLEMENTATION.md)
-- [API ドキュメント](docs/API.md)
-- [デプロイガイド](docs/DEPLOYMENT.md)
-- [RAG 機能の実装](docs/rag_complete_implementation.md)
+- [System Design Document](docs/DESIGN.md)
+- [Current Implementation Status](docs/CURRENT_IMPLEMENTATION.md)
+- [API Documentation](docs/API.md)
+- [Deployment Guide](docs/DEPLOYMENT.md)
+- [RAG Feature Implementation](docs/rag_complete_implementation.md)
 
-## 🐳 Docker デプロイ
+## 🐳 Docker Deployment
 
-### 開発環境
+### Development Environment
 
 ```bash
-# 基本サービスの起動
+# Start basic services
 docker-compose up -d elasticsearch tika
 
-# ローカル開発
+# Local development
 yarn dev
 ```
 
-### 本番環境
+### Production Environment
 
 ```bash
-# すべてのサービスをビルドして起動
+# Build and start all services
 docker-compose up -d
 ```
 
-## 🤝 貢献ガイド
+## 🤝 Contributing
 
-1. プロジェクトを Fork する
-2. 機能ブランチを作成する (`git checkout -b feature/AmazingFeature`)
-3. 変更をコミットする (`git commit -m 'Add some AmazingFeature'`)
-4. ブランチにプッシュする (`git push origin feature/AmazingFeature`)
-5. Pull Request を開く
+1. Fork the project
+2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
+3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
+4. Push to the branch (`git push origin feature/AmazingFeature`)
+5. Open a Pull Request
 
-## 📄 ライセンス
+## 📄 License
 
-このプロジェクトは MIT ライセンスの下で提供されています。詳細は [LICENSE](LICENSE) ファイルをご覧ください。
+This project is provided under the MIT license. See the [LICENSE](LICENSE) file for details.
 
-## 🙏 謝辞
+## 🙏 Acknowledgments
 
-- [LangChain](https://langchain.com/) - AI アプリケーション開発フレームワーク
-- [NestJS](https://nestjs.com/) - Node.js バックエンドフレームワーク
-- [React](https://react.dev/) - フロントエンド UI フレームワーク
-- [Elasticsearch](https://www.elastic.co/) - 検索および分析エンジン
-- [Apache Tika](https://tika.apache.org/) - ドキュメント解析ツール
+- [LangChain](https://langchain.com/) - AI application development framework
+- [NestJS](https://nestjs.com/) - Node.js backend framework
+- [React](https://react.dev/) - Frontend UI framework
+- [Elasticsearch](https://www.elastic.co/) - Search and analytics engine
+- [Apache Tika](https://tika.apache.org/) - Document parsing tool
 
-## 📞 サポート
+## 📞 Support
 
-質問や提案がある場合は、[Issue](../../issues) を送信するか、メンテナーに連絡してください。
+For questions or suggestions, please submit an [Issue](../../issues) or contact the maintainers.

+ 345 - 0
docs/superpowers/plans/2026-03-17-i18n-japanese-fallback-fix.md

@@ -0,0 +1,345 @@
+# i18n Default Language Configuration Fix Design
+
+> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development to implement this plan.
+
+**Goal:** Add DEFAULT_LANGUAGE configuration in .env file, with English as the hardcoded fallback when not configured.
+
+**Architecture:** Read DEFAULT_LANGUAGE from environment variables in constants.ts, default to 'en' if not set.
+
+**Tech Stack:** NestJS (backend), React (frontend), TypeScript, dotenv
+
+---
+
+## Problem Statement
+
+### Current Issues
+
+1. **No .env Configuration** - Default language is hardcoded in constants.ts
+   - Cannot be changed without code modification
+   - Different environments cannot have different defaults
+
+2. **Fallback Language Issue** (`server/src/i18n/i18n.service.ts:180`)
+   - When an unsupported language is passed, system defaults to Japanese
+   - This causes unexpected Japanese output for users with unsupported locale
+
+3. **Japanese Comments** (`server/src/common/constants.ts:21`)
+   - Comment `// デフォルト言語` should be English per project standards
+
+4. **Hardcoded System Prompts** (`server/src/i18n/i18n.service.ts`)
+   - `getPrompt()` method: Japanese fallback prompts hardcoded in else branch
+   - `getDocumentTitlePrompt()` method: Japanese fallback hardcoded
+   - `getChatTitlePrompt()` method: Japanese fallback hardcoded
+
+### Current State
+
+| Component | Default Language | Source |
+|-----------|-----------------|--------|
+| Backend constants | `'zh'` | Hardcoded |
+| Backend i18n service | `'zh'` | From constants |
+| Frontend context | `'en'` | Hardcoded |
+
+---
+
+## Fix Design
+
+### Decision: Env-Based Configuration with English Default
+
+**Configuration Flow:**
+```
+.env → DEFAULT_LANGUAGE → constants.ts → i18n.service.ts
+         ↓ (if not set)
+       'en' (hardcoded fallback)
+```
+
+**Rationale:**
+- English is the most universally understood international language
+- Safer default for international users
+- Matches frontend default
+- Environment-based config allows per-deployment customization
+
+---
+
+## Files to Modify
+
+### 1. `server/.env.sample`
+
+**Add:** Default language configuration option
+
+```bash
+# Default language for the system (zh, en, ja)
+# If not set, defaults to 'en'
+# DEFAULT_LANGUAGE=en
+```
+
+### 2. `server/src/common/constants.ts`
+
+**Change:** Read from environment with English fallback
+
+```typescript
+// Supported languages
+const SUPPORTED_LANGUAGES = ['zh', 'en', 'ja'] as const;
+
+// Read DEFAULT_LANGUAGE from environment
+function getDefaultLanguage(): typeof SUPPORTED_LANGUAGES[number] {
+  const envValue = process.env.DEFAULT_LANGUAGE?.toLowerCase();
+  
+  // Validate: must be one of supported languages
+  if (envValue && SUPPORTED_LANGUAGES.includes(envValue as typeof SUPPORTED_LANGUAGES[number])) {
+    return envValue as typeof SUPPORTED_LANGUAGES[number];
+  }
+  
+  // Fallback to English if not set or invalid
+  return 'en';
+}
+
+// Default language - read from env, fallback to English
+export const DEFAULT_LANGUAGE = getDefaultLanguage();
+export const DEFAULT_LANGUAGE_FALLBACK = 'en';
+```
+
+### 3. `server/src/i18n/i18n.service.ts`
+
+#### 3.1 Fix getPrompt() fallback (line ~180)
+
+**Current:**
+```typescript
+} else { // 默认为日语,符合プロジェクト要求
+  return type === 'withContext' ? `
+  以下ナレッジベース...
+```
+
+**Proposed:**
+```typescript
+} else { // Fallback to English for unsupported languages
+  return type === 'withContext' ? `
+  Answer the user's question based on the following knowledge base content.
+  ${hasKnowledgeGroup ? `
+  **IMPORTANT**: The user has selected a specific knowledge group. Please answer strictly based on the knowledge base content below. If the relevant information is not found in the knowledge base, explicitly tell the user: "${noMatchMsg}", before providing an answer.
+  ` : ''}
+  Knowledge Base CONTENT:
+  {context}
+
+  Conversation history:
+  {history}
+
+  User question: {question}
+
+  Please answer in English and strictly follow these Markdown formatting guidelines:
+
+  1. **Paragraphs & Structure**:
+     - Use clear paragraph breaks with blank lines between key points
+     - Use headings (## or ###) to organize longer answers
+
+  2. **Text Formatting**:
+     - Use **bold** to emphasize important concepts and keywords
+     - Use lists (- or 1.) to organize multiple points
+     - Use \`code\` to mark technical terms, commands, file names
+
+  3. **Code Display**:
+     - Use code blocks with language specification:
+       \`\`\`python
+       def example():
+           return "example"
+       \`\`\`
+     - Supported languages: python, javascript, typescript, java, bash, sql, etc.
+
+  4. **Diagrams & Charts**:
+     - Use Mermaid syntax for flowcharts, sequence diagrams, etc.:
+       \`\`\`mermaid
+       graph LR
+           A[Start] --> B[Process]
+           B --> C[End]
+       \`\`\`
+     - Use cases: process flows, architecture diagrams, state diagrams, sequence diagrams
+
+  5. **Other Requirements**:
+     - Keep answers concise and clear
+     - Use numbered lists for multi-step processes
+     - Use tables for comparison information (if applicable)
+  ` : `
+  As an intelligent assistant, please answer the user's question.
+
+  Conversation history:
+  {history}
+
+  User question: {question}
+
+  Please answer in English.
+  `;
+}
+```
+
+#### 3.2 Fix getDocumentTitlePrompt() fallback (line ~253)
+
+**Current:**
+```typescript
+} else {
+  return `あなたはドキュメントアナライザー...
+```
+
+**Proposed:**
+```typescript
+} else {
+  return `You are a document analyzer. Read the following text (start of a document) and generate a concise, professional title (max 50 chars).
+Return ONLY the title text. No preamble like "The title is...".
+Language: English
+Text:
+${contentSample}`;
+}
+```
+
+#### 3.3 Fix getChatTitlePrompt() fallback (line ~278)
+
+**Current:**
+```typescript
+} else {
+  return `以下の会話スニペットに基づい...
+```
+
+**Proposed:**
+```typescript
+} else {
+  return `Based on the following conversation snippet, generate a short, descriptive title (max 50 chars) that summarizes the topic.
+Return ONLY the title. No preamble.
+Language: English
+Snippet:
+User: ${userMessage}
+Assistant: ${aiResponse}`;
+}
+```
+
+---
+
+## Task Breakdown
+
+### Task 1: Update .env.sample
+
+**Files:**
+- Modify: `server/.env.sample`
+
+- [ ] **Step 1: Add DEFAULT_LANGUAGE configuration**
+
+```bash
+# Default language for the system (zh, en, ja)
+# If not set, defaults to 'en' (English)
+DEFAULT_LANGUAGE=en
+```
+
+### Task 2: Update constants.ts with env-based config
+
+**Files:**
+- Modify: `server/src/common/constants.ts`
+
+- [ ] **Step 1: Replace hardcoded DEFAULT_LANGUAGE with env-based logic**
+
+```typescript
+// Supported languages
+const SUPPORTED_LANGUAGES = ['zh', 'en', 'ja'] as const;
+
+// Read DEFAULT_LANGUAGE from environment
+function getDefaultLanguage(): typeof SUPPORTED_LANGUAGES[number] {
+  const envValue = process.env.DEFAULT_LANGUAGE?.toLowerCase();
+  
+  // Validate: must be one of supported languages
+  if (envValue && SUPPORTED_LANGUAGES.includes(envValue as typeof SUPPORTED_LANGUAGES[number])) {
+    return envValue as typeof SUPPORTED_LANGUAGES[number];
+  }
+  
+  // Fallback to English if not set or invalid
+  return 'en';
+}
+
+// Default language - read from env, fallback to English
+export const DEFAULT_LANGUAGE = getDefaultLanguage();
+export const DEFAULT_LANGUAGE_FALLBACK = 'en';
+```
+
+**Note:** No new dependencies required - uses simple array validation.
+
+### Task 3: Fix i18n.service.ts getPrompt() Fallback
+
+**Files:**
+- Modify: `server/src/i18n/i18n.service.ts:180-235`
+
+- [ ] **Step 1: Replace Japanese fallback with English**
+
+Replace the entire `else` block (lines ~180-235) with English fallback prompts.
+
+### Task 4: Fix i18n.service.ts getDocumentTitlePrompt() Fallback
+
+**Files:**
+- Modify: `server/src/i18n/i18n.service.ts:253-259`
+
+- [ ] **Step 1: Replace Japanese fallback with English**
+
+Replace the `else` block with English prompt.
+
+### Task 5: Fix i18n.service.ts getChatTitlePrompt() Fallback
+
+**Files:**
+- Modify: `server/src/i18n/i18n.service.ts:278-285`
+
+- [ ] **Step 1: Replace Japanese fallback with English**
+
+Replace the `else` block with English prompt.
+
+### Task 6: Verification
+
+- [ ] **Step 1: Run TypeScript check**
+
+```bash
+cd server && yarn build
+```
+
+Expected: Build succeeds without errors
+
+- [ ] **Step 2: Test env configuration**
+
+```bash
+# Test with DEFAULT_LANGUAGE=zh
+DEFAULT_LANGUAGE=zh yarn start:dev
+
+# Test with DEFAULT_LANGUAGE=en
+DEFAULT_LANGUAGE=en yarn start:dev
+
+# Test with no DEFAULT_LANGUAGE (should default to 'en')
+yarn start:dev
+```
+
+- [ ] **Step 3: Verify fallback behavior**
+
+Test that unsupported language code returns English instead of Japanese.
+
+---
+
+## Expected Result
+
+| Configuration | Before | After |
+|---------------|--------|-------|
+| DEFAULT_LANGUAGE source | Hardcoded `'zh'` | Read from `.env`, fallback to `'en'` |
+| Fallback language | `'ja'` | `'en'` |
+| constants.ts comment | 日本語 | English |
+| getPrompt fallback | 日本語 | English |
+| getDocumentTitlePrompt fallback | 日本語 | English |
+| getChatTitlePrompt fallback | 日本語 | English |
+
+### Configuration Examples
+
+| .env Setting | Result |
+|--------------|--------|
+| `DEFAULT_LANGUAGE=zh` | 中文 |
+| `DEFAULT_LANGUAGE=en` | English |
+| `DEFAULT_LANGUAGE=ja` | 日本語 |
+| (not set) | English (default) |
+| `DEFAULT_LANGUAGE=invalid` | English (fallback) |
+
+---
+
+## Risk & Mitigation
+
+**Low Risk:** Changes are configuration-based with safe defaults.
+
+**Mitigation:**
+- Hardcoded `'en'` fallback ensures safe behavior even if env is misconfigured
+- Keep 'zh', 'en', 'ja' as supported languages
+- Japanese ('ja') still fully supported when explicitly configured

+ 22 - 18
server/.env.sample

@@ -1,12 +1,12 @@
 PORT=3001
-# 重要:在生产环境中必须更改以下设置
-# 数据库路径
+# IMPORTANT: Must change the following in production environment
+# Database path
 DATABASE_PATH=./data/metadata.db
 
-# 服务主机配置(生产环境请使用实际服务器地址)
-ELASTICSEARCH_HOST=http://127.0.0.1:9200    # 生产环境请更改
-TIKA_HOST=http://127.0.0.1:9998            # 生产环境请更改
-LIBREOFFICE_URL=http://127.0.0.1:8100       # 生产环境请更改
+# Service host configuration (use actual server address in production)
+ELASTICSEARCH_HOST=http://127.0.0.1:9200    # Change for production
+TIKA_HOST=http://127.0.0.1:9998            # Change for production
+LIBREOFFICE_URL=http://127.0.0.1:8100       # Change for production
 JWT_SECRET=your-super-secure-jwt-secret-key-change-it-in-production
 
 # File Upload Configuration
@@ -15,30 +15,34 @@ MAX_FILE_SIZE=104857600
 TEMP_DIR=./temp
 
 # Vector Dimensions Configuration
-# 埋め込みモデルの出力次元数と一致させる必要があります
-# 一般的な値: 2560 (text-embedding-3-large), 1536 (text-embedding-3-small), 2048 (カスタム)
+# Must match the output dimensions of your embedding model
+# Common values: 2560 (text-embedding-3-large), 1536 (text-embedding-3-small), 2048 (custom)
 DEFAULT_VECTOR_DIMENSIONS=2048
 
 # Chunk Size Limits Configuration
-# チャンクサイズの上限 (tokens) - 環境変数による制限(優先度最高)
-# 使用する埋め込みモデルに合わせて設定してください
+# Maximum chunk size (tokens) - env var limit (highest priority)
+# Set according to your embedding model
 # OpenAI text-embedding-3-large: 8191
 # OpenAI text-embedding-3-small: 8191
 # Google Gemini embedding-001: 2048
 MAX_CHUNK_SIZE=8191
 
-# チャンク重なり(オーバーラップ)の上限 (tokens) - 環境変数による制限
-# チャンクサイズの 10-20% を推奨します
+# Maximum chunk overlap (tokens) - env var limit
+# Recommended: 10-20% of chunk size
 MAX_OVERLAP_SIZE=200
 
 # Memory Management Configuration
-# メモリ使用量の上限 (MB)。この値を超えると待機や強制GCがトリガーされます
+# Default language for the system (zh, en, ja)
+# If not set, defaults to 'en'
+DEFAULT_LANGUAGE=en
+
+# Memory usage limit (MB). Triggers wait or forced GC when exceeded
 MAX_MEMORY_USAGE_MB=1024
-# バッチ処理サイズ (チャンク数)
+# Batch processing size (chunk count)
 CHUNK_BATCH_SIZE=100
-# 強制GCのしきい値 (MB)
+# Forced GC threshold (MB)
 GC_THRESHOLD_MB=800
 
-# 前端設定
-# ALLOWED_HOSTS - API 接続を許可するホストリスト(カンマ区切り)
-# フロントエンドの .env ファイルで REACT_APP_ALLOWED_HOSTS として設定
+# Frontend settings
+# ALLOWED_HOSTS - Comma-separated list of hosts allowed for API connection
+# Set in frontend .env file as REACT_APP_ALLOWED_HOSTS

+ 52 - 52
server/README.md

@@ -1,113 +1,113 @@
-# Simple Knowledge Base - バックエンドサービス (Server)
+# Simple Knowledge Base - Backend Service (Server)
 
-[NestJS](https://nestjs.com/) フレームワークで構築された RAG (検索拡張生成) ナレッジベースのバックエンドシステムです。ファイルの解析、ベクトルインデックス、ハイブリッド検索、およびマルチモデル管理機能を提供します。
+A RAG (Retrieval-Augmented Generation) knowledge base backend system built with the [NestJS](https://nestjs.com/) framework. Provides file parsing, vector indexing, hybrid search, and multi-model management features.
 
-## 🌟 主な特徴
+## 🌟 Key Features
 
-- **インテリジェントなドキュメント処理**: [Apache Tika](https://tika.apache.org/) を統合し、PDF、Word、Markdown、TXT など多様な形式からのテキスト抽出をサポート。
-- **効率的なベクトル検索**: [Elasticsearch](https://www.elastic.co/) をベクトルデータベースとして使用。KNN ベクトル検索と全文検索を組み合わせたハイブリッド検索 (Hybrid Search) をサポート。
-- **柔軟な RAG エンジン**: LangChain をベースに構築。チャンク分割ルール (Chunking) や再ランキング (Rerank) のカスタマイズが可能。
-- **マルチモデルプロバイダー**: OpenAI、Google Gemini、およびローカルデプロイの LLM モデルへの動的な接続をサポート。
-- **安全な管理機能**: JWT による認証とユーザー権限管理機能を内蔵。
+- **Intelligent Document Processing**: Integrated with [Apache Tika](https://tika.apache.org/) to support text extraction from various formats including PDF, Word, Markdown, and TXT.
+- **Efficient Vector Search**: Uses [Elasticsearch](https://www.elastic.co/) as the vector database. Supports hybrid search combining KNN vector search and full-text search.
+- **Flexible RAG Engine**: Built on LangChain. Supports customization of chunking rules and reranking.
+- **Multi-Model Provider**: Supports dynamic connection to OpenAI, Google Gemini, and locally deployed LLM models.
+- **Secure Management**: Built-in JWT authentication and user permission management.
 
-## 🛠️ 技術スタック
+## 🛠️ Tech Stack
 
-- **フレームワーク**: NestJS (TypeScript)
-- **データベース**: SQLite (TypeORM)
-- **検索エンジン**: Elasticsearch 8.x/9.x
-- **AI フレームワーク**: LangChain
-- **ライブラリ**: RxJS, Class-Validator
+- **Framework**: NestJS (TypeScript)
+- **Database**: SQLite (TypeORM)
+- **Search Engine**: Elasticsearch 8.x/9.x
+- **AI Framework**: LangChain
+- **Libraries**: RxJS, Class-Validator
 
-## 📋 前提条件
+## 📋 Prerequisites
 
-プロジェクトを実行する前に、以下の環境が整っていることを確認してください:
+Before running the project, ensure you have the following environment set up:
 
-- [Node.js](https://nodejs.org/) (v18 以上推奨)
+- [Node.js](https://nodejs.org/) (v18 or higher recommended)
 - [Yarn](https://yarnpkg.com/)
-- [Docker](https://www.docker.com/) & Docker Compose (インフラ実行用)
+- [Docker](https://www.docker.com/) & Docker Compose (for infrastructure)
 
-## 🚀 クイックスタート
+## 🚀 Quick Start
 
-### 1. インフラストラクチャの起動
+### 1. Start Infrastructure
 
-プロジェクトのルートディレクトリ (`simple-kb/`) にある `docker-compose.yml` ファイルを使用して、Elasticsearch と Tika をクイック起動します。
+Use the `docker-compose.yml` file in the project root (`simple-kb/`) to quickly start Elasticsearch and Tika.
 
 ```bash
-# プロジェクトのルートディレクトリで実行
+# Run from project root directory
 docker-compose up -d
 ```
 
-起動成功後:
+After successful startup:
 
-- **Elasticsearch**: ポート `19200` をリスン (コンテナの 9200 ポートをマッピング)
-- **Tika**: ポート `9998` をリスン
+- **Elasticsearch**: Listens on port `19200` (maps container's 9200 port)
+- **Tika**: Listens on port `9998`
 
-### 2. 依存関係のインストール
+### 2. Install Dependencies
 
-`server` ディレクトリに移動し、パッケージをインストールします:
+Navigate to the `server` directory and install packages:
 
 ```bash
 cd server
 yarn install
 ```
 
-### 3. 環境設定
+### 3. Environment Configuration
 
-プロジェクトは、基本設定を環境変数のファイルに基づきます。設定(特に Elasticsearch のアドレス)が正しいことを確認してください:
+The project uses environment variables for configuration. Make sure the settings are correct (especially Elasticsearch address):
 
 ```env
-# データベースのパス
+# Database path
 DATABASE_PATH=server/data/metadata.db
 
-# JWT シークレット
+# JWT secret
 JWT_SECRET=your_secure_secret
 
-# Elasticsearch 設定 (docker-compose のポートと一致させてください)
+# Elasticsearch settings (match docker-compose ports)
 ELASTICSEARCH_HOST=http://localhost:19200
 ELASTICSEARCH_INDEX=knowledge_base
 
-# Tika 設定
+# Tika settings
 TIKA_HOST=http://localhost:9998
 
-# ファイルアップロードの保存パス
+# File upload storage path
 UPLOAD_FILE_PATH=./uploads
 ```
 
-### 4. サービスの起動
+### 4. Start Services
 
 ```bash
-# 開発モード (推奨。ホットリロード対応)
+# Development mode (recommended, with hot reload)
 yarn run start:dev
 
-# 本番モードでのビルドと実行
+# Build and run in production mode
 yarn build
 yarn run start:prod
 ```
 
-バックエンドサービスはデフォルトで **<http://localhost:13000>** で実行され、API プレフィックスは `/api` です。
+The backend service runs on **http://localhost:13000** by default, with API prefix `/api`.
 
-## 🧪 テスト
+## 🧪 Testing
 
 ```bash
-# ユニットテスト
+# Unit tests
 yarn run test
 
-# E2E テスト
+# E2E tests
 yarn run test:e2e
 ```
 
-## ⚠️ 注意事項とヒント
+## ⚠️ Notes and Tips
 
-1. **データベースの初期化**:
-   - 初回実行時に、TypeORM は `server/data/` ディレクトリ配下に `metadata.db` (または設定された DB) を自動的に作成します。
-   - 開発環境では `synchronize: true` により、テーブル構造が自動同期されます。
+1. **Database Initialization**:
+   - On first run, TypeORM automatically creates `metadata.db` (or configured DB) under the `server/data/` directory.
+   - In development mode, with `synchronize: true`, table structures are auto-synced.
 
-2. **Elasticsearch への接続**:
-   - `Connection refused` エラーが発生した場合は、Docker コンテナが正常に動作しているか確認してください (`docker ps`)。
-   - サービス起動時に、`knowledge_base` という名前のインデックスが自動的に検出・作成されます。
+2. **Elasticsearch Connection**:
+   - If you encounter a `Connection refused` error, check if Docker containers are running properly (`docker ps`).
+   - On service startup, an index named `knowledge_base` is automatically detected and created.
 
-3. **デフォルトのアカウント**:
-   - データベースをリセットした場合は、新規ユーザー登録を行うか、既存の管理データを参照してください。通常はフロントエンドの登録機能を使用して最初のユーザーを作成することをお勧めします。
+3. **Default Account**:
+   - If you reset the database, either register a new user or refer to existing admin data. It's recommended to use the frontend registration feature to create the first user.
 
-4. **ファイルの解析**:
-   - 大容量のファイルをアップロードした場合、Tika による解析に数秒かかることがあります。フロントエンドの処理ステータスを確認しながらお待ちください。
+4. **File Parsing**:
+   - When uploading large files, parsing by Tika may take a few seconds. Please wait while checking the frontend processing status.

+ 4 - 4
server/src/chat/chat.service.ts

@@ -375,7 +375,7 @@ ${instruction}`;
     }
   }
 
-  private buildContext(results: any[], language: string = 'ja'): string {
+  private buildContext(results: any[], language: string = DEFAULT_LANGUAGE): string {
     return results
       .map(
         (result, index) =>
@@ -386,7 +386,7 @@ ${instruction}`;
 
   private formatHistory(
     history: ChatMessage[],
-    userLanguage: string = 'ja',
+    userLanguage: string = DEFAULT_LANGUAGE,
   ): string {
     const userLabel = this.i18nService.getMessage('userLabel', userLanguage);
     const assistantLabel = this.i18nService.getMessage('assistantLabel', userLanguage);
@@ -440,7 +440,7 @@ ${instruction}`;
         type: 'LLM (Simple)',
         model: `${config.name} (${config.modelId})`,
         user: userId
-      }, 'ja'));
+      }, DEFAULT_LANGUAGE));
       const settings = await this.tenantService.getSettings(tenantId || 'default');
       const llm = new ChatOpenAI({
         apiKey: config.apiKey || 'ollama',
@@ -483,7 +483,7 @@ ${instruction}`;
 
       // Get language from user settings
       const userSettings = await this.userSettingService.getByUser(userId);
-      const language = userSettings?.language || 'ja';
+      const language = userSettings?.language || DEFAULT_LANGUAGE;
 
       // Build prompt
       const prompt = this.i18nService.getChatTitlePrompt(language, userMessage, aiResponse);

+ 25 - 2
server/src/common/constants.ts

@@ -17,8 +17,31 @@ export const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
 
 export const DEFAULT_MAX_BATCH_SIZE = 2048;
 
-// デフォルト言語
-export const DEFAULT_LANGUAGE = 'zh';
+// Supported languages
+const SUPPORTED_LANGUAGES = ['zh', 'en', 'ja'] as const;
+
+/**
+ * Get the default language from the environment variable.
+ * Fallback to 'en' (English) if not set or invalid.
+ */
+function getDefaultLanguage(): (typeof SUPPORTED_LANGUAGES)[number] {
+  const envValue = process.env.DEFAULT_LANGUAGE?.toLowerCase();
+
+  // Validate: must be one of supported languages
+  if (
+    envValue &&
+    SUPPORTED_LANGUAGES.includes(envValue as (typeof SUPPORTED_LANGUAGES)[number])
+  ) {
+    return envValue as (typeof SUPPORTED_LANGUAGES)[number];
+  }
+
+  // Fallback to English if not set or invalid
+  return 'en';
+}
+
+// Default language - read from env, fallback to English
+export const DEFAULT_LANGUAGE = getDefaultLanguage();
+export const DEFAULT_LANGUAGE_FALLBACK = 'en';
 
 // システム全体の共通テナントID(シードデータetc.で使用)
 export const GLOBAL_TENANT_ID = '00000000-0000-0000-0000-000000000000';

+ 1 - 1
server/src/defaults.ts

@@ -24,5 +24,5 @@ export const DEFAULT_SETTINGS: AppSettings = {
   chunkSize: 1000,
   chunkOverlap: 100,
 
-  language: 'ja',
+  language: 'zh',
 };

+ 1 - 1
server/src/elasticsearch/elasticsearch.service.ts

@@ -297,7 +297,7 @@ export class ElasticsearchService implements OnModuleInit {
     const fileIds = explicitFileIds;
 
     if (fileIds && fileIds.length === 0) {
-      this.logger.log('検索対象ファイルが0件for、検索をスキップします');
+      this.logger.log('No search target files (count=0), skipping search');
       return [];
     }
 

+ 73 - 65
server/src/i18n/i18n.service.ts

@@ -177,61 +177,69 @@ User question: {question}
 
 Please answer in English.
 `;
-    } else { // 默认为日语,符合项目要求
-      return type === 'withContext' ? `
-以下のナレッジベースの内容に基づいてユーザーの質問に答えてくplease。
-${hasKnowledgeGroup ? `
-**重要**: ユーザーが特定の知識グループを選択しました。以下のナレッジベースの内容に厳密に基づいて回答please。ナレッジベースに関連情報がない場合は、「${noMatchMsg}」とユーザーに明示的に伝えてfrom、回答を提供please。
-` : ''}
-ナレッジベースの内容:
-{context}
-
-会話履歴:
-{history}
-
-ユーザーの質問:{question}
-
-日本語で回答please。以下の Markdown 書式要件に厳密に従ってくplease:
-
-1. **段落と構造**:
-   - 明確な段落分けを使用し、要点間に空行を入れる
-   - 長い回答には見出し(## または ###)を使用
-
-2. **テキスト書式**:
-   - 重要な概念やキーワードを強調するために **太字** を使用
-   - 複数のポイントを整理するためにリスト(- または 1.)を使用
-   - 技術用語、コマンド、ファイル名をマークするために \`コード\` を使用
-
-3. **コード表示**:
-   - 言語を指定してコードブロックを使用:
-     \`\`\`python
-     def example():
-         return "例"
-     \`\`\`
-   - 対応言語:python, javascript, typescript, java, bash, sql etc.
-
-4. **図表とチャート**:
-   - フローチャート、シーケンス図etc.に Mermaid 構文を使用:
-     \`\`\`mermaid
-     graph LR
-         A[開始] --> B[処理]
-         B --> C[終了]
-     \`\`\`
-   - 使用例:プロセスフロー、アーキテクチャ図、状態図、シーケンス図
-
-5. **その他の要件**:
-   - 簡潔で明確な回答を心がける
-   - 複数のステップがある場合は番号付きリストを使用
-   - 比較情報には表を使用(該当する場合)
-` : `
-インテリジェントアシスタントとして、ユーザーの質問に答えてくplease。
-
-会話履歴:
-{history}
-
-ユーザーの質問:{question}
-      日本語で回答please。
-`;
+    } else {
+      // Fallback to English for unsupported languages
+      return type === 'withContext'
+        ? `
+  Answer the user's question based on the following knowledge base content.
+  ${
+    hasKnowledgeGroup
+      ? `
+  **IMPORTANT**: The user has selected a specific knowledge group. Please answer strictly based on the knowledge base content below. If the relevant information is not found in the knowledge base, explicitly tell the user: "${noMatchMsg}", before providing an answer.
+  `
+      : ''
+  }
+  Knowledge Base CONTENT:
+  {context}
+
+  Conversation history:
+  {history}
+
+  User question: {question}
+
+  Please answer in English and strictly follow these Markdown formatting guidelines:
+
+  1. **Paragraphs & Structure**:
+     - Use clear paragraph breaks with blank lines between key points
+     - Use headings (## or ###) to organize longer answers
+
+  2. **Text Formatting**:
+     - Use **bold** to emphasize important concepts and keywords
+     - Use lists (- or 1.) to organize multiple points
+     - Use \`code\` to mark technical terms, commands, file names
+
+  3. **Code Display**:
+     - Use code blocks with language specification:
+       \`\`\`python
+       def example():
+           return "example"
+       \`\`\`
+     - Supported languages: python, javascript, typescript, java, bash, sql, etc.
+
+  4. **Diagrams & Charts**:
+     - Use Mermaid syntax for flowcharts, sequence diagrams, etc.:
+       \`\`\`mermaid
+       graph LR
+           A[Start] --> B[Process]
+           B --> C[End]
+       \`\`\`
+     - Use cases: process flows, architecture diagrams, state diagrams, sequence diagrams
+
+  5. **Other Requirements**:
+     - Keep answers concise and clear
+     - Use numbered lists for multi-step processes
+     - Use tables for comparison information (if applicable)
+  `
+        : `
+  As an intelligent assistant, please answer the user's question.
+
+  Conversation history:
+  {history}
+
+  User question: {question}
+
+  Please answer in English.
+  `;
     }
   }
 
@@ -251,10 +259,10 @@ Language: English
 Text:
 ${contentSample}`;
     } else {
-      return `あなたはドキュメントアナライザー.以下のテキスト(ドキュメントの冒頭部分)を読み、簡潔でプロフェッショナルなタイトル(最大50文字)を生成please。
-タイトルテキストのみを返please。説明文や前置き(例:「タイトルは:」)は含めないでくplease。
-言語:日本語
-テキスト:
+      return `You are a document analyzer. Read the following text (start of a document) and generate a concise, professional title (max 50 chars).
+Return ONLY the title text. No preamble like "The title is...".
+Language: English
+Text:
 ${contentSample}`;
     }
   }
@@ -276,12 +284,12 @@ Snippet:
 User: ${userMessage}
 Assistant: ${aiResponse}`;
     } else {
-      return `以下の会話スニペットに基づいて、トピックを要約する短く説明的なタイトル(最大50文字)を生成please。
-タイトルのみを返please。前置きは不要.
-言語:日本語
-スニペット:
-ユーザー: ${userMessage}
-アシスタント: ${aiResponse}`;
+      return `Based on the following conversation snippet, generate a short, descriptive title (max 50 chars) that summarizes the topic.
+Return ONLY the title. No preamble.
+Language: English
+Snippet:
+User: ${userMessage}
+Assistant: ${aiResponse}`;
     }
   }
 }

+ 13 - 13
server/src/i18n/messages.ts

@@ -78,9 +78,9 @@ export const errorMessages = {
     elasticsearchHostRequired: 'ELASTICSEARCH_HOST 环境变量未设置',
   },
   ja: {
-    noEmbeddingModel: '先にシステム設定で埋め込みモデルを設定please',
+    noEmbeddingModel: '先にシステム設定で埋め込みモデルを設定してください',
     searchFailed: 'ナレッジベース検索に失敗しました。一般的な知識に基づいて回答します...',
-    invalidApiKey: 'APIキーが無効is',
+    invalidApiKey: 'APIキーが無効です',
     fileNotFound: 'ファイルが見つかりません',
     insufficientQuota: '利用枠が不足しています',
     modelNotConfigured: 'モデルが設定されていません',
@@ -89,7 +89,7 @@ export const errorMessages = {
     uploadNoFile: 'ファイルがアップロードされていません',
     uploadSizeExceeded: 'ファイルサイズが制限: {size}, 最大許容: {max}',
     uploadModelRequired: '埋め込みモデルを選択する必要があります',
-    uploadTypeUnsupported: 'サポートされていないファイル形式is: {type}',
+    uploadTypeUnsupported: 'サポートされていないファイル形式です: {type}',
     chunkOverflow: 'チャンクサイズ {size} が上限 {max} ({reason}) を超えています。自動調整されました',
     chunkUnderflow: 'チャンクサイズ {size} が最小値 {min} 未満.自動調整されました',
     overlapOverflow: '重なりサイズ {size} が上限 {max} を超えています。自動調整されました',
@@ -97,15 +97,15 @@ export const errorMessages = {
     overlapRatioExceeded: '重なりサイズ {size} がチャンクサイズの50% ({max}) を超えています。自動調整されました',
     batchOverflowWarning: 'バッチ処理のオーバーフローを避けるため、チャンクサイズを {safeSize} 以下にすることをお勧めします (現在: {size}, モデル制限の {percent}%)',
     estimatedChunkCountExcessive: '推定チャンク数が多すぎます ({count})。処理に時間がかかる可能性があります',
-    contentAndTitleRequired: '内容とタイトルは必須is',
+    contentAndTitleRequired: '内容とタイトルは必須です',
     embeddingModelNotFound: '埋め込みモデル {id} が見つかりません、またはタイプが embedding ではありません',
     ocrFailed: 'テキストの抽出に失敗しました: {message}',
     noImageUploaded: '画像がアップロードされていません',
     adminOnlyViewList: '管理者のみがユーザーリストを表示できます',
-    passwordsRequired: '現在のパスワードと新しいパスワードは必須is',
+    passwordsRequired: '現在のパスワードと新しいパスワードは必須です',
     newPasswordMinLength: '新しいパスワードは少なくとも6文字以上である必要があります',
     adminOnlyCreateUser: '管理者のみがユーザーを作成できます',
-    usernamePasswordRequired: 'ユーザー名とパスワードは必須is',
+    usernamePasswordRequired: 'ユーザー名とパスワードは必須です',
     passwordMinLength: 'パスワードは少なくとも6文字以上である必要があります',
     adminOnlyUpdateUser: '管理者のみがユーザー情報を更新できます',
     userNotFound: 'ユーザーが見つかりません',
@@ -120,18 +120,18 @@ export const errorMessages = {
     noteNotFound: 'ノートが見つかりません: {id}',
     knowledgeGroupNotFound: 'ナレッジグループが見つかりません: {id}',
     accessDeniedNoToken: 'アクセス不許可:トークンがありません',
-    invalidToken: '無効なトークンis',
+    invalidToken: '無効なトークンです',
     pdfFileNotFound: 'PDF ファイルが見つかりません',
     pdfFileEmpty: 'PDF ファイルが空.変換に失敗した可能性があります',
     pdfConversionFailed: 'PDF ファイルが存在しないか、変換に失敗しました',
-    pdfConversionFailedDetail: 'PDF 変換に失敗しました(ファイル ID: {id})。後でもう一度お試しくplease',
+    pdfConversionFailedDetail: 'PDF 変換に失敗しました(ファイル ID: {id})。後でもう一度お試しください',
     pdfPreviewNotSupported: 'このファイル形式はプレビューをサポートしていません',
     pdfServiceUnavailable: 'PDF サービスを利用できません: {message}',
     pageImageNotFound: 'ページ画像が見つかりません',
     pdfPageImageFailed: 'PDF ページの画像を取得できませんでした',
     someGroupsNotFound: '一部のグループが存在しません',
-    promptRequired: 'プロンプトは必須is',
-    addLLMConfig: 'システム設定で LLM モデルを追加please',
+    promptRequired: 'プロンプトは必須です',
+    addLLMConfig: 'システム設定で LLM モデルを追加してください',
     visionAnalysisFailed: 'ビジョン分析に失敗しました: {message}',
     visionSystemPrompt: 'あなたはプロフェッショナルなドキュメント分析アシスタントです。このドキュメント画像を分析し、以下の要求に従ってJSON形式で返してください:\n\n1. すべての可読テキストを抽出(読み順で、段落と書式を維持)\n2. 画像/グラフ/テーブルを識別(内容、意味、役割を説明)\n3. ページレイアウトを分析(テキストのみ/テキストと画像混在/テーブル/グラフなど)\n4. 分析品質を評価 (0-1)\n\nレスポンス形式:\n{\n  "text": "完全なテキスト内容",\n  "images": [\n    {"type": "グラフタイプ", "description": "詳細説明", "position": 1}\n  ],\n  "layout": "レイアウト説明",\n  "confidence": 0.95\n}',
     retryMechanismError: '再試行メカニズムの異常',
@@ -145,8 +145,8 @@ export const errorMessages = {
     searchHistoryDeleted: '検索履歴が削除されました',
     jwtSecretRequired: 'JWT_SECRET 環境変数が設定されていません',
     tenantNotFound: 'テナントが見つかりません',
-    usernameRequired: 'ユーザー名は必須is',
-    passwordRequiredForNewUser: '新しいユーザー {username} のパスワードが必要is',
+    usernameRequired: 'ユーザー名は必須です',
+    passwordRequiredForNewUser: '新しいユーザー {username} のパスワードが必要です',
     importTaskNotFound: 'インポートタスクが見つかりません',
     sourcePathNotFound: 'ソースパスが見つかりません: {path}',
     targetGroupRequired: 'ターゲットグループが指定されていません',
@@ -262,7 +262,7 @@ export const logMessages = {
     batchSizeAdjusted: '批量大小从 {old} 调整为 {new} (模型限制: {limit})',
     dimensionMismatch: '模型 {id} 维度不匹配: 预期 {expected}, 实际 {actual}',
     searchMetadataFailed: '为用户 {userId} 搜索知识库失败',
-    extractedTextTooLarge: '抽出されたテキストが大きいです: {size}MB',
+    extractedTextTooLarge: '提取的文本内容过大: {size}MB',
     preciseModeUnsupported: '格式 {ext} 不支持精密模式,回退到快速模式',
     visionModelNotConfiguredFallback: '未配置视觉模型,回退到快速模式',
     visionModelInvalidFallback: '视觉模型配置无效,回退到快速模式',

+ 2 - 1
server/src/knowledge-base/knowledge-base.service.ts

@@ -1,5 +1,6 @@
 import { Injectable, Logger, NotFoundException, Inject, forwardRef } from '@nestjs/common';
 import { ConfigService } from '@nestjs/config';
+import { DEFAULT_LANGUAGE } from '../common/constants';
 import { I18nService } from '../i18n/i18n.service';
 import { InjectRepository } from '@nestjs/typeorm';
 import { Repository, In } from 'typeorm';
@@ -269,7 +270,7 @@ export class KnowledgeBaseService {
       const ragPrompt = this.ragService.buildRagPrompt(
         query,
         ragResults,
-        settings.language || 'ja',
+        settings.language || DEFAULT_LANGUAGE,
       );
 
       const result = {

+ 3 - 2
server/src/rag/rag.service.ts

@@ -9,6 +9,7 @@ import { TenantService } from '../tenant/tenant.service';
 import { ChatOpenAI } from '@langchain/openai';
 import { ModelConfig } from '../types';
 import { UserSettingService } from '../user/user-setting.service';
+import { DEFAULT_LANGUAGE } from '../common/constants';
 
 export interface RagSearchResult {
   content: string;
@@ -206,9 +207,9 @@ export class RagService {
   buildRagPrompt(
     query: string,
     searchResults: RagSearchResult[],
-    language: string = 'ja',
+    language: string = DEFAULT_LANGUAGE,
   ): string {
-    const lang = language || 'ja';
+    const lang = language || DEFAULT_LANGUAGE;
 
     // Build context
     let context = '';

+ 3 - 3
translation_map.json

@@ -1,4 +1,4 @@
 {
-  "      `💰 推定コスト: $${estimatedCost.toFixed(2)}, 推定時間: ${duration.toFixed(1)}s`\n    )": "      `💰 Estimated cost: $${estimatedCost.toFixed(2)}, Estimated time: ${duration.toFixed(1)}s`\n    )",
-  "    this.logger.log(`💰 推定コスト: $${estimatedCost.toFixed(2)}, 推定時間: ${duration.toFixed(1)}s`);": "    this.logger.log(`💰 Estimated cost: $${estimatedCost.toFixed(2)}, Estimated time: ${duration.toFixed(1)}s`);"
-}
+  "      `💰 Estimated cost: $${estimatedCost.toFixed(2)}, Estimated time: ${duration.toFixed(1)}s`\n    )": "      `💰 Estimated cost: $${estimatedCost.toFixed(2)}, Estimated time: ${duration.toFixed(1)}s`\n    )",
+  "    this.logger.log(`💰 Estimated cost: $${estimatedCost.toFixed(2)}, Estimated time: ${duration.toFixed(1)}s`);": "    this.logger.log(`💰 Estimated cost: $${estimatedCost.toFixed(2)}, Estimated time: ${duration.toFixed(1)}s`);"
+}

+ 6 - 4
web/.env

@@ -1,6 +1,8 @@
+# API base URL (relative path to backend)
 VITE_API_BASE_URL=/api
-# 許��れ�ホストリスト�カンマ区切り
-# ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0
+
+# Allowed hosts for API connection (comma-separated)
+# Example: VITE_ALLOWED_HOSTS=localhost,127.0.0.1,example.com
 VITE_ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0
 
 # Vite server configuration
@@ -8,5 +10,5 @@ VITE_PORT=13001
 VITE_HOST=0.0.0.0
 VITE_BACKEND_URL=http://localhost:3001
 
-# ĬÈÏϵͳÓïÑÔ£¨zh, en, ja£©
-VITE_DEFAULT_LANGUAGE=en
+# Interface language (zh, en, ja)
+VITE_DEFAULT_LANGUAGE=zh

+ 4 - 4
web/.env.example

@@ -1,8 +1,8 @@
-# API蝓コ譛ャURL�医ョ繝輔か繝ォ繝医�逶ク蟇セ繝代せ縺ァ繝舌ャ繧ッ繧ィ繝ウ繝峨↓謗・邯夲シ�
+# API base URL (relative path to backend)
 VITE_API_BASE_URL=/api
 
-# API謗・邯壹r險ア蜿ッ縺吶k繝帙せ繝医Μ繧ケ繝茨シ医き繝ウ繝槫玄蛻�j��
-# 萓�: VITE_ALLOWED_HOSTS=localhost,127.0.0.1,example.com
+# Allowed hosts for API connection (comma-separated)
+# Example: VITE_ALLOWED_HOSTS=localhost,127.0.0.1,example.com
 VITE_ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0
 
 # Vite server configuration
@@ -10,5 +10,5 @@ VITE_PORT=13001
 VITE_HOST=0.0.0.0
 VITE_BACKEND_URL=http://localhost:3001
 
-# トャネママオヘウモ�ヤ」ィzh, en, ja」ゥ
+# Interface language (zh, en, ja)
 VITE_DEFAULT_LANGUAGE=en