Files
aurak/docs/superpowers/plans/2026-03-17-i18n-japanese-fallback-fix.md
T
Developer 0a9588abb7 feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params)
- Add findByTemplateId method to service
- Add GET /by-template/:templateId endpoint to controller
- Service already includes CRUD for QuestionBank and QuestionBankItem
2026-04-23 17:19:11 +08:00

346 lines
9.4 KiB
Markdown

# 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