- Add --break-system-packages flag to pip install for Alpine Linux 3.12+ compatibility - Configure Astro server to bind to 0.0.0.0 for Docker container accessibility - Replace import.meta.env with process.env for runtime environment variable access in SSR - Enable dynamic LOGIN configuration at runtime Co-Authored-By: Warp <agent@warp.dev>
102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
import type { AstroGlobal, Request } from 'astro';
|
|
import enTranslations from '../i18n/en.json';
|
|
import deTranslations from '../i18n/de.json';
|
|
|
|
type Translations = typeof enTranslations;
|
|
|
|
const translations: Record<string, Translations> = {
|
|
en: enTranslations,
|
|
de: deTranslations,
|
|
};
|
|
|
|
/**
|
|
* Get the current locale from Astro
|
|
*/
|
|
export function getLocale(astro: AstroGlobal): string {
|
|
// Check environment variable first (for Docker/container environments)
|
|
const envLocale = process.env.LOCALE;
|
|
if (envLocale && (envLocale === 'de' || envLocale === 'en')) {
|
|
return envLocale;
|
|
}
|
|
return astro.locale || 'de';
|
|
}
|
|
|
|
/**
|
|
* Get locale from Request (for API routes)
|
|
*/
|
|
export function getLocaleFromRequest(request: Request): string {
|
|
// Check environment variable first (for Docker/container environments)
|
|
const envLocale = process.env.LOCALE;
|
|
if (envLocale && (envLocale === 'de' || envLocale === 'en')) {
|
|
return envLocale;
|
|
}
|
|
|
|
// Try to get locale from Accept-Language header
|
|
const acceptLanguage = request.headers.get('accept-language');
|
|
if (acceptLanguage) {
|
|
if (acceptLanguage.includes('de')) return 'de';
|
|
if (acceptLanguage.includes('en')) return 'en';
|
|
}
|
|
return 'de'; // Default to German
|
|
}
|
|
|
|
/**
|
|
* Get translation for a key
|
|
* Supports nested keys like "common.download"
|
|
* Supports interpolation with {{variable}}
|
|
*/
|
|
function getTranslation(locale: string, key: string, params?: Record<string, string>): string {
|
|
const translation = translations[locale] || translations.de;
|
|
|
|
// Navigate through nested keys
|
|
const keys = key.split('.');
|
|
let value: any = translation;
|
|
|
|
for (const k of keys) {
|
|
if (value && typeof value === 'object' && k in value) {
|
|
value = value[k];
|
|
} else {
|
|
// Fallback to German if key not found
|
|
value = deTranslations;
|
|
for (const k2 of keys) {
|
|
if (value && typeof value === 'object' && k2 in value) {
|
|
value = value[k2];
|
|
} else {
|
|
return key; // Return key if translation not found
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (typeof value !== 'string') {
|
|
return key;
|
|
}
|
|
|
|
// Replace placeholders like {{variable}}
|
|
if (params) {
|
|
return value.replace(/\{\{(\w+)\}\}/g, (match, paramKey) => {
|
|
return params[paramKey] || match;
|
|
});
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Get translation in Astro component
|
|
*/
|
|
export function t(astro: AstroGlobal, key: string, params?: Record<string, string>): string {
|
|
const locale = getLocale(astro);
|
|
return getTranslation(locale, key, params);
|
|
}
|
|
|
|
/**
|
|
* Get translation in API route
|
|
*/
|
|
export function tApi(request: Request, key: string, params?: Record<string, string>): string {
|
|
const locale = getLocaleFromRequest(request);
|
|
return getTranslation(locale, key, params);
|
|
}
|
|
|