Files
portfolio/app/api/i18n/[namespace]/route.ts
denshooter a5dba298f3
Some checks failed
Dev Deployment (Zero Downtime) / deploy-dev (push) Failing after 9m26s
feat: major UI/UX overhaul, snippets system, and performance fixes
2026-02-16 12:31:40 +01:00

85 lines
2.7 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { getLocalizedMessage } from '@/lib/i18n-loader';
import enMessages from '@/messages/en.json';
import deMessages from '@/messages/de.json';
// Cache für 5 Minuten
export const revalidate = 300;
const messagesMap = { en: enMessages, de: deMessages };
/**
* GET /api/i18n/[namespace]?locale=en
* Lädt alle Keys eines Namespace aus Directus oder JSON
*/
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ namespace: string }> }
) {
const { namespace } = await params;
const locale = req.nextUrl.searchParams.get('locale') || 'en';
// Normalize locale (de-DE -> de)
const normalizedLocale = locale.startsWith('de') ? 'de' : 'en';
try {
// Hole alle Keys aus JSON für diesen Namespace
const jsonData = messagesMap[normalizedLocale as 'en' | 'de'];
const namespaceData = getNestedValue(jsonData, namespace);
if (!namespaceData || typeof namespaceData !== 'object') {
return NextResponse.json({}, { status: 200 });
}
// Flatten das Objekt zu flachen Keys
const flatKeys = flattenObject(namespaceData as Record<string, unknown>);
// Lade jeden Key aus Directus (mit Fallback auf JSON)
const result: Record<string, string> = {};
await Promise.all(
Object.entries(flatKeys).map(async ([key, jsonValue]) => {
const fullKey = `${namespace}.${key}`;
const value = await getLocalizedMessage(fullKey, locale);
result[key] = value || String(jsonValue);
})
);
return NextResponse.json(result, {
headers: {
'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=600',
},
});
} catch (error) {
console.error('i18n API error:', error);
return NextResponse.json({ error: 'Failed to load translations' }, { status: 500 });
}
}
// Helper: Holt verschachtelte Werte aus Objekt
function getNestedValue(obj: Record<string, unknown>, path: string): unknown {
return path.split('.').reduce<unknown>((current, key) => {
if (current && typeof current === 'object' && key in current) {
return (current as Record<string, unknown>)[key];
}
return undefined;
}, obj);
}
// Helper: Flatten verschachteltes Objekt zu flachen Keys
function flattenObject(obj: Record<string, unknown>, prefix = ''): Record<string, string> {
const result: Record<string, string> = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (value && typeof value === 'object' && !Array.isArray(value)) {
Object.assign(result, flattenObject(value as Record<string, unknown>, newKey));
} else {
result[newKey] = String(value);
}
}
return result;
}