First Commit - Portfolio Page
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
// src/i18n/locales/de/blog/index.ts
|
||||
export const blog = {
|
||||
meta: {
|
||||
title: 'Blog - JTL Integration & Digital Solutions',
|
||||
description: 'Insights und Best Practices zu JTL-WaWi, E-Commerce und digitaler Transformation',
|
||||
header: {
|
||||
title: 'Insights & Best Practices',
|
||||
subtitle: 'Insights und Best Practices zu JTL-WaWi, E-Commerce und digitaler Transformation'
|
||||
}
|
||||
},
|
||||
posts: {
|
||||
'erp-integration-breuninger': {
|
||||
title: 'ApparelMagic und TradeByte: Analyse komplexer Integrationen',
|
||||
date: '2024-02-09',
|
||||
excerpt: 'Detaillierte Analyse einer E-Commerce-Integration zwischen Apparel Magic und Breuninger via TradeByte',
|
||||
category: 'System Integration',
|
||||
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integration', 'Python', 'MariaDB'],
|
||||
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
||||
content: {
|
||||
intro: {
|
||||
title: 'Apparel Magic meets Breuninger: Eine technische Analyse der TradeByte-Integration',
|
||||
description: 'Die Integration von E-Commerce-Systemen mit etablierten Marktplätzen stellt Unternehmen vor besondere Herausforderungen. In diesem Artikel teile ich meine Erfahrungen aus einem komplexen Integrationsprojekt zwischen Apparel Magic als ERP-System und der Breuninger-Plattform über TradeByte.'
|
||||
},
|
||||
background: {
|
||||
title: 'Projekthintergrund',
|
||||
systems: {
|
||||
erp: 'Apparel Magic als ERP-System für Produktdaten und Bestandsmanagement',
|
||||
middleware: 'TradeByte als Middleware für die Breuninger-Plattform'
|
||||
},
|
||||
challenges: {
|
||||
sync: 'Bidirektionale Synchronisation von Bestellungen',
|
||||
customers: 'Automatisierte Kundenanlage',
|
||||
delivery: 'Verwaltung von Lieferscheinen',
|
||||
inventory: 'Bestandsmanagement in Echtzeit'
|
||||
}
|
||||
},
|
||||
tech: {
|
||||
title: 'Technische Architektur',
|
||||
components: {
|
||||
title: 'Zentrale Komponenten'
|
||||
},
|
||||
database: {
|
||||
title: 'Middleware-Datenbank',
|
||||
description: 'Die MariaDB-Datenbank fungiert als zentraler Datenspeicher für die Integration:'
|
||||
}
|
||||
},
|
||||
api: {
|
||||
title: 'API-Integrationen',
|
||||
apparel_magic: {
|
||||
title: 'Apparel Magic API',
|
||||
description: 'Die REST-API von Apparel Magic wird für Kundenanlage und Bestandsmanagement verwendet:'
|
||||
},
|
||||
tradebyte: {
|
||||
title: 'TradeByte Integration',
|
||||
description: 'Die TradeByte-API verwendet eine Kombination aus REST und XML:'
|
||||
}
|
||||
},
|
||||
order_process: {
|
||||
title: 'Bestellprozess',
|
||||
steps: {
|
||||
fetch: 'Regelmäßiger Abruf neuer Bestellungen von TradeByte',
|
||||
customers: 'Automatische Kundenanlage in Apparel Magic',
|
||||
process: 'Bestellverarbeitung und Statusaktualisierung',
|
||||
delivery: 'Generierung und Speicherung von Lieferscheinen'
|
||||
},
|
||||
delivery_notes: {
|
||||
title: 'Lieferschein-Management'
|
||||
}
|
||||
},
|
||||
challenges: {
|
||||
title: 'Herausforderungen und Lösungen',
|
||||
status: {
|
||||
title: '1. Status-Management',
|
||||
description: 'Eine besondere Herausforderung war das Management von Bestellstatus:'
|
||||
},
|
||||
error_handling: {
|
||||
title: '2. Fehlerbehandlung und Monitoring',
|
||||
description: 'Robuste Fehlerbehandlung war essentiell für den Produktivbetrieb:'
|
||||
}
|
||||
},
|
||||
best_practices: {
|
||||
title: 'Best Practices',
|
||||
api: {
|
||||
title: '1. API-Kommunikation',
|
||||
items: {
|
||||
retry: 'Implementierung von Retry-Mechanismen',
|
||||
errors: 'Sorgfältiges Error Handling',
|
||||
logging: 'Ausführliches Logging aller Kommunikation'
|
||||
}
|
||||
},
|
||||
data: {
|
||||
title: '2. Datenmanagement',
|
||||
items: {
|
||||
storage: 'Zentrale Datenhaltung in MariaDB',
|
||||
transactions: 'Transaktionssicherheit bei kritischen Operationen',
|
||||
validation: 'Regelmäßige Datenvalidierung'
|
||||
}
|
||||
},
|
||||
automation: {
|
||||
title: '3. Prozessautomatisierung',
|
||||
items: {
|
||||
customers: 'Automatisierte Kundenanlage',
|
||||
status: 'Automatische Statusaktualisierungen',
|
||||
delivery: 'Systematisches Lieferschein-Management'
|
||||
}
|
||||
}
|
||||
},
|
||||
lessons: {
|
||||
title: 'Lessons Learned',
|
||||
api: {
|
||||
title: '1. API-Design',
|
||||
items: {
|
||||
docs: 'Gründliche API-Dokumentation ist essentiell',
|
||||
auth: 'Verständnis der verschiedenen Authentifizierungsmethoden',
|
||||
limits: 'Berücksichtigung von Rate Limits'
|
||||
}
|
||||
},
|
||||
validation: {
|
||||
title: '2. Datenvalidierung',
|
||||
items: {
|
||||
rules: 'Implementierung strenger Validierungsregeln',
|
||||
edge_cases: 'Sorgfältige Handhabung von Sonderfällen',
|
||||
cleanup: 'Automatische Datenbereinigung'
|
||||
}
|
||||
},
|
||||
optimization: {
|
||||
title: '3. Prozessoptimierung',
|
||||
items: {
|
||||
automation: 'Kontinuierliche Verbesserung der Automatisierung',
|
||||
performance: 'Regelmäßige Performance-Überprüfungen',
|
||||
monitoring: 'Proaktives Monitoring'
|
||||
}
|
||||
}
|
||||
},
|
||||
conclusion: {
|
||||
title: 'Fazit',
|
||||
requirements: {
|
||||
understanding: 'Tiefes Verständnis beider Systeme',
|
||||
implementation: 'Sorgfältige Implementierung der API-Kommunikation',
|
||||
error_handling: 'Robuste Fehlerbehandlung',
|
||||
monitoring: 'Kontinuierliches Monitoring'
|
||||
},
|
||||
results: 'Die entwickelte Lösung verarbeitet erfolgreich Bestellungen und ermöglicht eine nahtlose Integration zwischen den Systemen. Besonders die automatisierte Kundenanlage und das Lieferschein-Management haben sich als effizienzsteigernd erwiesen.'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
ui: {
|
||||
readMore: 'Weiterlesen',
|
||||
loading: {
|
||||
posts: 'Blogbeiträge werden geladen...',
|
||||
post: 'Blogbeitrag wird geladen...'
|
||||
},
|
||||
errors: {
|
||||
posts: 'Fehler beim Laden der Blogbeiträge',
|
||||
post: 'Der gesuchte Blogbeitrag existiert nicht oder wurde verschoben.'
|
||||
},
|
||||
backToBlog: 'Zurück zum Blog',
|
||||
publishedOn: 'Veröffentlicht am',
|
||||
category: 'Kategorie',
|
||||
tags: 'Tags',
|
||||
notFound: {
|
||||
title: 'Beitrag nicht gefunden',
|
||||
message: 'Der gesuchte Blogbeitrag existiert nicht oder wurde verschoben.'
|
||||
}
|
||||
},
|
||||
categories: {
|
||||
'Integration': 'Integration',
|
||||
'Entwicklung': 'Entwicklung',
|
||||
'Automatisierung': 'Automatisierung'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export type BlogConfig = typeof blog;
|
||||
export type BlogPost = BlogConfig['posts'][keyof BlogConfig['posts']];
|
||||
@@ -0,0 +1,138 @@
|
||||
// src/i18n/locales/de/blog/posts/erp-integration-breuninger.ts
|
||||
export const erpIntegrationBreuninger = {
|
||||
posts: {
|
||||
erp_integration: {
|
||||
title: 'ApparelMagic und TradeByte: Analyse komplexer Integrationen',
|
||||
date: '2024-02-09',
|
||||
excerpt: 'Detaillierte Analyse einer E-Commerce-Integration zwischen Apparel Magic und Breuninger via TradeByte',
|
||||
category: 'System Integration',
|
||||
tags: ['ERP', 'Apparel Magic', 'TradeByte', 'API Integration', 'Python', 'MariaDB'],
|
||||
coverImage: '/images/posts/erp-integration-breuninger/cover.jpg',
|
||||
intro: {
|
||||
title: 'Apparel Magic meets Breuninger: Eine technische Analyse der TradeByte-Integration',
|
||||
description: 'Die Integration von E-Commerce-Systemen mit etablierten Marktplätzen stellt Unternehmen vor besondere Herausforderungen. In diesem Artikel teile ich meine Erfahrungen aus einem komplexen Integrationsprojekt zwischen Apparel Magic als ERP-System und der Breuninger-Plattform über TradeByte.'
|
||||
},
|
||||
background: {
|
||||
title: 'Projekthintergrund',
|
||||
systems: {
|
||||
erp: 'Apparel Magic als ERP-System für Produktdaten und Bestandsmanagement',
|
||||
middleware: 'TradeByte als Middleware für die Breuninger-Plattform'
|
||||
},
|
||||
challenges: {
|
||||
sync: 'Bidirektionale Synchronisation von Bestellungen',
|
||||
customers: 'Automatisierte Kundenanlage',
|
||||
delivery: 'Verwaltung von Lieferscheinen',
|
||||
inventory: 'Bestandsmanagement in Echtzeit'
|
||||
}
|
||||
},
|
||||
tech: {
|
||||
title: 'Technische Architektur',
|
||||
components: {
|
||||
title: 'Zentrale Komponenten'
|
||||
},
|
||||
database: {
|
||||
title: 'Middleware-Datenbank',
|
||||
description: 'Die MariaDB-Datenbank fungiert als zentraler Datenspeicher für die Integration:'
|
||||
}
|
||||
},
|
||||
api: {
|
||||
title: 'API-Integrationen',
|
||||
apparel_magic: {
|
||||
title: 'Apparel Magic API',
|
||||
description: 'Die REST-API von Apparel Magic wird für Kundenanlage und Bestandsmanagement verwendet:'
|
||||
},
|
||||
tradebyte: {
|
||||
title: 'TradeByte Integration',
|
||||
description: 'Die TradeByte-API verwendet eine Kombination aus REST und XML:'
|
||||
}
|
||||
},
|
||||
order_process: {
|
||||
title: 'Bestellprozess',
|
||||
steps: {
|
||||
fetch: 'Regelmäßiger Abruf neuer Bestellungen von TradeByte',
|
||||
customers: 'Automatische Kundenanlage in Apparel Magic',
|
||||
process: 'Bestellverarbeitung und Statusaktualisierung',
|
||||
delivery: 'Generierung und Speicherung von Lieferscheinen'
|
||||
},
|
||||
delivery_notes: {
|
||||
title: 'Lieferschein-Management'
|
||||
}
|
||||
},
|
||||
challenges: {
|
||||
title: 'Herausforderungen und Lösungen',
|
||||
status: {
|
||||
title: '1. Status-Management',
|
||||
description: 'Eine besondere Herausforderung war das Management von Bestellstatus:'
|
||||
},
|
||||
error_handling: {
|
||||
title: '2. Fehlerbehandlung und Monitoring',
|
||||
description: 'Robuste Fehlerbehandlung war essentiell für den Produktivbetrieb:'
|
||||
}
|
||||
},
|
||||
best_practices: {
|
||||
title: 'Best Practices',
|
||||
api: {
|
||||
title: '1. API-Kommunikation',
|
||||
items: {
|
||||
retry: 'Implementierung von Retry-Mechanismen',
|
||||
errors: 'Sorgfältiges Error Handling',
|
||||
logging: 'Ausführliches Logging aller Kommunikation'
|
||||
}
|
||||
},
|
||||
data: {
|
||||
title: '2. Datenmanagement',
|
||||
items: {
|
||||
storage: 'Zentrale Datenhaltung in MariaDB',
|
||||
transactions: 'Transaktionssicherheit bei kritischen Operationen',
|
||||
validation: 'Regelmäßige Datenvalidierung'
|
||||
}
|
||||
},
|
||||
automation: {
|
||||
title: '3. Prozessautomatisierung',
|
||||
items: {
|
||||
customers: 'Automatisierte Kundenanlage',
|
||||
status: 'Automatische Statusaktualisierungen',
|
||||
delivery: 'Systematisches Lieferschein-Management'
|
||||
}
|
||||
}
|
||||
},
|
||||
lessons: {
|
||||
title: 'Lessons Learned',
|
||||
api: {
|
||||
title: '1. API-Design',
|
||||
items: {
|
||||
docs: 'Gründliche API-Dokumentation ist essentiell',
|
||||
auth: 'Verständnis der verschiedenen Authentifizierungsmethoden',
|
||||
limits: 'Berücksichtigung von Rate Limits'
|
||||
}
|
||||
},
|
||||
validation: {
|
||||
title: '2. Datenvalidierung',
|
||||
items: {
|
||||
rules: 'Implementierung strenger Validierungsregeln',
|
||||
edge_cases: 'Sorgfältige Handhabung von Sonderfällen',
|
||||
cleanup: 'Automatische Datenbereinigung'
|
||||
}
|
||||
},
|
||||
optimization: {
|
||||
title: '3. Prozessoptimierung',
|
||||
items: {
|
||||
automation: 'Kontinuierliche Verbesserung der Automatisierung',
|
||||
performance: 'Regelmäßige Performance-Überprüfungen',
|
||||
monitoring: 'Proaktives Monitoring'
|
||||
}
|
||||
}
|
||||
},
|
||||
conclusion: {
|
||||
title: 'Fazit',
|
||||
requirements: {
|
||||
understanding: 'Tiefes Verständnis beider Systeme',
|
||||
implementation: 'Sorgfältige Implementierung der API-Kommunikation',
|
||||
error_handling: 'Robuste Fehlerbehandlung',
|
||||
monitoring: 'Kontinuierliches Monitoring'
|
||||
},
|
||||
results: 'Die entwickelte Lösung verarbeitet erfolgreich Bestellungen und ermöglicht eine nahtlose Integration zwischen den Systemen. Besonders die automatisierte Kundenanlage und das Lieferschein-Management haben sich als effizienzsteigernd erwiesen.'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,253 @@
|
||||
// src/i18n/locales/de/blog/posts/fullstack-development-timetracking.ts
|
||||
export const fullstackDevelopmentTimetracking = {
|
||||
meta: {
|
||||
title: 'Fullstack-Entwicklung mit Python und React: Architektur unserer Zeiterfassungslösung',
|
||||
date: '2024-02-09',
|
||||
excerpt: 'Eine technische Deep-Dive in die Implementierung einer modernen Zeiterfassungslösung',
|
||||
category: 'System Architecture',
|
||||
coverImage: '/images/posts/fullstack-development-timetracking/cover.jpg',
|
||||
tags: ['Python', 'React', 'TypeScript', 'MSSQL', 'System Design']
|
||||
},
|
||||
content: {
|
||||
intro: {
|
||||
title: 'Fullstack-Entwicklung mit Python und React: Architektur unserer Zeiterfassungslösung',
|
||||
description: 'Die Entwicklung einer robusten Zeiterfassungslösung erfordert nicht nur technisches Know-how, sondern auch ein tiefes Verständnis für komplexe Geschäftsregeln und Benutzeranforderungen. In diesem Artikel teile ich unsere Erfahrungen bei der Implementierung einer modernen Fullstack-Zeiterfassungslösung mit Python und React.'
|
||||
},
|
||||
systemArchitecture: {
|
||||
title: 'Systemarchitektur',
|
||||
frontend: {
|
||||
title: 'Frontend (Next.js + TypeScript)',
|
||||
description: 'Die Frontend-Architektur basiert auf Next.js mit TypeScript und folgt einem komponenten-basierten Ansatz:',
|
||||
code: {
|
||||
types: `// types/TimeEntry.ts
|
||||
interface TimeEntry {
|
||||
id: number;
|
||||
date: string;
|
||||
checkIn: string;
|
||||
checkOut: string | null;
|
||||
userId: number;
|
||||
status: 'complete' | 'incomplete';
|
||||
}`,
|
||||
component: `// components/TimeEntryForm.tsx
|
||||
const TimeEntryForm: React.FC<TimeEntryFormProps> = ({ onSubmit }) => {
|
||||
const [entry, setEntry] = useState<TimeEntry>({
|
||||
date: new Date().toISOString().split('T')[0],
|
||||
checkIn: new Date().toLocaleTimeString(),
|
||||
checkOut: null,
|
||||
status: 'incomplete'
|
||||
});
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!validateTimeEntry(entry)) return;
|
||||
try {
|
||||
await onSubmit(entry);
|
||||
} catch (error) {
|
||||
console.error('Error submitting time entry:', error);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className='space-y-4'>
|
||||
<DateInput
|
||||
value={entry.date}
|
||||
onChange={(date) => setEntry({ ...entry, date })}
|
||||
/>
|
||||
<TimeInput
|
||||
value={entry.checkIn}
|
||||
onChange={(time) => setEntry({ ...entry, checkIn: time })}
|
||||
/>
|
||||
{/* Additional form elements */}
|
||||
</form>
|
||||
);
|
||||
};`
|
||||
}
|
||||
},
|
||||
backend: {
|
||||
title: 'Backend (Flask + MSSQL)',
|
||||
description: 'Das Backend verwendet Flask für die API und MSSQL für die Datenpersistenz:',
|
||||
code: {
|
||||
models: `# models/time_entry.py
|
||||
class TimeEntry(db.Model):
|
||||
__tablename__ = 'Stundenzettel'
|
||||
id = db.Column('ID', db.Decimal, primary_key=True)
|
||||
personal_id = db.Column('Personal_ID', db.Decimal)
|
||||
datum = db.Column('Datum', db.Date)
|
||||
kommen = db.Column('Kommen', db.Time)
|
||||
gehen = db.Column('Gehen', db.Time)
|
||||
@validates('gehen')
|
||||
def validate_checkout(self, key, value):
|
||||
if value and value < self.kommen:
|
||||
raise ValueError('Checkout time cannot be before checkin time')
|
||||
return value`,
|
||||
routes: `# routes/time_entries.py
|
||||
@app.route('/api/time-entries', methods=['POST'])
|
||||
@jwt_required
|
||||
def create_time_entry():
|
||||
data = request.get_json()
|
||||
user_id = get_jwt_identity()
|
||||
try:
|
||||
validate_time_entry_creation(data, user_id)
|
||||
entry = TimeEntry(
|
||||
personal_id=user_id,
|
||||
datum=data['date'],
|
||||
kommen=data['checkIn'],
|
||||
gehen=data.get('checkOut')
|
||||
)
|
||||
db.session.add(entry)
|
||||
db.session.commit()
|
||||
return jsonify(entry.to_dict()), 201
|
||||
except ValidationError as e:
|
||||
return jsonify({'error': str(e)}), 400`
|
||||
}
|
||||
}
|
||||
},
|
||||
businessLogic: {
|
||||
title: 'Geschäftslogik-Implementierung',
|
||||
validation: {
|
||||
title: 'Validierung von Zeiteinträgen',
|
||||
description: 'Die Validierungslogik stellt sicher, dass alle Geschäftsregeln eingehalten werden:',
|
||||
code: `def validate_time_entry_creation(data: dict, user_id: int) -> None:
|
||||
'''Validates a new time entry according to business rules.'''
|
||||
# Check for existing incomplete entries
|
||||
incomplete_entry = TimeEntry.query.filter_by(
|
||||
personal_id=user_id,
|
||||
gehen=None,
|
||||
datum=data['date']
|
||||
).first()
|
||||
if incomplete_entry:
|
||||
raise ValidationError('Cannot create new entry while incomplete entry exists')
|
||||
# Check for time overlap with existing entries
|
||||
overlapping_entry = TimeEntry.query.filter(
|
||||
TimeEntry.personal_id == user_id,
|
||||
TimeEntry.datum == data['date'],
|
||||
TimeEntry.kommen <= data['checkIn'],
|
||||
TimeEntry.gehen >= data['checkIn']
|
||||
).first()
|
||||
if overlapping_entry:
|
||||
raise ValidationError('Time entry overlaps with existing entry')`
|
||||
}
|
||||
},
|
||||
databaseDesign: {
|
||||
title: 'Datenbankdesign',
|
||||
description: 'Das MSSQL-Datenbankschema ist auf Effizienz und Integrität ausgelegt:',
|
||||
code: `CREATE TABLE dbo.Stundenzettel (
|
||||
ID decimal NOT NULL PRIMARY KEY,
|
||||
Personal_ID decimal,
|
||||
Datum date,
|
||||
Kommen time,
|
||||
Gehen time,
|
||||
xStatus int,
|
||||
xBenutzer nvarchar(15),
|
||||
xDatum datetime,
|
||||
xVersion timestamp
|
||||
);
|
||||
CREATE INDEX idx_personal_datum
|
||||
ON dbo.Stundenzettel(Personal_ID, Datum);`
|
||||
},
|
||||
security: {
|
||||
title: 'Sicherheitsimplementierung',
|
||||
authentication: {
|
||||
title: 'JWT-Authentifizierung',
|
||||
code: `# auth/jwt_handler.py
|
||||
from flask_jwt_extended import create_access_token
|
||||
def authenticate_user(username: str, password: str) -> str:
|
||||
user = Personal.query.filter_by(
|
||||
Benutzername=username,
|
||||
Passwort=password # In production, use proper password hashing
|
||||
).first()
|
||||
if not user:
|
||||
raise AuthenticationError('Invalid credentials')
|
||||
return create_access_token(identity=user.ID)`
|
||||
}
|
||||
},
|
||||
bestPractices: {
|
||||
title: 'Best Practices und Learnings',
|
||||
points: [
|
||||
{
|
||||
title: 'Datenvalidierung auf mehreren Ebenen',
|
||||
items: [
|
||||
'Frontend-Validierung für sofortiges Feedback',
|
||||
'Backend-Validierung für Geschäftsregeln',
|
||||
'Datenbankconstraints für Datenintegrität'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Fehlerbehandlung',
|
||||
items: [
|
||||
'Strukturierte Fehlermeldungen',
|
||||
'Benutzerfreundliche Fehlermeldungen im Frontend',
|
||||
'Detailliertes Logging im Backend'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Performance-Optimierung',
|
||||
items: [
|
||||
'Indexierung kritischer Datenbankfelder',
|
||||
'Frontend-Caching von Zeiteinträgen',
|
||||
'Lazy Loading für historische Daten'
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
challenges: {
|
||||
title: 'Herausforderungen und Lösungen',
|
||||
timezones: {
|
||||
title: '1. Zeitzonen-Handling',
|
||||
description: 'Eine besondere Herausforderung war die korrekte Behandlung von Zeitzonen:',
|
||||
code: `// utils/dateTime.ts
|
||||
export const formatTimeForDisplay = (time: string): string => {
|
||||
return new Date(\`1970-01-01T\${time}\`).toLocaleTimeString('de-DE', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
};
|
||||
export const formatTimeForAPI = (time: string): string => {
|
||||
return new Date(\`1970-01-01T\${time}\`).toISOString().split('T')[1];
|
||||
};`
|
||||
},
|
||||
concurrency: {
|
||||
title: '2. Concurrent Updates',
|
||||
description: 'Die Behandlung gleichzeitiger Updates erforderte spezielle Aufmerksamkeit:',
|
||||
code: `from sqlalchemy import and_, or_
|
||||
def update_time_entry(entry_id: int, data: dict) -> TimeEntry:
|
||||
entry = TimeEntry.query.filter_by(id=entry_id).with_for_update().first()
|
||||
if not entry:
|
||||
raise NotFoundError('Time entry not found')
|
||||
# Optimistic locking using version field
|
||||
if entry.xVersion != data['version']:
|
||||
raise ConcurrencyError('Entry was modified by another user')
|
||||
entry.gehen = data.get('checkOut')
|
||||
db.session.commit()
|
||||
return entry`
|
||||
},
|
||||
offline: {
|
||||
title: '3. Offline-Fähigkeit',
|
||||
description: 'Für die Offline-Funktionalität implementierten wir eine Service Worker-Strategie:',
|
||||
code: `// service-worker.ts
|
||||
const CACHE_NAME = 'timetracking-v1';
|
||||
self.addEventListener('fetch', (event) => {
|
||||
event.respondWith(
|
||||
caches.match(event.request).then(response => {
|
||||
return response || fetch(event.request).then(response => {
|
||||
return caches.open(CACHE_NAME).then(cache => {
|
||||
cache.put(event.request, response.clone());
|
||||
return response;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
});`
|
||||
}
|
||||
},
|
||||
conclusion: {
|
||||
title: 'Fazit',
|
||||
description: 'Die Entwicklung einer Zeiterfassungslösung erfordert sorgfältige Planung und Berücksichtigung zahlreicher Geschäftsregeln. Durch den Einsatz moderner Technologien wie Next.js, TypeScript und Flask konnten wir eine robuste und benutzerfreundliche Lösung implementieren.',
|
||||
keyPoints: [
|
||||
'Strikte Typisierung mit TypeScript',
|
||||
'Umfassende Validierungslogik',
|
||||
'Effizientes Datenbankdesign',
|
||||
'Benutzerfreundliche Fehlerbehandlung'
|
||||
],
|
||||
results: 'Die Lösung ist seit mehreren Monaten erfolgreich im Einsatz und verarbeitet täglich hunderte von Zeiteinträgen zuverlässig.'
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,204 @@
|
||||
// src/i18n/locales/de/blog/posts/rfid-automation.ts
|
||||
export const rfidAutomation = {
|
||||
meta: {
|
||||
title: 'RFID-Etiketten-Automatisierung: Von Datenbank zum Drucker',
|
||||
date: '2024-02-09',
|
||||
excerpt: 'Eine detaillierte technische Analyse der Implementierung eines automatisierten RFID-Etikettendruck-Systems mit Python',
|
||||
category: 'System Integration',
|
||||
coverImage: '/images/posts/rfid-automation/cover.jpg',
|
||||
tags: ['RFID', 'Python', 'ZPL', 'Automation', 'Zebra Printer', 'EPC']
|
||||
},
|
||||
content: {
|
||||
intro: {
|
||||
title: 'RFID-Etiketten-Automatisierung: Von Datenbank zum Drucker',
|
||||
description: 'In modernen Logistik- und Retail-Umgebungen ist die effiziente und fehlerfreie Etikettierung von Produkten mit RFID-Tags von entscheidender Bedeutung. In diesem Artikel teile ich meine Erfahrungen bei der Implementierung einer automatisierten Lösung für die Generierung und den Druck von RFID-Etiketten mit Chipkodierung.'
|
||||
},
|
||||
requirements: {
|
||||
title: 'Projekthintergrund',
|
||||
points: [
|
||||
'Automatische Generierung von EPC-Codes (Electronic Product Code)',
|
||||
'Erstellung von ZPL-Code für Zebra-Drucker',
|
||||
'Direkte Netzwerkkommunikation mit dem Drucker',
|
||||
'Integration mit bestehenden Produktdaten',
|
||||
'Fehlerbehandlung und Logging'
|
||||
]
|
||||
},
|
||||
implementation: {
|
||||
title: 'Technische Umsetzung',
|
||||
epcGeneration: {
|
||||
title: 'EPC-Code Generierung',
|
||||
description: 'Die EPC-Codes werden nach dem SGTIN-Standard (Serialized Global Trade Item Number) generiert:',
|
||||
code: `def generate_encoded_epc(company_prefix, indicator, item_ref, serial):
|
||||
sgtin = SGTIN(company_prefix, indicator, item_ref, serial)
|
||||
return sgtin.encode()`
|
||||
},
|
||||
zplTemplates: {
|
||||
title: 'ZPL-Template Management',
|
||||
description: 'Für die unterschiedlichen Etikettentypen wurden ZPL-Templates implementiert:',
|
||||
code: `def generate_zpl_code(artikelnr, description, ean, price, material, water_resistance, glass_type, encoded_epc):
|
||||
formatted_price = f'{price:.2f}'
|
||||
return f'''
|
||||
CT~~CD,~CC^~CT~
|
||||
^XA
|
||||
~TA000
|
||||
~JSN
|
||||
^LT35
|
||||
^MNW
|
||||
^MTT
|
||||
^PON
|
||||
^PMN
|
||||
^LH0,0
|
||||
^JMA
|
||||
^PR2,2
|
||||
~SD23
|
||||
^JUS
|
||||
^LRN
|
||||
^CI27
|
||||
^PA0,1,1,0
|
||||
^RS8,,,3
|
||||
^XZ
|
||||
^XA
|
||||
^MMT
|
||||
^PW413
|
||||
^LL531
|
||||
^LS-24
|
||||
^FT150,57^A0N,33,33^FH\\^CI27^FD{artikelnr}^FS^CI27
|
||||
^FT44,86^A0N,21,20^FH\\^CI27^FD{description}^FS^CI27
|
||||
^FT130,141^A0N,50,51^FH\\^CI27^FD{formatted_price} €^FS^CI27
|
||||
^FT167,175^A0N,21,20^FH\\^CI27^FD{material}^FS^CI27
|
||||
^FT185,201^A0N,21,20^FH\\^CI27^FD{water_resistance}^FS^CI27
|
||||
^FT155,227^A0N,21,20^FH\\^CI27^FD{glass_type}^FS^CI27
|
||||
^BY3,2,113^FT73,420^BEN,,Y,N
|
||||
^FH\\^FD{ean}^FS
|
||||
^RFW,H,1,2,1^FD3000^FS
|
||||
^RFW,H,2,12,1^FD{encoded_epc}^FS
|
||||
^PQ1,0,1,Y
|
||||
^XZ'''`
|
||||
},
|
||||
printerCommunication: {
|
||||
title: 'Netzwerkkommunikation mit dem Drucker',
|
||||
description: 'Die Kommunikation mit dem Zebra-Drucker erfolgt über TCP/IP:',
|
||||
code: `def send_to_printer(data, printer_ip='192.168.68.50', printer_port=9100):
|
||||
try:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.connect((printer_ip, printer_port))
|
||||
sock.sendall(data.encode('utf-8'))
|
||||
logger.info('Daten erfolgreich an den Drucker gesendet')
|
||||
except Exception as e:
|
||||
logger.error(f'Fehler beim Senden der Daten an den Drucker: {e}')`
|
||||
},
|
||||
serialNumberManagement: {
|
||||
title: 'Datenprozessierung und Seriennummernverwaltung',
|
||||
description: 'Die Verwaltung von Seriennummern ist kritisch für die Eindeutigkeit der EPC-Codes:',
|
||||
code: `def initialize_serial_number():
|
||||
global current_serial_number
|
||||
try:
|
||||
serial_log_content = SERIAL_NUMBER_LOG_PATH.read_text().strip()
|
||||
current_serial_number = int(serial_log_content)
|
||||
except (FileNotFoundError, ValueError):
|
||||
current_serial_number = START_SERIAL_NUMBER
|
||||
def get_next_serial_number():
|
||||
global current_serial_number
|
||||
current_serial_number += 1
|
||||
return current_serial_number
|
||||
def finalize_serial_number():
|
||||
SERIAL_NUMBER_LOG_PATH.write_text(str(current_serial_number))`
|
||||
}
|
||||
},
|
||||
features: {
|
||||
title: 'Implementierte Features',
|
||||
errorHandling: {
|
||||
title: '1. Robuste Fehlerbehandlung',
|
||||
points: [
|
||||
'Validierung der Eingabedaten',
|
||||
'Überprüfung der Netzwerkverbindung',
|
||||
'Persistenz von Seriennummern',
|
||||
'Detailliertes Logging aller Operationen'
|
||||
]
|
||||
},
|
||||
configurability: {
|
||||
title: '2. Konfigurierbarkeit',
|
||||
points: [
|
||||
'Drucker-IP und Port einstellbar',
|
||||
'Anpassbare ZPL-Templates',
|
||||
'Flexible EPC-Code-Generierung',
|
||||
'Konfigurierbare Seriennummernbereiche'
|
||||
]
|
||||
},
|
||||
scalability: {
|
||||
title: '3. Skalierbarkeit',
|
||||
points: [
|
||||
'Batch-Verarbeitung von Produktdaten',
|
||||
'Parallele Druckaufträge möglich',
|
||||
'Effizientes Ressourcenmanagement',
|
||||
'Modularer Code für einfache Erweiterbarkeit'
|
||||
]
|
||||
}
|
||||
},
|
||||
bestPractices: {
|
||||
title: 'Best Practices',
|
||||
dataValidation: {
|
||||
title: '1. Datenvalidierung',
|
||||
points: [
|
||||
'Strict typing für kritische Datenfelder',
|
||||
'Überprüfung von Pflichtfeldern',
|
||||
'Format- und Plausibilitätsprüfungen'
|
||||
]
|
||||
},
|
||||
faultTolerance: {
|
||||
title: '2. Fehlertoleranz',
|
||||
points: [
|
||||
'Automatische Wiederholungsversuche',
|
||||
'Graceful Degradation',
|
||||
'Detaillierte Fehlerprotokolle'
|
||||
]
|
||||
},
|
||||
maintainability: {
|
||||
title: '3. Wartbarkeit',
|
||||
points: [
|
||||
'Modularer Code-Aufbau',
|
||||
'Ausführliche Dokumentation',
|
||||
'Klare Trennung von Konfiguration und Code'
|
||||
]
|
||||
}
|
||||
},
|
||||
lessonsLearned: {
|
||||
title: 'Lessons Learned',
|
||||
zplSpecifics: {
|
||||
title: '1. ZPL-Spezifika',
|
||||
points: [
|
||||
'Genaue Kenntnis der ZPL-Spezifikationen notwendig',
|
||||
'Sorgfältige Validierung der generierten ZPL-Codes',
|
||||
'Regelmäßige Tests mit verschiedenen Druckermodellen'
|
||||
]
|
||||
},
|
||||
rfidStandards: {
|
||||
title: '2. RFID-Standards',
|
||||
points: [
|
||||
'Einhaltung der EPC-Standards kritisch',
|
||||
'Sorgfältige Verwaltung von Seriennummern',
|
||||
'Validierung der generierten EPC-Codes'
|
||||
]
|
||||
},
|
||||
networkCommunication: {
|
||||
title: '3. Netzwerkkommunikation',
|
||||
points: [
|
||||
'Robuste Fehlerbehandlung bei Netzwerkproblemen',
|
||||
'Timeouts und Wiederholungsversuche',
|
||||
'Pufferung von Druckaufträgen'
|
||||
]
|
||||
}
|
||||
},
|
||||
conclusion: {
|
||||
title: 'Fazit',
|
||||
description: 'Die implementierte Lösung ermöglicht eine effiziente und zuverlässige Automatisierung des RFID-Etikettierungsprozesses. Durch die Kombination von EPC-Code-Generierung, ZPL-Template-Management und direkter Druckerkommunikation wurde ein robustes System geschaffen, das sich in der Praxis bewährt hat.',
|
||||
keyPoints: [
|
||||
'Gründliche Planung der Systemarchitektur',
|
||||
'Umfassende Fehlerbehandlung',
|
||||
'Sorgfältige Dokumentation',
|
||||
'Regelmäßige Tests und Validierung'
|
||||
],
|
||||
results: 'Die Lösung läuft seit mehreren Monaten stabil im Produktivbetrieb und verarbeitet täglich hunderte von Etiketten.'
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
export const common = {
|
||||
// SEO & Meta
|
||||
siteTitle: 'Damjan Savić - Digital Solutions & JTL Integration',
|
||||
siteDescription: 'Entwickler individueller Lösungen zur Automatisierung von Prozessen',
|
||||
// Navigation
|
||||
nav: {
|
||||
home: 'Start',
|
||||
about: 'Über mich',
|
||||
services: 'Leistungen',
|
||||
portfolio: 'Portfolio',
|
||||
blog: 'Blog',
|
||||
contact: 'Kontakt'
|
||||
},
|
||||
// Common Actions
|
||||
actions: {
|
||||
readMore: 'Weiterlesen',
|
||||
viewMore: 'Mehr anzeigen',
|
||||
viewAll: 'Alle anzeigen',
|
||||
back: 'Zurück',
|
||||
close: 'Schließen',
|
||||
submit: 'Absenden',
|
||||
loading: 'Lädt...'
|
||||
},
|
||||
// UI Components
|
||||
ui: {
|
||||
published: 'Veröffentlicht am',
|
||||
lastUpdated: 'Zuletzt aktualisiert am',
|
||||
category: 'Kategorie',
|
||||
categories: 'Kategorien',
|
||||
tag: 'Tag',
|
||||
tags: 'Tags',
|
||||
author: 'Autor',
|
||||
minuteRead: 'Minuten Lesezeit',
|
||||
tableOfContents: 'Inhaltsverzeichnis'
|
||||
},
|
||||
// Error Messages
|
||||
errors: {
|
||||
generic: 'Ein Fehler ist aufgetreten',
|
||||
notFound: 'Seite nicht gefunden',
|
||||
loading: 'Fehler beim Laden',
|
||||
return: 'Zurück zur Startseite'
|
||||
},
|
||||
// Loading States
|
||||
loading: {
|
||||
content: 'Inhalt wird geladen',
|
||||
page: 'Seite wird geladen',
|
||||
processing: 'Wird verarbeitet'
|
||||
},
|
||||
// Dates
|
||||
dates: {
|
||||
months: {
|
||||
long: [
|
||||
'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
|
||||
'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'
|
||||
],
|
||||
short: [
|
||||
'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun',
|
||||
'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'
|
||||
]
|
||||
},
|
||||
weekdays: {
|
||||
long: [
|
||||
'Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
|
||||
'Donnerstag', 'Freitag', 'Samstag'
|
||||
],
|
||||
short: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
|
||||
}
|
||||
},
|
||||
// Social Media
|
||||
social: {
|
||||
followMe: 'Folgen Sie mir auf',
|
||||
shareOn: 'Teilen auf',
|
||||
linkedin: 'LinkedIn',
|
||||
github: 'GitHub',
|
||||
email: 'E-Mail'
|
||||
},
|
||||
// Contact Form
|
||||
contact: {
|
||||
title: 'Kontakt',
|
||||
name: 'Name',
|
||||
email: 'E-Mail',
|
||||
message: 'Nachricht',
|
||||
submit: 'Nachricht senden',
|
||||
success: 'Ihre Nachricht wurde erfolgreich gesendet',
|
||||
error: 'Es gab einen Fehler beim Senden Ihrer Nachricht'
|
||||
},
|
||||
// Accessibility
|
||||
a11y: {
|
||||
skipToContent: 'Zum Hauptinhalt springen',
|
||||
menuOpen: 'Menü öffnen',
|
||||
menuClose: 'Menü schließen',
|
||||
darkMode: 'Dark Mode umschalten',
|
||||
carousel: {
|
||||
next: 'Nächstes Bild',
|
||||
previous: 'Vorheriges Bild'
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
export type CommonTranslations = typeof common;
|
||||
@@ -0,0 +1,9 @@
|
||||
const cookiebanner = {
|
||||
cookies: {
|
||||
message: "Diese Website verwendet Cookies, um Ihr Browsing-Erlebnis zu verbessern. Die Daten werden nicht an Dritte weitergegeben.",
|
||||
accept: "Cookies akzeptieren",
|
||||
decline: "Ablehnen"
|
||||
}
|
||||
};
|
||||
|
||||
export default cookiebanner;
|
||||
@@ -0,0 +1,40 @@
|
||||
// src/i18n/locales/de/footer.ts
|
||||
const footer = {
|
||||
sections: {
|
||||
contact: {
|
||||
title: "Kontakt",
|
||||
email: "info@damjan-savic.com",
|
||||
location: "Köln, Deutschland",
|
||||
aria: {
|
||||
emailLink: "E-Mail senden",
|
||||
locationText: "Standort"
|
||||
}
|
||||
},
|
||||
navigation: {
|
||||
title: "Navigation",
|
||||
links: {
|
||||
portfolio: "Portfolio",
|
||||
blog: "Blog",
|
||||
about: "Über mich",
|
||||
contact: "Kontakt"
|
||||
}
|
||||
},
|
||||
social: {
|
||||
title: "Social Media",
|
||||
aria: {
|
||||
linkedin: "Besuchen Sie mein LinkedIn Profil",
|
||||
github: "Besuchen Sie mein GitHub Profil"
|
||||
}
|
||||
}
|
||||
},
|
||||
legal: {
|
||||
copyright: "Alle Rechte vorbehalten",
|
||||
links: {
|
||||
privacy: "Datenschutz",
|
||||
terms: "Impressum"
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
|
||||
export default footer;
|
||||
export type FooterTranslations = typeof footer;
|
||||
@@ -0,0 +1,109 @@
|
||||
// src/i18n/locales/de/index.ts
|
||||
|
||||
// Blog post translations
|
||||
import { erpIntegrationBreuninger } from './blog/posts/erp-integration-breuninger';
|
||||
import { fullstackDevelopmentTimetracking } from './blog/posts/fullstack-development-timetracking';
|
||||
import { rfidAutomation as blogRfidAutomation } from './blog/posts/rfid-automation';
|
||||
import { blog } from './blog/index';
|
||||
|
||||
// Page translations
|
||||
import { about } from './pages/about/index';
|
||||
import { contact } from './pages/contact/index';
|
||||
import { dashboard } from './pages/dashboard';
|
||||
import { home } from './pages/home';
|
||||
import { login } from './pages/login';
|
||||
import { notfound } from './pages/notfound';
|
||||
import { portfolio as portfolioPage } from './pages/portfolio';
|
||||
import { privacy } from './pages/privacy';
|
||||
import { terms } from './pages/terms';
|
||||
|
||||
// Portfolio project translations
|
||||
import { aiDataReader } from './portfolio/projects/ai-data-reader';
|
||||
import { portfolio } from './portfolio/index';
|
||||
|
||||
// Common translations and configurations
|
||||
import { common } from './common';
|
||||
import { meta } from './meta';
|
||||
import { navigation } from './navigation';
|
||||
|
||||
// Footer translations
|
||||
import footer from './footer';
|
||||
|
||||
// Zusammenführung aller Übersetzungsobjekte
|
||||
const translations = {
|
||||
// Pages
|
||||
pages: {
|
||||
about,
|
||||
contact,
|
||||
dashboard,
|
||||
home,
|
||||
login,
|
||||
notfound,
|
||||
portfolio: portfolioPage,
|
||||
privacy,
|
||||
terms,
|
||||
},
|
||||
// Blog
|
||||
blog: {
|
||||
...blog,
|
||||
posts: {
|
||||
erpIntegrationBreuninger,
|
||||
fullstackDevelopmentTimetracking,
|
||||
rfidAutomation: blogRfidAutomation,
|
||||
},
|
||||
},
|
||||
// Portfolio
|
||||
portfolio: {
|
||||
...portfolio,
|
||||
projects: {
|
||||
aiDataReader,
|
||||
},
|
||||
},
|
||||
// Footer
|
||||
footer,
|
||||
// Gemeinsame Konfigurationen
|
||||
common: {
|
||||
...common,
|
||||
cookies: {
|
||||
message: "Diese Website verwendet Cookies, um Ihr Browsing-Erlebnis zu verbessern. Die Daten werden nicht an Dritte weitergegeben.",
|
||||
accept: "Cookies akzeptieren",
|
||||
decline: "Ablehnen"
|
||||
}
|
||||
},
|
||||
meta,
|
||||
navigation,
|
||||
} as const;
|
||||
|
||||
// Default-Export: komplettes Übersetzungsobjekt
|
||||
export default translations;
|
||||
|
||||
// Typdefinition der Übersetzungen
|
||||
export type Translations = typeof translations;
|
||||
|
||||
// Re-Exports für den direkten Zugriff auf einzelne Module
|
||||
export {
|
||||
// Pages
|
||||
about,
|
||||
contact,
|
||||
dashboard,
|
||||
home,
|
||||
login,
|
||||
notfound,
|
||||
portfolioPage as portfolioPageTranslations,
|
||||
privacy,
|
||||
terms,
|
||||
// Blog
|
||||
blog,
|
||||
erpIntegrationBreuninger,
|
||||
fullstackDevelopmentTimetracking,
|
||||
blogRfidAutomation as blogRfidAutomationPost,
|
||||
// Portfolio
|
||||
portfolio,
|
||||
aiDataReader,
|
||||
// Footer
|
||||
footer,
|
||||
// Common
|
||||
common,
|
||||
meta,
|
||||
navigation,
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
export const meta = {
|
||||
site: {
|
||||
name: 'Damjan Savić',
|
||||
title: 'Damjan Savić - Digital Solutions & JTL Integration',
|
||||
subtitle: 'Entwickler individueller Lösungen zur Automatisierung von Prozessen',
|
||||
description: 'Mit einem Hintergrund in der Softwareentwicklung und Expertise in der digitalen Transformation unterstütze ich Unternehmen bei der Optimierung und Automatisierung ihrer Geschäftsprozesse.',
|
||||
keywords: [
|
||||
'JTL Integration',
|
||||
'E-Commerce Lösungen',
|
||||
'Prozessautomatisierung',
|
||||
'Digitale Beratung',
|
||||
'ERP Systeme',
|
||||
'Python Entwicklung',
|
||||
'Systemintegration',
|
||||
'Digitales Marketing'
|
||||
].join(', ')
|
||||
},
|
||||
company: {
|
||||
name: 'CoderConda',
|
||||
shortName: 'CoderConda',
|
||||
description: 'Ihr JTL-Servicepartner für schnelle, verbindliche und kosteneffiziente Lösungen.',
|
||||
address: 'Rotdornallee',
|
||||
city: 'Köln',
|
||||
postalCode: '50999',
|
||||
country: 'Deutschland',
|
||||
phone: '+49 175 695 0979',
|
||||
email: 'info@damjan-savic.com',
|
||||
website: 'www.damjan-savic.com'
|
||||
},
|
||||
author: {
|
||||
name: 'Damjan Savić',
|
||||
role: 'Consultant Digital Solutions',
|
||||
company: 'CoderConda',
|
||||
location: 'Köln, Deutschland',
|
||||
email: 'info@damjan-savic.com',
|
||||
website: 'https://www.damjan-savic.com',
|
||||
languages: [
|
||||
{ code: 'en', level: 'C2', name: 'Englisch' },
|
||||
{ code: 'sr', level: 'C2', name: 'Serbisch' },
|
||||
{ code: 'de', level: 'C2', name: 'Deutsch' },
|
||||
{ code: 'fr', level: 'B2', name: 'Französisch' },
|
||||
{ code: 'es', level: 'B2', name: 'Spanisch' },
|
||||
{ code: 'ru', level: 'A1', name: 'Russisch' }
|
||||
]
|
||||
},
|
||||
social: {
|
||||
linkedin: 'https://www.linkedin.com/in/damjansavic/',
|
||||
github: 'https://github.com/damjansavic',
|
||||
email: 'info@damjan-savic.com'
|
||||
},
|
||||
expertise: {
|
||||
areas: [
|
||||
'JTL Integration & Beratung',
|
||||
'Prozessautomatisierung',
|
||||
'E-Commerce Entwicklung',
|
||||
'Systemintegration',
|
||||
'ERP-Systeme',
|
||||
'Digitale Transformation'
|
||||
],
|
||||
technologies: [
|
||||
'Python',
|
||||
'React/Next.js',
|
||||
'MariaDB',
|
||||
'Docker',
|
||||
'JTL-WaWi',
|
||||
'Shopify',
|
||||
'Shopware'
|
||||
]
|
||||
},
|
||||
seo: {
|
||||
defaultLanguage: 'de',
|
||||
alternateLanguages: ['en', 'sr'],
|
||||
robots: 'index, follow',
|
||||
googleSiteVerification: '', // Falls benötigt
|
||||
og: {
|
||||
type: 'website',
|
||||
locale: 'de_DE',
|
||||
siteName: 'Damjan Savić - Digital Solutions',
|
||||
images: {
|
||||
url: '/images/og-image.jpg',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'Damjan Savić - Digital Solutions & JTL Integration'
|
||||
}
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
site: '@damjansavic',
|
||||
creator: '@damjansavic'
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
export type MetaConfig = typeof meta;
|
||||
@@ -0,0 +1,79 @@
|
||||
// C:\Development\Damjan Savic\Portfolio\src\i18n\locales\de\navigation.ts
|
||||
export const navigation = {
|
||||
// Hauptnavigation
|
||||
main: {
|
||||
home: 'Startseite',
|
||||
about: 'Über mich',
|
||||
portfolio: 'Portfolio',
|
||||
blog: 'Blog',
|
||||
contact: 'Kontakt'
|
||||
},
|
||||
// Dashboard und Admin
|
||||
admin: {
|
||||
login: 'Anmelden',
|
||||
dashboard: 'Dashboard',
|
||||
logout: 'Abmelden'
|
||||
},
|
||||
// Footer Navigation
|
||||
footer: {
|
||||
legal: {
|
||||
privacy: 'Datenschutz',
|
||||
terms: 'AGB',
|
||||
imprint: 'Impressum'
|
||||
},
|
||||
sections: {
|
||||
portfolio: 'Portfolio',
|
||||
blog: 'Blog',
|
||||
contact: 'Kontakt'
|
||||
}
|
||||
},
|
||||
// Seitennavigation
|
||||
sections: {
|
||||
experience: 'Erfahrung',
|
||||
skills: 'Fähigkeiten',
|
||||
projects: 'Projekte',
|
||||
about: 'Über mich'
|
||||
},
|
||||
// Breadcrumbs und zurück-Navigation
|
||||
navigation: {
|
||||
backTo: {
|
||||
home: 'Zurück zur Startseite',
|
||||
portfolio: 'Zurück zum Portfolio',
|
||||
blog: 'Zurück zum Blog'
|
||||
},
|
||||
breadcrumbs: {
|
||||
home: 'Startseite',
|
||||
portfolio: 'Portfolio',
|
||||
blog: 'Blog',
|
||||
about: 'Über mich',
|
||||
contact: 'Kontakt'
|
||||
}
|
||||
},
|
||||
// Mobile Navigation
|
||||
mobile: {
|
||||
menu: 'Menü',
|
||||
close: 'Schließen',
|
||||
open: 'Menü öffnen'
|
||||
},
|
||||
// URLs (für dynamische Route-Generierung)
|
||||
urls: {
|
||||
home: '/',
|
||||
about: '/about',
|
||||
portfolio: '/portfolio',
|
||||
blog: '/blog',
|
||||
contact: '/contact',
|
||||
login: '/login',
|
||||
dashboard: '/dashboard',
|
||||
privacy: '/privacy',
|
||||
terms: '/terms'
|
||||
},
|
||||
// Meta-Informationen für Navigation
|
||||
meta: {
|
||||
main: 'Hauptnavigation',
|
||||
footer: 'Footer Navigation',
|
||||
social: 'Social Media Navigation',
|
||||
legal: 'Rechtliche Navigation'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export type NavigationConfig = typeof navigation;
|
||||
@@ -0,0 +1,33 @@
|
||||
export const hero = {
|
||||
// Navigation/Header
|
||||
aboutMe: 'ÜBER MICH',
|
||||
// Main Section
|
||||
title: 'Digital Solutions Experte',
|
||||
description: 'Mit einem Hintergrund in Softwareentwicklung und Expertise in digitaler Transformation helfe ich Unternehmen ihre Prozesse durch innovative Lösungen zu optimieren und zu automatisieren.',
|
||||
// Expertise Areas
|
||||
expertise: {
|
||||
processAutomation: {
|
||||
title: 'Prozessautomatisierung',
|
||||
description: 'Entwicklung effizienter automatisierter Workflows'
|
||||
},
|
||||
systemIntegration: {
|
||||
title: 'Systemintegration',
|
||||
description: 'Verbindung und Optimierung von Geschäftssystemen'
|
||||
},
|
||||
customDevelopment: {
|
||||
title: 'Individuelle Entwicklung',
|
||||
description: 'Erstellung maßgeschneiderter Softwarelösungen'
|
||||
}
|
||||
},
|
||||
// Languages
|
||||
languages: {
|
||||
english: 'Englisch',
|
||||
serbian: 'Serbisch',
|
||||
german: 'Deutsch',
|
||||
french: 'Französisch',
|
||||
spanish: 'Spanisch',
|
||||
russian: 'Russisch'
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type HeroTranslations = typeof hero;
|
||||
@@ -0,0 +1,24 @@
|
||||
import { hero } from './hero';
|
||||
import { journey } from './journey';
|
||||
import { schema } from './schema';
|
||||
import { skillbar } from './skillbar';
|
||||
import { skillgroup } from './skillgroup';
|
||||
import { skills } from './skills';
|
||||
import { workflow } from './workflow';
|
||||
export const about = {
|
||||
hero,
|
||||
journey,
|
||||
schema,
|
||||
skillbar,
|
||||
skillgroup,
|
||||
skills,
|
||||
workflow
|
||||
} as const;
|
||||
// Typen exportieren
|
||||
export type { HeroTranslations } from './hero';
|
||||
export type { JourneyTranslations } from './journey';
|
||||
export type { SchemaTranslations } from './schema';
|
||||
export type { SkillBarTranslations } from './skillbar';
|
||||
export type { SkillGroupTranslations } from './skillgroup';
|
||||
export type { SkillsTranslations } from './skills';
|
||||
export type { WorkflowTranslations } from './workflow';
|
||||
@@ -0,0 +1,95 @@
|
||||
export const journey = {
|
||||
// Header
|
||||
title: 'Beruflicher Werdegang',
|
||||
subtitle: 'Von digitalen Medien zu Unternehmenslösungen',
|
||||
// Education Section
|
||||
education: {
|
||||
title: 'Ausbildung',
|
||||
degrees: {
|
||||
masters: {
|
||||
degree: 'M.A. Softwareentwicklung',
|
||||
university: 'Middlesex University, London',
|
||||
period: '2020 - 2022'
|
||||
},
|
||||
bachelors: {
|
||||
degree: 'B.A. Cross-Media Produktion',
|
||||
university: 'Middlesex University, London',
|
||||
period: '2018 - 2020'
|
||||
}
|
||||
}
|
||||
},
|
||||
// Languages Section
|
||||
languages: {
|
||||
title: 'Sprachen',
|
||||
items: {
|
||||
english: {
|
||||
name: 'Englisch',
|
||||
level: 'C2'
|
||||
},
|
||||
serbian: {
|
||||
name: 'Serbisch',
|
||||
level: 'C2'
|
||||
},
|
||||
german: {
|
||||
name: 'Deutsch',
|
||||
level: 'C2'
|
||||
},
|
||||
french: {
|
||||
name: 'Französisch',
|
||||
level: 'B2'
|
||||
},
|
||||
spanish: {
|
||||
name: 'Spanisch',
|
||||
level: 'B2'
|
||||
},
|
||||
russian: {
|
||||
name: 'Russisch',
|
||||
level: 'A1'
|
||||
}
|
||||
}
|
||||
},
|
||||
// Work History
|
||||
work: {
|
||||
positions: [
|
||||
{
|
||||
period: '08/2023 - Heute',
|
||||
company: 'Ritter Digital GmbH',
|
||||
title: 'Digital Solutions Consultant',
|
||||
location: 'Oberhausen',
|
||||
highlights: [
|
||||
'ERP-Beratung und -Implementierung (JTL WaWi)',
|
||||
'Prozessautomatisierung & Full-Stack-Entwicklung',
|
||||
'RFID-Technologie & Automatisierung',
|
||||
'Lead-Generierung & -Management',
|
||||
'KI-gestütztes Content-Management'
|
||||
]
|
||||
},
|
||||
{
|
||||
period: '02/2023 - 08/2023',
|
||||
company: 'Joyce & Girls Co AG',
|
||||
title: 'ERP Integration Specialist',
|
||||
location: 'Köln',
|
||||
highlights: [
|
||||
'Komplexe Systemintegration (Apparel Magic, TradeByte)',
|
||||
'Server-Administration und Automatisierung',
|
||||
'Datenbank- und API-Entwicklung',
|
||||
'Digitales Marketing und Kampagnenanalyse'
|
||||
]
|
||||
},
|
||||
{
|
||||
period: '08/2022 - 01/2023',
|
||||
company: 'Magnarius',
|
||||
title: 'RPA Developer & E-Commerce Manager',
|
||||
location: 'Bergisch Gladbach',
|
||||
highlights: [
|
||||
'Shopware 6 Entwicklung und JTL-Integration',
|
||||
'Google Ads Automatisierung',
|
||||
'CMS-Management und -Optimierung',
|
||||
'SEO-Strategieumsetzung'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type JourneyTranslations = typeof journey;
|
||||
@@ -0,0 +1,31 @@
|
||||
export const schema = {
|
||||
page: {
|
||||
name: 'Über Damjan Savić',
|
||||
description: 'Erfahren Sie mehr über Damjan Savić, einen zertifizierten JTL-Experten mit umfassender Erfahrung in E-Commerce und Warenwirtschaftslösungen.'
|
||||
},
|
||||
person: {
|
||||
jobTitle: 'JTL Integrations-Experte',
|
||||
description: 'Mit umfangreicher Erfahrung in der Integration und Optimierung von E-Commerce-Systemen unterstütze ich Unternehmen bei der digitalen Transformation ihrer Geschäftsprozesse.',
|
||||
languages: {
|
||||
english: 'Englisch',
|
||||
serbian: 'Serbisch',
|
||||
german: 'Deutsch',
|
||||
french: 'Französisch',
|
||||
spanish: 'Spanisch',
|
||||
russian: 'Russisch'
|
||||
},
|
||||
skills: {
|
||||
python: 'Python',
|
||||
googleAds: 'Google Ads',
|
||||
metaAds: 'Meta Ads',
|
||||
shopware: 'Shopware',
|
||||
shopify: 'Shopify',
|
||||
wooCommerce: 'WooCommerce',
|
||||
jtlWawi: 'JTL WAWI',
|
||||
serverAdmin: 'Server-Administration',
|
||||
airflow: 'AirFlow'
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type SchemaTranslations = typeof schema;
|
||||
@@ -0,0 +1,13 @@
|
||||
export const skillbar = {
|
||||
// Accessibility labels
|
||||
ariaLabel: {
|
||||
skillLevel: 'Fähigkeitsniveau',
|
||||
progressBar: 'Fortschrittsbalken'
|
||||
},
|
||||
// Screen reader text
|
||||
screenReader: {
|
||||
progress: '{{level}} Prozent Fortschritt für {{skill}}'
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type SkillBarTranslations = typeof skillbar;
|
||||
@@ -0,0 +1,63 @@
|
||||
export const skillgroup = {
|
||||
// Kategorien
|
||||
categories: {
|
||||
development: 'Entwicklung',
|
||||
ecommerce: 'E-Commerce',
|
||||
marketing: 'Marketing',
|
||||
automation: 'Automatisierung',
|
||||
languages: 'Programmiersprachen',
|
||||
databases: 'Datenbanken'
|
||||
},
|
||||
// Skills nach Kategorien
|
||||
skills: {
|
||||
development: {
|
||||
frontend: 'Frontend-Entwicklung',
|
||||
backend: 'Backend-Entwicklung',
|
||||
fullstack: 'Full-Stack-Entwicklung',
|
||||
api: 'API-Entwicklung',
|
||||
testing: 'Software-Testing'
|
||||
},
|
||||
ecommerce: {
|
||||
jtl: 'JTL WaWi',
|
||||
shopware: 'Shopware',
|
||||
shopify: 'Shopify',
|
||||
woocommerce: 'WooCommerce',
|
||||
magento: 'Magento'
|
||||
},
|
||||
marketing: {
|
||||
seo: 'Suchmaschinenoptimierung',
|
||||
sea: 'Suchmaschinenwerbung',
|
||||
analytics: 'Web-Analyse',
|
||||
googleAds: 'Google Ads',
|
||||
metaAds: 'Meta Ads'
|
||||
},
|
||||
automation: {
|
||||
rpa: 'Robotergestützte Prozessautomatisierung',
|
||||
workflow: 'Workflow-Automatisierung',
|
||||
cicd: 'CI/CD',
|
||||
testing: 'Test-Automatisierung',
|
||||
deployment: 'Deployment-Automatisierung'
|
||||
},
|
||||
languages: {
|
||||
python: 'Python',
|
||||
javascript: 'JavaScript',
|
||||
typescript: 'TypeScript',
|
||||
php: 'PHP',
|
||||
sql: 'SQL'
|
||||
},
|
||||
databases: {
|
||||
mysql: 'MySQL',
|
||||
postgresql: 'PostgreSQL',
|
||||
mongodb: 'MongoDB',
|
||||
redis: 'Redis',
|
||||
elasticsearch: 'Elasticsearch'
|
||||
}
|
||||
},
|
||||
// Accessibility
|
||||
ariaLabels: {
|
||||
skillGroup: 'Fähigkeitsgruppe',
|
||||
skillList: 'Liste der Fähigkeiten in dieser Kategorie'
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type SkillGroupTranslations = typeof skillgroup;
|
||||
@@ -0,0 +1,46 @@
|
||||
// de/pages/about/skills.ts
|
||||
export const skills = {
|
||||
title: 'Fähigkeiten',
|
||||
skillGroups: [
|
||||
{
|
||||
category: 'Entwicklung',
|
||||
items: [
|
||||
{ name: 'Python', level: 90 },
|
||||
{ name: 'Google Ads', level: 85 },
|
||||
{ name: 'Meta Ads', level: 85 }
|
||||
]
|
||||
},
|
||||
{
|
||||
category: 'E-Commerce',
|
||||
items: [
|
||||
{ name: 'Shopware', level: 85 },
|
||||
{ name: 'Shopify', level: 85 },
|
||||
{ name: 'WooCommerce', level: 85 }
|
||||
]
|
||||
},
|
||||
{
|
||||
category: 'Systemadministration',
|
||||
items: [
|
||||
{ name: 'JTL WAWI', level: 85 },
|
||||
{ name: 'Server', level: 75 },
|
||||
{ name: 'AirFlow', level: 60 }
|
||||
]
|
||||
}
|
||||
],
|
||||
ui: {
|
||||
percentage: 'Prozent',
|
||||
levelLabel: 'Niveau',
|
||||
skillLevel: '{{level}}% Beherrschung in {{skill}}'
|
||||
},
|
||||
aria: {
|
||||
skillGroup: 'Fähigkeitsgruppe für {{category}}',
|
||||
skillBar: 'Fortschrittsbalken für {{skill}}',
|
||||
skillIcon: 'Symbol für {{category}}',
|
||||
selectSkill: 'Fähigkeit auswählen'
|
||||
},
|
||||
screenReader: {
|
||||
skillProgress: '{{skill}} mit einem Niveau von {{level}} Prozent'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export type SkillsTranslations = typeof skills;
|
||||
@@ -0,0 +1,44 @@
|
||||
export const workflow = {
|
||||
// Seitentitel
|
||||
title: 'MEIN WORKFLOW',
|
||||
description: 'Systematischer Ansatz zur Softwareentwicklung durch definierte Schritte',
|
||||
// Workflow-Schritte
|
||||
steps: [
|
||||
{
|
||||
number: '01',
|
||||
title: 'ANFORDERUNGSANALYSE'
|
||||
},
|
||||
{
|
||||
number: '02',
|
||||
title: 'ABFRAGE VON DEADLINES UND EINSCHRÄNKUNGEN'
|
||||
},
|
||||
{
|
||||
number: '03',
|
||||
title: 'EINRICHTUNG DER ENTWICKLUNGSUMGEBUNG'
|
||||
},
|
||||
{
|
||||
number: '04',
|
||||
title: 'PROGRAMMIERUNG'
|
||||
},
|
||||
{
|
||||
number: '05',
|
||||
title: 'TESTEN DER ERGEBNISSE'
|
||||
},
|
||||
{
|
||||
number: '06',
|
||||
title: 'SUPPORT UND SKALIERUNG DES CODES'
|
||||
}
|
||||
],
|
||||
// Aria Labels für Barrierefreiheit
|
||||
aria: {
|
||||
workflowSection: 'Workflow-Prozess',
|
||||
stepNumber: 'Schritt {{number}}',
|
||||
stepDescription: 'Workflow-Schritt: {{title}}'
|
||||
},
|
||||
// Screen Reader Texte
|
||||
screenReader: {
|
||||
stepProgress: 'Schritt {{number}} von {{total}}: {{title}}'
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type WorkflowTranslations = typeof workflow;
|
||||
@@ -0,0 +1,39 @@
|
||||
export const contactform = {
|
||||
// Formular Header
|
||||
title: 'Kontaktieren Sie mich',
|
||||
description: 'Haben Sie Fragen oder möchten Sie zusammenarbeiten? Schreiben Sie mir eine Nachricht.',
|
||||
// Formularfelder
|
||||
name: {
|
||||
label: 'Name',
|
||||
placeholder: 'Ihr vollständiger Name'
|
||||
},
|
||||
email: {
|
||||
label: 'E-Mail',
|
||||
placeholder: 'ihre.email@beispiel.de'
|
||||
},
|
||||
message: {
|
||||
label: 'Nachricht',
|
||||
placeholder: 'Ihre Nachricht an mich...'
|
||||
},
|
||||
// Button
|
||||
submit: 'Nachricht senden',
|
||||
// Statusmeldungen
|
||||
successMessage: 'Vielen Dank für Ihre Nachricht! Ich werde mich so schnell wie möglich bei Ihnen melden.',
|
||||
errorMessage: 'Entschuldigung, beim Senden Ihrer Nachricht ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.',
|
||||
// Fehlermeldungen
|
||||
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 eine Nachricht ein'
|
||||
},
|
||||
// Aria Labels
|
||||
aria: {
|
||||
form: 'Kontaktformular',
|
||||
submitting: 'Formular wird gesendet',
|
||||
successAlert: 'Erfolgsmeldung',
|
||||
errorAlert: 'Fehlermeldung'
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type ContactFormTranslations = typeof contactform;
|
||||
@@ -0,0 +1,25 @@
|
||||
export const contactinfo = {
|
||||
// Header
|
||||
title: 'Kontaktinformationen',
|
||||
description: 'Sie können mich über folgende Wege erreichen',
|
||||
// Kontaktmethoden Labels
|
||||
addressLabel: 'Bürostandort',
|
||||
phoneLabel: 'Telefon',
|
||||
emailLabel: 'E-Mail',
|
||||
// Kontaktinformationen
|
||||
address: 'Rotdornallee, Köln',
|
||||
phone: '+49 175 695 0979',
|
||||
email: 'info@damjan-savic.com',
|
||||
// Zusätzliche Informationen
|
||||
availabilityNote: 'Geschäftszeiten: Montag bis Freitag, 9:00 - 17:00 Uhr',
|
||||
// Aria Labels
|
||||
aria: {
|
||||
contactCard: 'Kontaktinformationskarte',
|
||||
addressLink: 'Öffne Standort in Google Maps',
|
||||
phoneLink: 'Anrufen',
|
||||
emailLink: 'E-Mail senden',
|
||||
externalLink: 'Öffnet in neuem Tab'
|
||||
}
|
||||
} as const;
|
||||
// Type für Typsicherheit
|
||||
export type ContactInfoTranslations = typeof contactinfo;
|
||||
@@ -0,0 +1,71 @@
|
||||
// src/i18n/locales/de/pages/contact/index.ts
|
||||
export const contact = {
|
||||
breadcrumb: "KONTAKT",
|
||||
hero: {
|
||||
title: "Lassen Sie uns zusammenarbeiten",
|
||||
subtitle: "Sie haben ein Projekt im Sinn? Lassen Sie uns besprechen, wie wir Ihnen bei der Erreichung Ihrer Ziele helfen können."
|
||||
},
|
||||
contactInfo: {
|
||||
title: "Kontaktinformationen",
|
||||
description: "Sie können mich über folgende Wege erreichen",
|
||||
address: {
|
||||
label: "Bürostandort",
|
||||
value: "Rotdornallee, Köln"
|
||||
},
|
||||
phone: {
|
||||
label: "Telefon",
|
||||
value: "+49 175 695 0979"
|
||||
},
|
||||
email: {
|
||||
label: "E-Mail",
|
||||
value: "info@damjan-savic.com"
|
||||
},
|
||||
availabilityNote: "Geschäftszeiten: Montag bis Freitag, 9:00 - 17:00 Uhr",
|
||||
aria: {
|
||||
contactCard: "Kontaktinformationskarte",
|
||||
addressLink: "Öffne Standort in Google Maps",
|
||||
phoneLink: "Anrufen",
|
||||
emailLink: "E-Mail senden",
|
||||
externalLink: "Öffnet in neuem Tab"
|
||||
}
|
||||
},
|
||||
contactForm: {
|
||||
title: "Kontaktieren Sie mich",
|
||||
description: "Haben Sie Fragen oder möchten Sie zusammenarbeiten? Schreiben Sie mir eine Nachricht.",
|
||||
name: {
|
||||
label: "Name",
|
||||
placeholder: "Ihr vollständiger Name"
|
||||
},
|
||||
email: {
|
||||
label: "E-Mail",
|
||||
placeholder: "ihre.email@beispiel.de"
|
||||
},
|
||||
message: {
|
||||
label: "Nachricht",
|
||||
placeholder: "Ihre Nachricht an mich..."
|
||||
},
|
||||
submit: "Nachricht senden",
|
||||
successMessage: "Vielen Dank für Ihre Nachricht! Ich werde mich so schnell wie möglich bei Ihnen melden.",
|
||||
errorMessage: "Entschuldigung, beim Senden Ihrer Nachricht ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.",
|
||||
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 eine Nachricht ein"
|
||||
},
|
||||
aria: {
|
||||
form: "Kontaktformular",
|
||||
submitting: "Formular wird gesendet",
|
||||
successAlert: "Erfolgsmeldung",
|
||||
errorAlert: "Fehlermeldung"
|
||||
}
|
||||
}
|
||||
} as const;
|
||||
|
||||
export type ContactTranslations = typeof contact;
|
||||
|
||||
export default {
|
||||
pages: {
|
||||
contact: contact
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
// src/i18n/locales/de/pages/dashboard.ts
|
||||
export const dashboard = {
|
||||
// SEO
|
||||
seo: {
|
||||
title: 'Analytics Dashboard',
|
||||
description: 'Website-Analysedashboard'
|
||||
},
|
||||
// Hauptüberschriften
|
||||
header: {
|
||||
title: 'Analytics Dashboard',
|
||||
activeUsers: 'aktive Nutzer'
|
||||
},
|
||||
// Metrikkarten
|
||||
metrics: {
|
||||
pageViews: {
|
||||
title: 'Seitenaufrufe',
|
||||
perMinute: 'pro Minute'
|
||||
},
|
||||
uniqueVisitors: {
|
||||
title: 'Eindeutige Besucher',
|
||||
currentlyActive: 'aktuell aktiv'
|
||||
},
|
||||
conversions: {
|
||||
title: 'Konversionen',
|
||||
rate: 'Konversionsrate'
|
||||
},
|
||||
timeOnSite: {
|
||||
title: 'Durchschn. Besuchszeit',
|
||||
bounceRate: 'Absprungrate'
|
||||
}
|
||||
},
|
||||
// Top-Seiten Bereich
|
||||
topPages: {
|
||||
title: 'Top-Seiten',
|
||||
columns: {
|
||||
path: 'Pfad',
|
||||
views: 'Aufrufe',
|
||||
change: 'Änderung'
|
||||
}
|
||||
},
|
||||
// Event-Tracking Bereich
|
||||
events: {
|
||||
title: 'Event-Tracking',
|
||||
types: {
|
||||
contactForm: 'Kontaktformular Absendung',
|
||||
portfolioView: 'Portfolio Ansicht',
|
||||
cvDownload: 'Lebenslauf Download',
|
||||
blogRead: 'Blog Gelesen'
|
||||
}
|
||||
},
|
||||
// Statusmeldungen
|
||||
status: {
|
||||
loading: 'Lade Dashboard...',
|
||||
error: 'Fehler beim Laden der Daten',
|
||||
notAuthenticated: 'Bitte melden Sie sich an'
|
||||
},
|
||||
// Sonstiges
|
||||
misc: {
|
||||
viewMore: 'Mehr anzeigen',
|
||||
refresh: 'Aktualisieren',
|
||||
period: {
|
||||
today: 'Heute',
|
||||
yesterday: 'Gestern',
|
||||
last7Days: 'Letzte 7 Tage',
|
||||
last30Days: 'Letzte 30 Tage',
|
||||
thisMonth: 'Dieser Monat',
|
||||
lastMonth: 'Letzter Monat'
|
||||
}
|
||||
},
|
||||
// Trends und Änderungen
|
||||
trends: {
|
||||
increase: 'Zunahme',
|
||||
decrease: 'Abnahme',
|
||||
noChange: 'Keine Änderung'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
// src/i18n/locales/de/pages/home/about.ts
|
||||
export const about = {
|
||||
title: 'Über Mich',
|
||||
content: 'Als Berater im Bereich der Digitalisierung helfe ich Unternehmen, ihre Abläufe durch moderne Software zu verbessern. Ich entwickle Lösungen zur Verbindung von Warenwirtschaftssystemen, Programme zur Automatisierung von Arbeitsabläufen und RFID-Anwendungen zur besseren Warenverfolgung. Bei der Ritter Digital GmbH arbeite ich mit JTL-Software und entwickle individuelle Programmlösungen. Ein weiteres Projekt war die Verbindung der Systeme von Breuninger mit Apparel Magic über TB.One. Mein Ziel ist es, Unternehmen durch Software effizienter zu machen.',
|
||||
image: {
|
||||
alt: 'Portrait von Damjan Savić'
|
||||
}
|
||||
} as const;
|
||||
export type AboutTranslations = typeof about;
|
||||
@@ -0,0 +1,77 @@
|
||||
// src/i18n/locales/de/pages/home/experience.ts
|
||||
export const experience = {
|
||||
title: 'Berufserfahrung',
|
||||
navigation: {
|
||||
prev: '←',
|
||||
next: '→'
|
||||
},
|
||||
positions: [
|
||||
{
|
||||
role: 'Consultant Digital Solutions & Developer',
|
||||
company: 'RITTER Gesellschaft für digitale Geschäftsprozesse mbH',
|
||||
period: '08/2023 - HEUTE',
|
||||
highlights: [
|
||||
'JTL WaWi, WMS und POS Beratung & Implementierung',
|
||||
'Python-basierte Automationslösungen',
|
||||
'RFID-Systeme und GUI-Entwicklung',
|
||||
'KI & Business Intelligence'
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'ERP-Integrationsspezialist & E-Commerce-Entwickler',
|
||||
company: 'Joyce & Girls',
|
||||
period: '01/2023 - 08/2023',
|
||||
highlights: [
|
||||
'ApparelMagic & TradeByte Integration',
|
||||
'MariaDB Middleware-Entwicklung',
|
||||
'Windows Server Administration',
|
||||
'Shopify-Optimierung'
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'RPA Developer & E-Commerce Manager',
|
||||
company: 'C&S Marketing',
|
||||
period: '08/2022 - 01/2023',
|
||||
highlights: [
|
||||
'Shopware 6 & JTL Integration',
|
||||
'Python Automatisierung',
|
||||
'Google Ads Optimierung',
|
||||
'CMS Management'
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'E-Commerce Developer',
|
||||
company: 'Brands Club GmbH',
|
||||
period: '08/2021 - 07/2022',
|
||||
highlights: [
|
||||
'Shopify & JTL Integration',
|
||||
'Server Administration',
|
||||
'Content Production',
|
||||
'Marketing Automation'
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'E-Commerce Developer',
|
||||
company: 'Feine Uhren Eupen',
|
||||
period: '01/2021 - 08/2021',
|
||||
highlights: [
|
||||
'Shopware 5 Development',
|
||||
'Produktfotografie',
|
||||
'Sales im Luxusuhrensegment',
|
||||
'E-Commerce Management'
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'Online Marketing Manager',
|
||||
company: 'Ufer8, Ambis, Teatro & Die Halle Tor 2',
|
||||
period: '01/2018 - 12/2020',
|
||||
highlights: [
|
||||
'Social Media Content',
|
||||
'Event Marketing',
|
||||
'Veranstaltungsorganisation',
|
||||
'Marketing Automation'
|
||||
]
|
||||
}
|
||||
]
|
||||
} as const;
|
||||
export type ExperienceTranslations = typeof experience;
|
||||
@@ -0,0 +1,27 @@
|
||||
// src/i18n/locales/de/pages/home/expertise.ts
|
||||
export const expertise = {
|
||||
title: 'Bereiche meiner Expertise',
|
||||
areas: [
|
||||
{
|
||||
title: 'ERP Integration',
|
||||
description: 'Expert für JTL-Wawi Implementierung, Konfiguration und Optimierung. Spezialisiert auf Warenwirtschaftssysteme und POS-Integration.',
|
||||
skills: ['JTL-Wawi', 'JTL-WMS', 'JTL-POS', 'Apparel Magic']
|
||||
},
|
||||
{
|
||||
title: 'Entwicklung',
|
||||
description: 'Full-Stack Entwicklung mit Fokus auf Python-Automatisierung, React Frontends und Datenbankdesign.',
|
||||
skills: ['Python', 'React/Next.js', 'MariaDB', 'Docker']
|
||||
},
|
||||
{
|
||||
title: 'E-Commerce',
|
||||
description: 'Umfangreiche Erfahrung mit verschiedenen E-Commerce-Plattformen und Marktplatz-Integrationen.',
|
||||
skills: ['Shopify', 'Shopware', 'WooCommerce', 'API Integration']
|
||||
},
|
||||
{
|
||||
title: 'Digitales Marketing',
|
||||
description: 'Strategischer Ansatz im digitalen Marketing mit Fokus auf Automatisierung und Analyse.',
|
||||
skills: ['Google Ads', 'Meta Ads', 'SEO', 'Analytics']
|
||||
}
|
||||
]
|
||||
} as const;
|
||||
export type ExpertiseTranslations = typeof expertise;
|
||||
@@ -0,0 +1,29 @@
|
||||
// src/i18n/locales/de/pages/home/hero.ts
|
||||
export const hero = {
|
||||
title: 'SOFTWARE ENGINEER',
|
||||
name: 'DAMJAN SAVIĆ',
|
||||
cta: 'KONTAKT AUFNEHMEN',
|
||||
image: {
|
||||
alt: 'Portrait von Damjan Savić'
|
||||
},
|
||||
social: {
|
||||
getInTouch: 'Kontaktieren Sie mich',
|
||||
linkedin: {
|
||||
title: 'Besuchen Sie mein LinkedIn Profil'
|
||||
},
|
||||
github: {
|
||||
title: 'Besuchen Sie mein GitHub Profil'
|
||||
},
|
||||
email: {
|
||||
title: 'Senden Sie mir eine E-Mail'
|
||||
}
|
||||
},
|
||||
navigation: {
|
||||
experience: 'ERFAHRUNG',
|
||||
skills: 'FÄHIGKEITEN',
|
||||
projects: 'PROJEKTE',
|
||||
about: 'ÜBER MICH'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export type HeroTranslations = typeof hero;
|
||||
@@ -0,0 +1,18 @@
|
||||
// src/i18n/locales/de/pages/home/index.ts
|
||||
import { hero } from './hero';
|
||||
import { about } from './about';
|
||||
import { experience } from './experience';
|
||||
import { expertise } from './expertise';
|
||||
import { skills } from './skills';
|
||||
import { projects } from './projects';
|
||||
|
||||
export const home = {
|
||||
hero,
|
||||
about,
|
||||
experience,
|
||||
expertise,
|
||||
skills,
|
||||
projects
|
||||
} as const;
|
||||
|
||||
export type HomeTranslations = typeof home;
|
||||
@@ -0,0 +1,10 @@
|
||||
// src/i18n/locales/de/pages/home/projects.ts
|
||||
export const projects = {
|
||||
title: 'Portfolio',
|
||||
viewAll: 'Alle Projekte →',
|
||||
loading: 'Projekte werden geladen...',
|
||||
error: {
|
||||
loading: 'Fehler beim Laden der Projekte'
|
||||
}
|
||||
} as const;
|
||||
export type ProjectsTranslations = typeof projects;
|
||||
@@ -0,0 +1,41 @@
|
||||
// src/i18n/locales/de/pages/home/skills.ts
|
||||
export const skills = {
|
||||
title: 'Fähigkeiten',
|
||||
skills: [
|
||||
{
|
||||
name: 'ERP',
|
||||
level: 90,
|
||||
description: 'Enterprise Resource Planning'
|
||||
},
|
||||
{
|
||||
name: 'Datenbank',
|
||||
level: 85,
|
||||
description: 'Datenbankentwicklung und -administration'
|
||||
},
|
||||
{
|
||||
name: 'E-Commerce',
|
||||
level: 95,
|
||||
description: 'Online-Handel und Plattformen'
|
||||
},
|
||||
{
|
||||
name: 'Python',
|
||||
level: 80,
|
||||
description: 'Programmiersprache Python'
|
||||
},
|
||||
{
|
||||
name: 'React',
|
||||
level: 75,
|
||||
description: 'Frontend-Entwicklung mit React'
|
||||
},
|
||||
{
|
||||
name: 'Server',
|
||||
level: 70,
|
||||
description: 'Server-Administration'
|
||||
}
|
||||
],
|
||||
aria: {
|
||||
skillLevel: 'Fähigkeitsniveau',
|
||||
selectSkill: 'Fähigkeit auswählen'
|
||||
}
|
||||
} as const;
|
||||
export type SkillsTranslations = typeof skills;
|
||||
@@ -0,0 +1,54 @@
|
||||
// src/i18n/locales/de/pages/login.ts
|
||||
export const login = {
|
||||
// SEO
|
||||
seo: {
|
||||
title: 'Login',
|
||||
description: 'Anmelden für Zugriff auf das Dashboard'
|
||||
},
|
||||
// Hauptüberschrift
|
||||
header: {
|
||||
title: 'Im Dashboard anmelden'
|
||||
},
|
||||
// Formular
|
||||
form: {
|
||||
// Felder
|
||||
email: {
|
||||
label: 'E-Mail-Adresse',
|
||||
placeholder: 'ihre.email@beispiel.de'
|
||||
},
|
||||
password: {
|
||||
label: 'Passwort',
|
||||
placeholder: 'Ihr Passwort'
|
||||
},
|
||||
// Buttons
|
||||
submit: {
|
||||
default: 'Anmelden',
|
||||
loading: 'Anmeldung läuft...'
|
||||
},
|
||||
// Fehlermeldungen
|
||||
errors: {
|
||||
default: 'Ein Fehler ist aufgetreten',
|
||||
invalidCredentials: 'Ungültige Anmeldedaten',
|
||||
emailRequired: 'Bitte geben Sie Ihre E-Mail-Adresse ein',
|
||||
passwordRequired: 'Bitte geben Sie Ihr Passwort ein',
|
||||
emailInvalid: 'Bitte geben Sie eine gültige E-Mail-Adresse ein'
|
||||
}
|
||||
},
|
||||
// Links und Hilfe
|
||||
help: {
|
||||
forgotPassword: 'Passwort vergessen?',
|
||||
needHelp: 'Benötigen Sie Hilfe?',
|
||||
contactSupport: 'Support kontaktieren'
|
||||
},
|
||||
// Statusmeldungen
|
||||
status: {
|
||||
authenticating: 'Authentifizierung...',
|
||||
success: 'Erfolgreich angemeldet',
|
||||
redirecting: 'Weiterleitung zum Dashboard...'
|
||||
},
|
||||
// Sicherheitshinweise
|
||||
security: {
|
||||
secureConnection: 'Sichere Verbindung',
|
||||
privacyNote: 'Ihre Daten werden verschlüsselt übertragen'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
// src/i18n/locales/de/pages/notfound.ts
|
||||
export const notfound = {
|
||||
// SEO
|
||||
seo: {
|
||||
title: '404 - Seite nicht gefunden',
|
||||
description: 'Die gesuchte Seite existiert nicht.'
|
||||
},
|
||||
// Hauptinhalt
|
||||
content: {
|
||||
errorCode: '404',
|
||||
title: 'Seite nicht gefunden',
|
||||
description: 'Die gesuchte Seite existiert nicht oder wurde verschoben.',
|
||||
},
|
||||
// Aktionsbuttons
|
||||
actions: {
|
||||
goBack: 'Zurück',
|
||||
homePage: 'Startseite'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,111 @@
|
||||
// src/i18n/locales/de/pages/portfolio.ts
|
||||
export const portfolio = {
|
||||
// SEO und Meta-Informationen
|
||||
seo: {
|
||||
title: 'Portfolio - Damjan Savić',
|
||||
description: 'Entdecken Sie meine Projekte im Bereich JTL-Integration, E-Commerce und Digitale Transformation.'
|
||||
},
|
||||
// Hauptseite
|
||||
main: {
|
||||
title: 'Portfolio',
|
||||
loading: 'Projekte werden geladen...',
|
||||
error: 'Fehler beim Laden der Projekte',
|
||||
noProjects: {
|
||||
title: 'Keine Projekte gefunden',
|
||||
description: 'Aktuell sind keine Projekte verfügbar. Schauen Sie später wieder vorbei.'
|
||||
}
|
||||
},
|
||||
// Projekt-Karten
|
||||
projectCard: {
|
||||
date: 'Datum',
|
||||
technologies: 'Technologien',
|
||||
moreCount: 'weitere', // für '+X weitere'
|
||||
readMore: 'Mehr erfahren'
|
||||
},
|
||||
// Projekt-Details
|
||||
project: {
|
||||
navigation: {
|
||||
back: 'Zurück zum Portfolio',
|
||||
projectDetails: 'PROJEKT DETAILS'
|
||||
},
|
||||
metadata: {
|
||||
date: 'Datum',
|
||||
client: 'Kunde',
|
||||
duration: 'Dauer',
|
||||
repository: 'Repository',
|
||||
documentation: 'Dokumentation',
|
||||
technologies: 'Technologien',
|
||||
live: 'Live-Version'
|
||||
},
|
||||
sections: {
|
||||
overview: 'Überblick',
|
||||
challenge: 'Herausforderung',
|
||||
solution: 'Lösung',
|
||||
results: 'Ergebnisse',
|
||||
systemArchitecture: 'Systemarchitektur',
|
||||
implementation: 'Implementierung',
|
||||
technologies: 'Verwendete Technologien'
|
||||
}
|
||||
},
|
||||
// Kategorien und Filter
|
||||
categories: {
|
||||
all: 'Alle',
|
||||
'Data Science': 'Data Science',
|
||||
'AI Development': 'KI-Entwicklung',
|
||||
'Integration': 'Integration',
|
||||
'Full-Stack Development': 'Full-Stack Entwicklung',
|
||||
'Data Processing': 'Datenverarbeitung',
|
||||
'Content Production': 'Content-Produktion',
|
||||
'Machine Learning': 'Machine Learning',
|
||||
'Automation': 'Automatisierung'
|
||||
},
|
||||
// Spezifische Projekte
|
||||
projects: {
|
||||
'ai-data-reader': {
|
||||
title: 'KI-basierte Produktdatenpflege aus PDF-Dateien',
|
||||
description: 'Entwicklung eines automatisierten Systems zur Extraktion und Strukturierung von Produktdaten aus PDF-Dokumenten'
|
||||
},
|
||||
'bi-vision': {
|
||||
title: 'KI-Videos für BI-Software',
|
||||
description: 'Entwicklung von KI-gestützten Erklärvideos für Business Intelligence Dashboards'
|
||||
},
|
||||
'business-intelligence-ai': {
|
||||
title: 'KI für Business Intelligence',
|
||||
description: 'Integration von KI-Modellen in Business Intelligence Systeme zur Prozessoptimierung'
|
||||
},
|
||||
'claude-personal-assistant': {
|
||||
title: 'KI-basierter Personal Assistant mit Claude AI',
|
||||
description: 'Entwicklung eines personalisierten KI-Assistenten für professionelle E-Mail-Kommunikation'
|
||||
},
|
||||
'e-commerce-integration': {
|
||||
title: 'Integration mit TradeByte',
|
||||
description: 'Integration eines Shopify-Shops mit JTL-WaWi für optimierte Bestandsführung'
|
||||
},
|
||||
'jtl-integration-project': {
|
||||
title: 'JTL Integration Referenzprojekt',
|
||||
description: 'Ein vollständiges Lagersystem in Krefeld auf Basis von JTL'
|
||||
},
|
||||
'local-llm-training': {
|
||||
title: 'Training von lokalen KI-Modellen',
|
||||
description: 'Entwicklung einer Pipeline für das Training und die Feinabstimmung lokaler KI-Modelle'
|
||||
},
|
||||
'processautomation': {
|
||||
title: 'Automatisierung mit Python',
|
||||
description: 'Entwicklung von Automatisierungslösungen für Geschäftsprozesse'
|
||||
},
|
||||
'rfid-automation': {
|
||||
title: 'RFID-Automatisierung',
|
||||
description: 'Entwicklung eines automatisierten Systems zur Erstellung und zum Druck von RFID-Etiketten'
|
||||
},
|
||||
'timetracking-software': {
|
||||
title: 'Digitale Zeiterfassung',
|
||||
description: 'Entwicklung einer modernen Zeiterfassungslösung mit Next.js, Flask und MSSQL'
|
||||
}
|
||||
},
|
||||
// Status-Meldungen
|
||||
status: {
|
||||
loading: 'Wird geladen...',
|
||||
error: 'Ein Fehler ist aufgetreten',
|
||||
success: 'Erfolgreich geladen'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
// src/i18n/locales/de/pages/privacy.ts
|
||||
export const privacy = {
|
||||
// SEO und Schema
|
||||
seo: {
|
||||
title: 'Datenschutzerklärung',
|
||||
description: 'Datenschutzerklärung für die Portfolio-Website von Damjan Savić'
|
||||
},
|
||||
schema: {
|
||||
name: 'Datenschutzerklärung',
|
||||
description: 'Datenschutzerklärung für die Portfolio-Website von Damjan Savić'
|
||||
},
|
||||
// Hauptinhalt
|
||||
content: {
|
||||
title: 'Datenschutzerklärung',
|
||||
lastUpdated: 'Zuletzt aktualisiert: 10. März 2024',
|
||||
// Navigation
|
||||
breadcrumbs: {
|
||||
currentTitle: 'Datenschutzerklärung'
|
||||
},
|
||||
// Abschnitte
|
||||
sections: {
|
||||
introduction: {
|
||||
title: '1. Einführung',
|
||||
content: 'Diese Datenschutzerklärung erläutert, wie wir Ihre personenbezogenen Daten bei der Nutzung unserer Website erfassen, verwenden und schützen.'
|
||||
},
|
||||
dataCollection: {
|
||||
title: '2. Datenerfassung',
|
||||
providedInfo: {
|
||||
title: '2.1 Von Ihnen bereitgestellte Informationen',
|
||||
intro: 'Bei Verwendung unseres Kontaktformulars erfassen wir:',
|
||||
items: [
|
||||
'Name',
|
||||
'E-Mail-Adresse',
|
||||
'Nachrichteninhalt'
|
||||
]
|
||||
},
|
||||
automaticInfo: {
|
||||
title: '2.2 Automatisch erfasste Informationen',
|
||||
intro: 'Wir erfassen automatisch:',
|
||||
items: [
|
||||
'IP-Adresse',
|
||||
'Browser-Typ',
|
||||
'Geräteinformationen',
|
||||
'Besuchte Seiten',
|
||||
'Verweildauer auf der Website'
|
||||
]
|
||||
}
|
||||
},
|
||||
dataUsage: {
|
||||
title: '3. Verwendung Ihrer Daten',
|
||||
intro: 'Wir verwenden Ihre Daten für:',
|
||||
items: [
|
||||
'Beantwortung Ihrer Anfragen',
|
||||
'Verbesserung unserer Website',
|
||||
'Analyse von Nutzungsmustern',
|
||||
'Betrugsprävention'
|
||||
]
|
||||
},
|
||||
cookies: {
|
||||
title: '4. Cookies',
|
||||
intro: 'Wir verwenden Cookies für:',
|
||||
items: [
|
||||
'Speicherung Ihrer Präferenzen',
|
||||
'Analyse des Website-Verkehrs',
|
||||
'Verständnis des Nutzerverhaltens'
|
||||
]
|
||||
},
|
||||
security: {
|
||||
title: '5. Datensicherheit',
|
||||
intro: 'Wir implementieren geeignete Sicherheitsmaßnahmen zum Schutz Ihrer personenbezogenen Daten, einschließlich:',
|
||||
items: [
|
||||
'Verschlüsselung der Datenübertragung',
|
||||
'Regelmäßige Sicherheitsbewertungen',
|
||||
'Zugriffskontrollen',
|
||||
'Sichere Datenspeicherung'
|
||||
]
|
||||
},
|
||||
rights: {
|
||||
title: '6. Ihre Rechte',
|
||||
intro: 'Sie haben das Recht auf:',
|
||||
items: [
|
||||
'Zugriff auf Ihre personenbezogenen Daten',
|
||||
'Berichtigung der Daten',
|
||||
'Löschung der Daten',
|
||||
'Widerspruch gegen die Datenverarbeitung',
|
||||
'Datenübertragbarkeit'
|
||||
]
|
||||
},
|
||||
contact: {
|
||||
title: '7. Kontaktinformationen',
|
||||
intro: 'Für datenschutzbezogene Anfragen kontaktieren Sie uns unter:',
|
||||
email: 'E-Mail: privacy@damjan-savic.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
// src/i18n/locales/de/pages/terms.ts
|
||||
export const terms = {
|
||||
// SEO und Schema
|
||||
seo: {
|
||||
title: 'Allgemeine Geschäftsbedingungen',
|
||||
description: 'Allgemeine Geschäftsbedingungen für die Portfolio-Website von Damjan Savić'
|
||||
},
|
||||
schema: {
|
||||
name: 'Allgemeine Geschäftsbedingungen',
|
||||
description: 'Allgemeine Geschäftsbedingungen für die Portfolio-Website von Damjan Savić'
|
||||
},
|
||||
// Hauptinhalt
|
||||
content: {
|
||||
title: 'Allgemeine Geschäftsbedingungen',
|
||||
lastUpdated: 'Zuletzt aktualisiert: 10. März 2024',
|
||||
// Navigation
|
||||
breadcrumbs: {
|
||||
currentTitle: 'Allgemeine Geschäftsbedingungen'
|
||||
},
|
||||
// Abschnitte
|
||||
sections: {
|
||||
agreement: {
|
||||
title: '1. Zustimmung zu den Bedingungen',
|
||||
content: 'Mit dem Zugriff auf unsere Website stimmen Sie zu, an diese Allgemeinen Geschäftsbedingungen gebunden zu sein und alle geltenden Gesetze und Vorschriften einzuhalten.'
|
||||
},
|
||||
intellectualProperty: {
|
||||
title: '2. Rechte an geistigem Eigentum',
|
||||
content: 'Alle Inhalte dieser Website, einschließlich, aber nicht beschränkt auf Texte, Grafiken, Logos, Bilder und Software, sind Eigentum von Damjan Savić und durch Gesetze zum Schutz geistigen Eigentums geschützt.'
|
||||
},
|
||||
userResponsibilities: {
|
||||
title: '3. Nutzerverantwortlichkeiten',
|
||||
intro: 'Bei der Nutzung unserer Website stimmen Sie zu:',
|
||||
items: [
|
||||
'Korrekte Informationen bereitzustellen',
|
||||
'Die Website legal und ethisch zu nutzen',
|
||||
'Keinen unbefugten Zugriff zu versuchen',
|
||||
'Den Betrieb der Website nicht zu stören'
|
||||
]
|
||||
},
|
||||
liability: {
|
||||
title: '4. Haftungsbeschränkung',
|
||||
content: 'Wir haften nicht für indirekte, zufällige, besondere, Folge- oder Strafschäden, die sich aus Ihrer Nutzung oder Unfähigkeit zur Nutzung der Website ergeben.'
|
||||
},
|
||||
changes: {
|
||||
title: '5. Änderungen der Bedingungen',
|
||||
content: 'Wir behalten uns das Recht vor, diese Bedingungen jederzeit zu ändern. Wir werden die Nutzer über wesentliche Änderungen informieren, indem wir die neuen Allgemeinen Geschäftsbedingungen auf dieser Seite veröffentlichen.'
|
||||
},
|
||||
governingLaw: {
|
||||
title: '6. Geltendes Recht',
|
||||
content: 'Diese Bedingungen unterliegen den Gesetzen der Bundesrepublik Deutschland und werden in Übereinstimmung mit diesen ausgelegt, ohne Berücksichtigung von Kollisionsnormen.'
|
||||
},
|
||||
contact: {
|
||||
title: '7. Kontaktinformationen',
|
||||
intro: 'Bei Fragen zu diesen Allgemeinen Geschäftsbedingungen kontaktieren Sie uns bitte unter:',
|
||||
email: 'E-Mail: legal@damjan-savic.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
// src/i18n/locales/de/portfolio/index.ts
|
||||
import aiDataReader from './projects/ai-data-reader';
|
||||
export const portfolio = {
|
||||
// Meta-Informationen für die Portfolio-Seite
|
||||
seo: {
|
||||
title: 'Portfolio - Damjan Savić',
|
||||
description: 'Entdecken Sie meine Projekte im Bereich JTL-Integration, E-Commerce und digitale Transformation.'
|
||||
},
|
||||
// Portfolio-Überschriften und Filter
|
||||
sections: {
|
||||
title: 'Portfolio',
|
||||
subtitle: 'Ausgewählte Projekte und Referenzen',
|
||||
filterTitle: 'Kategorien',
|
||||
sortTitle: 'Sortierung'
|
||||
},
|
||||
// Filter-Optionen
|
||||
filters: {
|
||||
all: 'Alle',
|
||||
categories: {
|
||||
'Data Science': 'Data Science',
|
||||
'AI Development': 'KI-Entwicklung',
|
||||
'Integration': 'Integration',
|
||||
'Full-Stack Development': 'Full-Stack Entwicklung',
|
||||
'Data Processing': 'Datenverarbeitung',
|
||||
'Content Production': 'Content-Produktion',
|
||||
'Machine Learning': 'Machine Learning',
|
||||
'Automation': 'Automatisierung'
|
||||
}
|
||||
},
|
||||
// Sortier-Optionen
|
||||
sort: {
|
||||
date: 'Datum',
|
||||
title: 'Titel',
|
||||
category: 'Kategorie'
|
||||
},
|
||||
// UI-Texte
|
||||
ui: {
|
||||
loading: 'Projekte werden geladen...',
|
||||
noProjects: 'Keine Projekte gefunden',
|
||||
viewProject: 'Projekt ansehen',
|
||||
backToPortfolio: 'Zurück zum Portfolio',
|
||||
technologies: 'Technologien',
|
||||
client: 'Kunde',
|
||||
duration: 'Dauer',
|
||||
visitWebsite: 'Website besuchen',
|
||||
viewRepository: 'Repository ansehen',
|
||||
viewDocumentation: 'Dokumentation'
|
||||
},
|
||||
// Alle Projekte
|
||||
projects: {
|
||||
'ai-data-reader': aiDataReader,
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,107 @@
|
||||
// src/i18n/locales/de/portfolio/projects/ai-data-reader.ts
|
||||
export const aiDataReader = {
|
||||
meta: {
|
||||
slug: 'ai-data-reader',
|
||||
title: "KI-basierte Produktdatenpflege aus PDF-Dateien",
|
||||
description: "Entwicklung eines automatisierten Systems zur Extraktion und Strukturierung von Produktdaten aus PDF-Dokumenten",
|
||||
excerpt: "Integration von Claude AI für die intelligente Verarbeitung von Produktinformationen und nahtlose JTL-ERP-Integration.",
|
||||
date: "2024-02",
|
||||
category: "Data Processing",
|
||||
client: "Amazon Seller",
|
||||
duration: "2 Monate",
|
||||
url: "https://www.damjan-savic.com",
|
||||
repository: "",
|
||||
documentation: "",
|
||||
published: true,
|
||||
featured: true,
|
||||
technologies: ["Python", "FastAPI", "Claude AI", "PyPDF", "Pydantic", "JTL-Wawi"],
|
||||
tags: ["Data Extraction", "ERP", "Process Automation", "PDF Processing"]
|
||||
},
|
||||
content: {
|
||||
intro: "Ein KI-gestütztes System zur automatisierten Extraktion von Produktdaten aus PDF-Dokumenten mit direkter Integration in JTL-Warenwirtschaftssysteme, entwickelt für maximale Effizienz in der Produktdatenpflege.",
|
||||
|
||||
challenge: {
|
||||
title: "Die Herausforderung",
|
||||
description: "Die manuelle Erfassung von Produktdaten aus PDF-Dokumenten war zeitaufwendig und fehleranfällig.",
|
||||
points: [
|
||||
"Große Mengen an PDF-Dokumenten mit Produktinformationen",
|
||||
"Zeitintensive manuelle Dateneingabe",
|
||||
"Inkonsistente Datenqualität",
|
||||
"Hoher personeller Aufwand"
|
||||
]
|
||||
},
|
||||
|
||||
solution: {
|
||||
title: "Unsere Lösung",
|
||||
description: "Entwicklung eines KI-gestützten Systems zur automatisierten Datenextraktion",
|
||||
content: "Durch den Einsatz von Claude AI und modernen Python-Technologien haben wir eine vollautomatische Lösung geschaffen, die PDF-Dokumente verarbeitet und die extrahierten Daten direkt in das JTL-Warenwirtschaftssystem integriert.",
|
||||
points: [
|
||||
"Automatisierte PDF-Verarbeitung",
|
||||
"KI-gestützte Datenextraktion",
|
||||
"Intelligente Datenvalidierung",
|
||||
"Nahtlose JTL-Integration"
|
||||
]
|
||||
},
|
||||
|
||||
technical: {
|
||||
title: "Technische Umsetzung",
|
||||
description: "Die Lösung basiert auf einer modularen Python-Architektur mit verschiedenen Kernkomponenten:",
|
||||
points: [
|
||||
"Robuste PDF-Textextraktion mit PyPDF",
|
||||
"KI-gestützte Datenextraktion mit Claude AI",
|
||||
"Validierung durch Pydantic Models",
|
||||
"JTL-ERP Integration über CSV-Export"
|
||||
],
|
||||
code: `class ProductData(BaseModel):
|
||||
artikel_nummer: str
|
||||
name: str
|
||||
hersteller: str
|
||||
inhaltsstoffe: List[str]
|
||||
allergene: List[str]
|
||||
naehrwerte: NaehrwertData
|
||||
nettogewicht: str
|
||||
vegan: bool
|
||||
vegetarisch: bool
|
||||
|
||||
def _extract_with_claude(self, prompt: str) -> Dict[str, Any]:
|
||||
'''Extrahiert strukturierte Daten mit Claude AI.'''
|
||||
response = self.client.messages.create(
|
||||
model='claude-3-sonnet-20240229',
|
||||
messages=[{
|
||||
'role': 'user',
|
||||
'content': prompt
|
||||
}]
|
||||
)
|
||||
return self._clean_json_string(response.content)`
|
||||
},
|
||||
|
||||
implementation: {
|
||||
title: "Implementierungsprozess",
|
||||
description: "Der automatisierte Workflow wurde in mehreren Phasen implementiert:",
|
||||
points: [
|
||||
"PDF-Batch-Verarbeitung aus Input-Verzeichnis",
|
||||
"Intelligente Texterkennung und -strukturierung",
|
||||
"Mehrschichtige Validierungslogik",
|
||||
"Robuste Fehlerbehandlung",
|
||||
"Integration in bestehende Systeme"
|
||||
]
|
||||
},
|
||||
|
||||
results: {
|
||||
title: "Ergebnisse und Auswirkungen",
|
||||
description: "Die Implementierung führte zu signifikanten Verbesserungen im Geschäftsprozess:",
|
||||
points: [
|
||||
"90% Zeitersparnis bei der Produktdatenpflege",
|
||||
"99% Genauigkeit bei der Datenextraktion",
|
||||
"Eliminierung manueller Dateneingaben",
|
||||
"Standardisierte Produktdatenqualität",
|
||||
"Deutlich reduzierte Fehlerquote"
|
||||
]
|
||||
},
|
||||
|
||||
conclusion: "Das entwickelte System hat die Produktdatenpflege grundlegend revolutioniert. Durch die Kombination von KI-Technologie und automatisierter Datenverarbeitung wurde nicht nur die Effizienz drastisch gesteigert, sondern auch die Datenqualität erheblich verbessert. Das Projekt zeigt eindrucksvoll, wie moderne KI-Lösungen praktische Geschäftsprobleme lösen können."
|
||||
}
|
||||
};
|
||||
|
||||
// Re-export für Kompatibilität mit dem Projektimport-System
|
||||
export default aiDataReader;
|
||||
Reference in New Issue
Block a user