Files
klz-cables.com/lib/i18n.ts
2025-12-29 18:18:48 +01:00

341 lines
10 KiB
TypeScript

export type Locale = 'en' | 'de';
export const defaultLocale: Locale = 'en';
export const locales: Locale[] = ['en', 'de'];
// Simple translation dictionary
const translations = {
en: {
site: {
title: 'Kabel-Konfigurator',
description: 'Professional cable solutions - configure and order custom cables',
},
nav: {
home: 'Home',
blog: 'Blog',
products: 'Products',
contact: 'Contact',
privacy: 'Privacy Policy',
legal: 'Legal Notice',
terms: 'Terms & Conditions',
},
home: {
hero: 'Professional Cable Solutions',
heroSubtitle: 'Configure your custom cables online',
cta: 'Configure Now',
featuredPosts: 'Latest News',
featuredProducts: 'Featured Products',
},
blog: {
title: 'Blog',
description: 'Latest news and insights about cables and energy',
readMore: 'Read more',
noPosts: 'No posts available.',
backToBlog: '← Back to Blog',
categories: 'Categories',
featured: 'Featured Posts',
allPosts: 'All Posts',
noPostsDescription: 'Check back soon for new content.',
},
products: {
title: 'Products',
categories: 'Categories',
noProducts: 'No products available.',
noCategories: 'No categories available.',
inStock: 'In Stock',
outOfStock: 'Out of Stock',
price: 'Price',
sku: 'SKU',
viewAll: 'View All Products',
},
product: {
backToProducts: '← Back to Products',
description: 'Description',
specifications: 'Specifications',
price: 'Price',
sku: 'SKU',
stock: 'Stock Status',
inStock: 'In Stock',
outOfStock: 'Out of Stock',
},
productCategory: {
backToCategories: '← Back to Categories',
productsInCategory: 'Products in this category',
},
contact: {
title: 'Contact Us',
subtitle: 'Get in touch with our team',
name: 'Your Name',
email: 'Your Email',
message: 'Your Message',
submit: 'Send Message',
success: 'Message sent successfully!',
error: 'Failed to send message. Please try again.',
processing: 'Sending...',
phone: 'Phone (optional)',
subject: 'Subject',
company: 'Company (optional)',
requiredFields: 'Required fields are marked with *',
sending: 'Sending...',
errors: {
nameRequired: 'Please enter your name',
emailRequired: 'Please enter your email address',
emailInvalid: 'Please enter a valid email address',
messageRequired: 'Please enter your message',
},
},
consent: {
title: 'Cookie & Analytics Consent',
description: 'We use analytics cookies to improve our website. Please accept to continue.',
accept: 'Accept',
decline: 'Decline',
analytics: 'Analytics',
analyticsDesc: 'Help us understand how visitors use our site',
},
cookieConsent: {
message: 'We use cookies to enhance your browsing experience and analyze our traffic.',
privacyPolicy: 'Privacy Policy',
decline: 'Decline',
accept: 'Accept',
},
footer: {
rights: 'All rights reserved.',
madeWith: 'Made with Next.js',
},
common: {
readMore: 'Read more',
back: 'Back',
loading: 'Loading...',
noContent: 'No content available.',
date: 'Date',
updated: 'Updated',
},
form: {
success: 'Message sent successfully!',
error: {
submit: 'Failed to send message. Please try again.',
network: 'Network error. Please try again.',
},
sending: 'Sending...',
name: 'Your Name',
email: 'Your Email',
message: 'Your Message',
submit: 'Send Message',
},
},
de: {
site: {
title: 'Kabel-Konfigurator',
description: 'Professionelle Kabel-Lösungen - konfigurieren und bestellen Sie maßgeschneiderte Kabel',
},
nav: {
home: 'Startseite',
blog: 'Blog',
products: 'Produkte',
contact: 'Kontakt',
privacy: 'Datenschutz',
legal: 'Impressum',
terms: 'AGB',
},
home: {
hero: 'Professionelle Kabel-Lösungen',
heroSubtitle: 'Konfigurieren Sie Ihre maßgeschneiderten Kabel online',
cta: 'Jetzt konfigurieren',
featuredPosts: 'Aktuelle Neuigkeiten',
featuredProducts: 'Empfohlene Produkte',
},
blog: {
title: 'Blog',
description: 'Aktuelle Neuigkeiten und Einblicke über Kabel und Energie',
readMore: 'Weiterlesen',
noPosts: 'Keine Beiträge verfügbar.',
backToBlog: '← Zurück zum Blog',
categories: 'Kategorien',
featured: 'Beiträge',
allPosts: 'Alle Beiträge',
noPostsDescription: 'Schauen Sie bald wieder vorbei für neue Inhalte.',
},
products: {
title: 'Produkte',
categories: 'Kategorien',
noProducts: 'Keine Produkte verfügbar.',
noCategories: 'Keine Kategorien verfügbar.',
inStock: 'Auf Lager',
outOfStock: 'Nicht auf Lager',
price: 'Preis',
sku: 'Artikelnummer',
viewAll: 'Alle Produkte anzeigen',
},
product: {
backToProducts: '← Zurück zu Produkten',
description: 'Beschreibung',
specifications: 'Spezifikationen',
price: 'Preis',
sku: 'Artikelnummer',
stock: 'Lagerbestand',
inStock: 'Auf Lager',
outOfStock: 'Nicht auf Lager',
},
productCategory: {
backToCategories: '← Zurück zu Kategorien',
productsInCategory: 'Produkte in dieser Kategorie',
},
contact: {
title: 'Kontakt',
subtitle: 'Nehmen Sie Kontakt mit unserem Team auf',
name: 'Ihr Name',
email: 'Ihre E-Mail',
message: 'Ihre Nachricht',
submit: 'Nachricht senden',
success: 'Nachricht erfolgreich gesendet!',
error: 'Nachricht konnte nicht gesendet werden. Bitte versuchen Sie es erneut.',
processing: 'Wird gesendet...',
phone: 'Telefon (optional)',
subject: 'Betreff',
company: 'Firma (optional)',
requiredFields: 'Pflichtfelder sind mit * markiert',
sending: 'Wird gesendet...',
errors: {
nameRequired: 'Bitte geben Sie Ihren Namen ein',
emailRequired: 'Bitte geben Sie Ihre E-Mail-Adresse ein',
emailInvalid: 'Bitte geben Sie eine gültige E-Mail-Adresse ein',
messageRequired: 'Bitte geben Sie Ihre Nachricht ein',
},
},
consent: {
title: 'Cookie- & Analyse-Einwilligung',
description: 'Wir verwenden Analyse-Cookies, um unsere Website zu verbessern. Bitte akzeptieren Sie zur Fortsetzung.',
accept: 'Akzeptieren',
decline: 'Ablehnen',
analytics: 'Analyse',
analyticsDesc: 'Helfen Sie uns zu verstehen, wie Besucher unsere Seite nutzen',
},
cookieConsent: {
message: 'Wir verwenden Cookies, um Ihr Surferlebnis zu verbessern und unseren Traffic zu analysieren.',
privacyPolicy: 'Datenschutzrichtlinie',
decline: 'Ablehnen',
accept: 'Akzeptieren',
},
footer: {
rights: 'Alle Rechte vorbehalten.',
madeWith: 'Erstellt mit Next.js',
},
common: {
readMore: 'Weiterlesen',
back: 'Zurück',
loading: 'Wird geladen...',
noContent: 'Kein Inhalt verfügbar.',
date: 'Datum',
updated: 'Aktualisiert',
},
form: {
success: 'Nachricht erfolgreich gesendet!',
error: {
submit: 'Nachricht konnte nicht gesendet werden. Bitte versuchen Sie es erneut.',
network: 'Netzwerkfehler. Bitte versuchen Sie es erneut.',
},
sending: 'Wird gesendet...',
name: 'Ihr Name',
email: 'Ihre E-Mail',
message: 'Ihre Nachricht',
submit: 'Nachricht senden',
},
},
};
export function t(key: string, locale: Locale = 'en'): string {
const keys = key.split('.');
let value: any = translations[locale];
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
// Fallback to English
value = translations.en;
for (const k2 of keys) {
if (value && typeof value === 'object' && k2 in value) {
value = value[k2];
} else {
return key; // Return the key itself if translation not found
}
}
return value;
}
}
// Ensure we always return a string
return typeof value === 'string' ? value : key;
}
export function getLocaleFromPath(path: string): Locale {
if (path.startsWith('/de/')) {
return 'de';
}
return 'en';
}
export function getLocalizedPath(path: string, locale: Locale): string {
if (locale === 'en') {
return path.replace('/de/', '/');
}
if (locale === 'de') {
if (path === '/') return '/de';
return path.startsWith('/de/') ? path : `/de${path}`;
}
return path;
}
export function getPathWithoutLocale(path: string): string {
if (path.startsWith('/de/')) {
return path.substring(3) || '/';
}
return path;
}
export const languageNames: Record<Locale, string> = {
en: 'English',
de: 'Deutsch',
};
export function getSiteInfo(locale?: Locale) {
const loc = locale || defaultLocale;
return {
title: t('site.title', loc),
description: t('site.description', loc),
locale: loc,
baseUrl: process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com',
locales: ['en', 'de'],
};
}
// Hook for client components (simplified version)
export function useTranslation(namespace?: string) {
// This would be used in client components
// For now, return a simple t function
return {
t: (key: string) => t(namespace ? `${namespace}.${key}` : key, defaultLocale)
};
}
// Get alternate URLs for SEO
export function getAlternateUrls(path: string) {
return [
{ locale: 'en', url: path.replace('/de/', '/') },
{ locale: 'de', url: path.startsWith('/de') ? path : `/de${path}` },
];
}
// Hook for client components - returns current locale
export function useLocale(): Locale {
// This is a simplified version for build purposes
// In a real app, this would use next/navigation to get the current path
return defaultLocale;
}
// Get dictionary for client components
export function getDictionary(locale: Locale) {
return {
t: (key: string) => t(key, locale)
};
}