| name | enforcing-user-language-consistency |
| description | Ensures userLanguage/preferredLanguage is passed through ALL AI-related code paths. Use when modifying UI/UX, agents, RAG, tool factories, or any AI core code. Prevents translation inconsistencies. |
Enforcing User Language Consistency
MANDATORY when modifying any code that touches:
- UI/UX components that display AI feedback
- Agent prompts or CoT instructions
- RAG context generation
- Tool factories
- Evaluation output
- Any AI-generated text shown to users
The Problem
User language (preferredLanguage) must flow through the ENTIRE call chain:
API Route → Tool Factory → Tool Implementation → Agent → RAG → Response
If ANY step loses the language context, users get mixed-language responses (e.g., German explanation for a Greek user).
Language Flow Architecture
Source of Truth
// apps/web-app/app/api/chat-agentkit/route.ts
const preferredLanguage = getUserNativeLanguage({
dbNativeLanguage, // 1st priority: DB stored preference
browserLanguage, // 2nd priority: Accept-Language header
defaultLanguage: "English"
});
Required Flow
┌─────────────────────────────────────────────────────────────────┐
│ API Route (route.ts) │
│ - Calculates preferredLanguage from DB/browser │
│ - Passes to ALL tool factories │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Tool Factory (tool-factories.ts) │
│ - Captures userNativeLanguage in closure │
│ - Uses as fallback when agent doesn't pass it │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Tool Implementation (evaluate-text.ts, etc.) │
│ - Receives userLanguage in params │
│ - Passes to Agent context │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Agents (*-agent-cot.ts) │
│ - Receives userLanguage in analyze() method │
│ - Uses in prompt: "Feedback in ${feedbackLang}" │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ RAG Context (hybrid-context.ts) │
│ - Receives userNativeLanguage in options │
│ - May affect content retrieval/filtering │
└─────────────────────────────────────────────────────────────────┘
Checklist When Modifying AI Code
1. API Route Changes
// ALWAYS pass preferredLanguage to tool factories
const toolInstance = createSomeTool(
userId,
supabase,
preferredLanguage // ← REQUIRED
);
2. New Tool Factory
export function createNewTool(
userId: string,
supabase: SupabaseClient,
userNativeLanguage?: string // ← REQUIRED PARAMETER
) {
// Capture in closure for fallback
const capturedLanguage = userNativeLanguage || "English";
return tool({
parameters: z.object({
userLanguage: z.string().optional() // ← Agent can override
}),
execute: async (params) => {
// Use captured language as fallback
const effectiveLanguage = params.userLanguage || capturedLanguage;
// ... pass effectiveLanguage to implementation
}
});
}
3. New Agent Method
async analyze(
text: string,
userLanguage?: string, // ← REQUIRED PARAMETER
context?: AgentEvaluationContext
): Promise<any> {
const feedbackLang = userLanguage || "German";
const prompt = `
...
"feedback": "... in ${feedbackLang}",
"explanation": "... in ${feedbackLang}"
`;
}
4. RAG Context Generation
const ragContext = await hybridRAGContextManager.generateContext(
queryText,
{
examType: params.examType,
userNativeLanguage: effectiveLanguage // ← REQUIRED
}
);
5. UI Components Displaying AI Text
// If component shows AI feedback, ensure language context is available
interface Props {
feedback: string;
userLanguage?: string; // For potential re-rendering
}
Anti-Patterns (NEVER DO)
Missing Language in Tool Factory
// WRONG - Language will default to English for everyone
export function createBadTool(userId: string, supabase: SupabaseClient) {
return tool({
execute: async (params) => {
// No language context available!
}
});
}
Hardcoded Language in Agent
// WRONG - Ignores user preference
const prompt = `Feedback auf Deutsch...`; // Should be ${feedbackLang}
Not Passing Language to Nested Calls
// WRONG - Language lost in nested call
const result = await evaluateText({
text: params.text,
examType: params.examType
// Missing: userLanguage: effectiveLanguage
});
Validation Checklist
Before committing any AI-related code changes:
Language Flow:
- [ ] API route passes preferredLanguage to ALL tool factories?
- [ ] Tool factory captures userNativeLanguage in closure?
- [ ] Tool factory uses captured language as fallback?
- [ ] Tool implementation passes language to agent?
- [ ] Agent prompt uses ${feedbackLang} variable?
- [ ] RAG context receives userNativeLanguage?
No Hardcoding:
- [ ] No hardcoded "German", "English", etc. in prompts?
- [ ] Language variable used for all user-facing text?
- [ ] Default fallback is "English" not "German"?
Key Files to Check
| File | Language Variable | Purpose |
|---|---|---|
route.ts |
preferredLanguage |
Source of truth, passes to tools |
tool-factories.ts |
userNativeLanguage |
Captures in closure for tools |
*-agent-cot.ts |
userLanguage |
Uses in prompts as feedbackLang |
hybrid-context.ts |
userNativeLanguage |
RAG context options |
evaluate-text.ts |
userLanguage |
Tool implementation |
Quick Reference
// Pattern: Always capture + fallback + pass through
const capturedLanguage = userNativeLanguage || "English";
const effectiveLanguage = params.userLanguage || capturedLanguage;
// In prompts: Variable, not hardcoded
const feedbackLang = userLanguage || "German";
prompt = `"explanation": "... in ${feedbackLang}"`;
Summary
Before every AI-related change, ask:
- Does preferredLanguage flow from API route to this code?
- Is there a fallback if language is missing?
- Are prompts using variables, not hardcoded languages?
- Is language passed to ALL nested calls (agents, RAG, etc.)?
If any answer is NO → fix before committing.