* Initial plan * Initial analysis: understanding locale system issues Co-authored-by: denshooter <44590296+denshooter@users.noreply.github.com> * Fix translation types to match actual component usage Co-authored-by: denshooter <44590296+denshooter@users.noreply.github.com> * Add comprehensive locale system documentation and fix API route types Co-authored-by: denshooter <44590296+denshooter@users.noreply.github.com> * Address code review feedback: improve readability and translate comments to English Co-authored-by: denshooter <44590296+denshooter@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: denshooter <44590296+denshooter@users.noreply.github.com>
80 lines
2.5 KiB
TypeScript
80 lines
2.5 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);
|
|
|
|
// 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: any, path: string): any {
|
|
return path.split('.').reduce((current, key) => current?.[key], obj);
|
|
}
|
|
|
|
// Helper: Flatten verschachteltes Objekt zu flachen Keys
|
|
function flattenObject(obj: any, 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, newKey));
|
|
} else {
|
|
result[newKey] = String(value);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|