First Commit - Portfolio Page

This commit is contained in:
2025-02-10 00:55:39 +01:00
commit bba0e331a8
239 changed files with 33355 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
// src/i18n/locales/en/blog/index.ts
export const blog = {
meta: {
title: 'Blog - JTL Integration & Digital Solutions',
description: 'Insights and Best Practices on JTL-WaWi, E-Commerce, and Digital Transformation',
header: {
title: 'Insights & Best Practices',
subtitle: 'Insights and Best Practices on JTL-WaWi, E-Commerce, and Digital Transformation'
}
},
posts: {
'erp-integration-breuninger': {
title: 'ApparelMagic and TradeByte: Analysis of Complex Integrations',
date: '2024-02-09',
excerpt: 'Detailed analysis of an e-commerce integration between Apparel Magic and 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: A Technical Analysis of the TradeByte Integration',
description: 'The integration of e-commerce systems with established marketplaces poses unique challenges for companies. In this article, I share my experiences from a complex integration project between Apparel Magic as an ERP system and the Breuninger platform via TradeByte.'
},
background: {
title: 'Project Background',
systems: {
erp: 'Apparel Magic as an ERP system for product data and inventory management',
middleware: 'TradeByte as the middleware for the Breuninger platform'
},
challenges: {
sync: 'Bidirectional synchronization of orders',
customers: 'Automated customer creation',
delivery: 'Management of delivery notes',
inventory: 'Real-time inventory management'
}
},
tech: {
title: 'Technical Architecture',
components: {
title: 'Key Components'
},
database: {
title: 'Middleware Database',
description: 'The MariaDB database serves as the central data store for the integration:'
}
},
api: {
title: 'API Integrations',
apparel_magic: {
title: 'Apparel Magic API',
description: 'The REST API of Apparel Magic is used for customer creation and inventory management:'
},
tradebyte: {
title: 'TradeByte Integration',
description: 'The TradeByte API uses a combination of REST and XML:'
}
},
order_process: {
title: 'Order Process',
steps: {
fetch: 'Regular retrieval of new orders from TradeByte',
customers: 'Automatic customer creation in Apparel Magic',
process: 'Order processing and status update',
delivery: 'Generation and storage of delivery notes'
},
delivery_notes: {
title: 'Delivery Note Management'
}
},
challenges: {
title: 'Challenges and Solutions',
status: {
title: '1. Status Management',
description: 'A particular challenge was managing order statuses:'
},
error_handling: {
title: '2. Error Handling and Monitoring',
description: 'Robust error handling was essential for production operation:'
}
},
best_practices: {
title: 'Best Practices',
api: {
title: '1. API Communication',
items: {
retry: 'Implementation of retry mechanisms',
errors: 'Careful error handling',
logging: 'Comprehensive logging of all communications'
}
},
data: {
title: '2. Data Management',
items: {
storage: 'Central data storage in MariaDB',
transactions: 'Transactional security for critical operations',
validation: 'Regular data validation'
}
},
automation: {
title: '3. Process Automation',
items: {
customers: 'Automated customer creation',
status: 'Automatic status updates',
delivery: 'Systematic delivery note management'
}
}
},
lessons: {
title: 'Lessons Learned',
api: {
title: '1. API Design',
items: {
docs: 'Thorough API documentation is essential',
auth: 'Understanding of various authentication methods',
limits: 'Consideration of rate limits'
}
},
validation: {
title: '2. Data Validation',
items: {
rules: 'Implementation of strict validation rules',
edge_cases: 'Careful handling of edge cases',
cleanup: 'Automated data cleanup'
}
},
optimization: {
title: '3. Process Optimization',
items: {
automation: 'Continuous improvement of automation',
performance: 'Regular performance reviews',
monitoring: 'Proactive monitoring'
}
}
},
conclusion: {
title: 'Conclusion',
requirements: {
understanding: 'Deep understanding of both systems',
implementation: 'Careful implementation of API communication',
error_handling: 'Robust error handling',
monitoring: 'Continuous monitoring'
},
results: 'The developed solution successfully processes orders and enables seamless integration between the systems. In particular, automated customer creation and delivery note management have proven to be efficiency boosters.'
}
}
},
},
ui: {
readMore: 'Read More',
loading: {
posts: 'Loading blog posts...',
post: 'Loading blog post...'
},
errors: {
posts: 'Error loading blog posts',
post: 'The requested blog post does not exist or has been moved.'
},
backToBlog: 'Back to Blog',
publishedOn: 'Published on',
category: 'Category',
tags: 'Tags',
notFound: {
title: 'Post Not Found',
message: 'The requested blog post does not exist or has been moved.'
}
},
categories: {
'Integration': 'Integration',
'Entwicklung': 'Development',
'Automatisierung': 'Automation'
}
} as const;
export type BlogConfig = typeof blog;
export type BlogPost = BlogConfig['posts'][keyof BlogConfig['posts']];
@@ -0,0 +1,138 @@
// src/i18n/locales/en/blog/posts/erp-integration-breuninger.ts
export const erpIntegrationBreuninger = {
posts: {
erp_integration: {
title: "ApparelMagic and TradeByte: Analysis of Complex Integrations",
date: "2024-02-09",
excerpt: "Detailed analysis of an e-commerce integration between Apparel Magic and 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: A Technical Analysis of the TradeByte Integration",
description: "The integration of e-commerce systems with established marketplaces presents unique challenges for companies. In this article, I share my experiences from a complex integration project between Apparel Magic as an ERP system and the Breuninger platform via TradeByte."
},
background: {
title: "Project Background",
systems: {
erp: "Apparel Magic as an ERP system for product data and inventory management",
middleware: "TradeByte as middleware for the Breuninger platform"
},
challenges: {
sync: "Bidirectional synchronization of orders",
customers: "Automated customer creation",
delivery: "Management of delivery notes",
inventory: "Real-time inventory management"
}
},
tech: {
title: "Technical Architecture",
components: {
title: "Central Components"
},
database: {
title: "Middleware Database",
description: "The MariaDB database serves as the central data store for the integration:"
}
},
api: {
title: "API Integrations",
apparel_magic: {
title: "Apparel Magic API",
description: "The REST API of Apparel Magic is used for customer creation and inventory management:"
},
tradebyte: {
title: "TradeByte Integration",
description: "The TradeByte API uses a combination of REST and XML:"
}
},
order_process: {
title: "Order Process",
steps: {
fetch: "Regular retrieval of new orders from TradeByte",
customers: "Automatic customer creation in Apparel Magic",
process: "Order processing and status update",
delivery: "Generation and storage of delivery notes"
},
delivery_notes: {
title: "Delivery Note Management"
}
},
challenges: {
title: "Challenges and Solutions",
status: {
title: "1. Status Management",
description: "A particular challenge was managing order statuses:"
},
error_handling: {
title: "2. Error Handling and Monitoring",
description: "Robust error handling was essential for production operations:"
}
},
best_practices: {
title: "Best Practices",
api: {
title: "1. API Communication",
items: {
retry: "Implementation of retry mechanisms",
errors: "Careful error handling",
logging: "Comprehensive logging of all communications"
}
},
data: {
title: "2. Data Management",
items: {
storage: "Central data storage in MariaDB",
transactions: "Transactional security for critical operations",
validation: "Regular data validation"
}
},
automation: {
title: "3. Process Automation",
items: {
customers: "Automated customer creation",
status: "Automatic status updates",
delivery: "Systematic delivery note management"
}
}
},
lessons: {
title: "Lessons Learned",
api: {
title: "1. API Design",
items: {
docs: "Thorough API documentation is essential",
auth: "Understanding of various authentication methods",
limits: "Consideration of rate limits"
}
},
validation: {
title: "2. Data Validation",
items: {
rules: "Implementation of strict validation rules",
edge_cases: "Careful handling of edge cases",
cleanup: "Automated data cleanup"
}
},
optimization: {
title: "3. Process Optimization",
items: {
automation: "Continuous improvement of automation",
performance: "Regular performance reviews",
monitoring: "Proactive monitoring"
}
}
},
conclusion: {
title: "Conclusion",
requirements: {
understanding: "Deep understanding of both systems",
implementation: "Careful implementation of the API communication",
error_handling: "Robust error handling",
monitoring: "Continuous monitoring"
},
results: "The developed solution successfully processes orders and enables seamless integration between the systems. In particular, the automated customer creation and delivery note management have proven to enhance efficiency."
}
}
}
};
@@ -0,0 +1,253 @@
// src/i18n/locales/en/blog/posts/fullstack-development-timetracking.ts
export const fullstackDevelopmentTimetracking = {
meta: {
title: 'Fullstack Development with Python and React: Architecture of our Time Tracking Solution',
date: '2024-02-09',
excerpt: 'A technical deep dive into the implementation of a modern time tracking solution',
category: 'System Architecture',
coverImage: '/images/posts/fullstack-development-timetracking/cover.jpg',
tags: ['Python', 'React', 'TypeScript', 'MSSQL', 'System Design']
},
content: {
intro: {
title: 'Fullstack Development with Python and React: Architecture of our Time Tracking Solution',
description: 'Developing a robust time tracking solution requires not only technical expertise but also a deep understanding of complex business rules and user requirements. In this article, I share our experiences in implementing a modern fullstack time tracking solution with Python and React.'
},
systemArchitecture: {
title: 'System Architecture',
frontend: {
title: 'Frontend (Next.js + TypeScript)',
description: 'The frontend architecture is based on Next.js with TypeScript and follows a component-based approach:',
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: 'The backend uses Flask for the API and MSSQL for data persistence:',
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: 'Business Logic Implementation',
validation: {
title: 'Time Entry Validation',
description: 'The validation logic ensures that all business rules are followed:',
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: 'Database Design',
description: 'The MSSQL database schema is designed for efficiency and integrity:',
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: 'Security Implementation',
authentication: {
title: 'JWT Authentication',
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 and Learnings',
points: [
{
title: 'Data Validation at Multiple Levels',
items: [
'Frontend validation for immediate feedback',
'Backend validation for business rules',
'Database constraints for data integrity'
]
},
{
title: 'Error Handling',
items: [
'Structured error messages',
'User-friendly error messages in frontend',
'Detailed logging in backend'
]
},
{
title: 'Performance Optimization',
items: [
'Indexing of critical database fields',
'Frontend caching of time entries',
'Lazy loading for historical data'
]
}
]
},
challenges: {
title: 'Challenges and Solutions',
timezones: {
title: '1. Timezone Handling',
description: 'A particular challenge was the correct handling of timezones:',
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: 'Handling concurrent updates required special attention:',
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 Capability',
description: 'For offline functionality, we implemented a service worker strategy:',
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: 'Conclusion',
description: 'Developing a time tracking solution requires careful planning and consideration of numerous business rules. By using modern technologies like Next.js, TypeScript, and Flask, we were able to implement a robust and user-friendly solution.',
keyPoints: [
'Strict typing with TypeScript',
'Comprehensive validation logic',
'Efficient database design',
'User-friendly error handling'
],
results: 'The solution has been successfully in use for several months and reliably processes hundreds of time entries daily.'
}
}
};
@@ -0,0 +1,204 @@
// src/i18n/locales/en/blog/posts/rfid-automation.ts
export const rfidAutomation = {
meta: {
title: 'RFID Label Automation: From Database to Printer',
date: '2024-02-09',
excerpt: 'A detailed technical analysis of implementing an automated RFID label printing system with Python',
category: 'System Integration',
coverImage: '/images/posts/rfid-automation/cover.jpg',
tags: ['RFID', 'Python', 'ZPL', 'Automation', 'Zebra Printer', 'EPC']
},
content: {
intro: {
title: 'RFID Label Automation: From Database to Printer',
description: 'In modern logistics and retail environments, efficient and error-free labeling of products with RFID tags is crucial. In this article, I share my experiences implementing an automated solution for generating and printing RFID labels with chip encoding.'
},
requirements: {
title: 'Project Background',
points: [
'Automatic generation of EPC codes (Electronic Product Code)',
'Creation of ZPL code for Zebra printers',
'Direct network communication with the printer',
'Integration with existing product data',
'Error handling and logging'
]
},
implementation: {
title: 'Technical Implementation',
epcGeneration: {
title: 'EPC Code Generation',
description: 'The EPC codes are generated according to the SGTIN standard (Serialized Global Trade Item Number):',
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: 'ZPL templates were implemented for different label types:',
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: 'Network Communication with the Printer',
description: 'Communication with the Zebra printer is done via 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('Data successfully sent to printer')
except Exception as e:
logger.error(f'Error sending data to printer: {e}')`
},
serialNumberManagement: {
title: 'Data Processing and Serial Number Management',
description: 'Managing serial numbers is critical for the uniqueness of 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: 'Implemented Features',
errorHandling: {
title: '1. Robust Error Handling',
points: [
'Input data validation',
'Network connection verification',
'Serial number persistence',
'Detailed logging of all operations'
]
},
configurability: {
title: '2. Configurability',
points: [
'Adjustable printer IP and port',
'Customizable ZPL templates',
'Flexible EPC code generation',
'Configurable serial number ranges'
]
},
scalability: {
title: '3. Scalability',
points: [
'Batch processing of product data',
'Parallel print jobs possible',
'Efficient resource management',
'Modular code for easy extensibility'
]
}
},
bestPractices: {
title: 'Best Practices',
dataValidation: {
title: '1. Data Validation',
points: [
'Strict typing for critical data fields',
'Verification of required fields',
'Format and plausibility checks'
]
},
faultTolerance: {
title: '2. Fault Tolerance',
points: [
'Automatic retry attempts',
'Graceful degradation',
'Detailed error logs'
]
},
maintainability: {
title: '3. Maintainability',
points: [
'Modular code structure',
'Comprehensive documentation',
'Clear separation of configuration and code'
]
}
},
lessonsLearned: {
title: 'Lessons Learned',
zplSpecifics: {
title: '1. ZPL Specifics',
points: [
'Detailed knowledge of ZPL specifications necessary',
'Careful validation of generated ZPL codes',
'Regular testing with different printer models'
]
},
rfidStandards: {
title: '2. RFID Standards',
points: [
'Adherence to EPC standards critical',
'Careful management of serial numbers',
'Validation of generated EPC codes'
]
},
networkCommunication: {
title: '3. Network Communication',
points: [
'Robust error handling for network issues',
'Timeouts and retry attempts',
'Buffering of print jobs'
]
}
},
conclusion: {
title: 'Conclusion',
description: 'The implemented solution enables efficient and reliable automation of the RFID labeling process. Through the combination of EPC code generation, ZPL template management, and direct printer communication, a robust system has been created that has proven itself in practice.',
keyPoints: [
'Thorough planning of system architecture',
'Comprehensive error handling',
'Careful documentation',
'Regular testing and validation'
],
results: 'The solution has been running stably in production for several months and processes hundreds of labels daily.'
}
}
};
+99
View File
@@ -0,0 +1,99 @@
export const common = {
// SEO & Meta
siteTitle: 'Damjan Savić - Digital Solutions & JTL Integration',
siteDescription: 'Developer of custom solutions for process automation',
// Navigation
nav: {
home: 'Home',
about: 'About',
services: 'Services',
portfolio: 'Portfolio',
blog: 'Blog',
contact: 'Contact'
},
// Common Actions
actions: {
readMore: 'Read More',
viewMore: 'View More',
viewAll: 'View All',
back: 'Back',
close: 'Close',
submit: 'Submit',
loading: 'Loading...'
},
// UI Components
ui: {
published: 'Published on',
lastUpdated: 'Last updated on',
category: 'Category',
categories: 'Categories',
tag: 'Tag',
tags: 'Tags',
author: 'Author',
minuteRead: 'minute read',
tableOfContents: 'Table of Contents'
},
// Error Messages
errors: {
generic: 'An error has occurred',
notFound: 'Page not found',
loading: 'Error loading',
return: 'Return to homepage'
},
// Loading States
loading: {
content: 'Loading content',
page: 'Loading page',
processing: 'Processing'
},
// Dates
dates: {
months: {
long: [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'
],
short: [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]
},
weekdays: {
long: [
'Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday'
],
short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
}
},
// Social Media
social: {
followMe: 'Follow me on',
shareOn: 'Share on',
linkedin: 'LinkedIn',
github: 'GitHub',
email: 'Email'
},
// Contact Form
contact: {
title: 'Contact',
name: 'Name',
email: 'Email',
message: 'Message',
submit: 'Send Message',
success: 'Your message has been sent successfully',
error: 'There was an error sending your message'
},
// Accessibility
a11y: {
skipToContent: 'Skip to main content',
menuOpen: 'Open menu',
menuClose: 'Close menu',
darkMode: 'Toggle dark mode',
carousel: {
next: 'Next image',
previous: 'Previous image'
}
}
} as const;
export type CommonTranslations = typeof common;
+9
View File
@@ -0,0 +1,9 @@
const cookiebanner = {
cookies: {
message: "This website uses cookies to enhance your browsing experience. The data will not be shared with third parties.",
accept: "Accept Cookies",
decline: "Decline"
}
};
export default cookiebanner;
+40
View File
@@ -0,0 +1,40 @@
// src/i18n/locales/en/footer.ts
const footer = {
sections: {
contact: {
title: "Contact",
email: "info@damjan-savic.com",
location: "Cologne, Germany",
aria: {
emailLink: "Send email",
locationText: "Location"
}
},
navigation: {
title: "Navigation",
links: {
portfolio: "Portfolio",
blog: "Blog",
about: "About",
contact: "Contact"
}
},
social: {
title: "Social Media",
aria: {
linkedin: "Visit my LinkedIn profile",
github: "Visit my GitHub profile"
}
}
},
legal: {
copyright: "All rights reserved",
links: {
privacy: "Privacy Policy",
terms: "Legal Notice"
}
}
} as const;
export default footer;
export type FooterTranslations = typeof footer;
+109
View File
@@ -0,0 +1,109 @@
// src/i18n/locales/en/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';
// Page translations
import { about } from './pages/about/index';
import { contact } from './pages/contact/index';
import { dashboard } from './pages/dashboard';
import { home } from './pages/home/index';
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';
// Common translations and configurations
import { common } from './common';
import { meta } from './meta';
import { navigation } from './navigation';
// Footer translations
import footer from './footer';
// Merging all translation objects
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,
// Common configurations
common: {
...common,
cookies: {
message: "This website uses cookies to enhance your browsing experience and provide personalized content. The collected data will not be shared with third parties.",
accept: "Accept Cookies",
decline: "Decline"
}
},
meta,
navigation,
} as const;
// Default export: complete translations object
export default translations;
// Type definition for translations
export type Translations = typeof translations;
// Re-exports for direct access to individual modules
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,
};
+93
View File
@@ -0,0 +1,93 @@
export const meta = {
site: {
name: 'Damjan Savić',
title: 'Damjan Savić - Digital Solutions & JTL Integration',
subtitle: 'Developer of custom solutions for process automation',
description: 'With a background in software development and expertise in digital transformation, I help companies optimize and automate their business processes.',
keywords: [
'JTL Integration',
'E-Commerce Solutions',
'Process Automation',
'Digital Consulting',
'ERP Systems',
'Python Development',
'System Integration',
'Digital Marketing'
].join(', ')
},
company: {
name: 'Damjan Savić',
shortName: 'Damjan Savić',
description: 'Your software development partner for fast, reliable, and cost-efficient solutions.',
address: 'Rotdornallee',
city: 'Köln',
postalCode: '50999',
country: 'Germany',
phone: '+49 175 695 0979',
email: 'info@damjan-savic.com',
website: 'www.damjan-savic.com'
},
author: {
name: 'Damjan Savić',
role: 'Consultant Digital Solutions',
company: 'Ritter Digital GmbH',
location: 'Oberhausen, Germany',
email: 'info@damjan-savic.com',
website: 'www.damjan-savic.com',
languages: [
{ code: 'en', level: 'C2', name: 'English' },
{ code: 'sr', level: 'C2', name: 'Serbian' },
{ code: 'de', level: 'C2', name: 'German' },
{ code: 'fr', level: 'B2', name: 'French' },
{ code: 'es', level: 'B2', name: 'Spanish' },
{ code: 'ru', level: 'A1', name: 'Russian' }
]
},
social: {
linkedin: 'https://www.linkedin.com/in/damjansavic/',
github: 'https://github.com/damjansavic',
email: 'info@damjan-savic.com'
},
expertise: {
areas: [
'JTL Integration & Consulting',
'Process Automation',
'E-Commerce Development',
'System Integration',
'ERP Systems',
'Digital Transformation'
],
technologies: [
'Python',
'React/Next.js',
'MariaDB',
'Docker',
'JTL-WaWi',
'Shopify',
'Shopware'
]
},
seo: {
defaultLanguage: 'en',
alternateLanguages: ['de', 'sr'],
robots: 'index, follow',
googleSiteVerification: '', // If needed
og: {
type: 'website',
locale: 'en_US',
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;
+79
View File
@@ -0,0 +1,79 @@
// C:\Development\Damjan Savic\Portfolio\src\i18n\locales\en\navigation.ts
export const navigation = {
// Main navigation
main: {
home: 'Home',
about: 'About',
portfolio: 'Portfolio',
blog: 'Blog',
contact: 'Contact'
},
// Dashboard and Admin
admin: {
login: 'Login',
dashboard: 'Dashboard',
logout: 'Logout'
},
// Footer Navigation
footer: {
legal: {
privacy: 'Privacy Policy',
terms: 'Terms & Conditions',
imprint: 'Imprint'
},
sections: {
portfolio: 'Portfolio',
blog: 'Blog',
contact: 'Contact'
}
},
// Page sections
sections: {
experience: 'Experience',
skills: 'Skills',
projects: 'Projects',
about: 'About'
},
// Breadcrumbs and back navigation
navigation: {
backTo: {
home: 'Back to Home',
portfolio: 'Back to Portfolio',
blog: 'Back to Blog'
},
breadcrumbs: {
home: 'Home',
portfolio: 'Portfolio',
blog: 'Blog',
about: 'About',
contact: 'Contact'
}
},
// Mobile Navigation
mobile: {
menu: 'Menu',
close: 'Close',
open: 'Open Menu'
},
// URLs (for dynamic route generation)
urls: {
home: '/',
about: '/about',
portfolio: '/portfolio',
blog: '/blog',
contact: '/contact',
login: '/login',
dashboard: '/dashboard',
privacy: '/privacy',
terms: '/terms'
},
// Meta information for navigation
meta: {
main: 'Main Navigation',
footer: 'Footer Navigation',
social: 'Social Media Navigation',
legal: 'Legal Navigation'
}
} as const;
export type NavigationConfig = typeof navigation;
+33
View File
@@ -0,0 +1,33 @@
export const hero = {
// Navigation/Header
aboutMe: 'ABOUT ME',
// Main Section
title: 'Digital Solutions Expert',
description: 'With a background in software development and expertise in digital transformation, I help companies optimize and automate their processes through innovative solutions.',
// Expertise Areas
expertise: {
processAutomation: {
title: 'Process Automation',
description: 'Development of efficient automated workflows'
},
systemIntegration: {
title: 'System Integration',
description: 'Connection and optimization of business systems'
},
customDevelopment: {
title: 'Custom Development',
description: 'Creation of tailored software solutions'
}
},
// Languages
languages: {
english: 'English',
serbian: 'Serbian',
german: 'German',
french: 'French',
spanish: 'Spanish',
russian: 'Russian'
}
} as const;
// Type for type safety
export type HeroTranslations = typeof hero;
+24
View File
@@ -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: 'Professional Journey',
subtitle: 'From digital media to enterprise solutions',
// Education Section
education: {
title: 'Education',
degrees: {
masters: {
degree: 'M.A. Software Development',
university: 'Middlesex University, London',
period: '2020 - 2022'
},
bachelors: {
degree: 'B.A. Cross-Media Production',
university: 'Middlesex University, London',
period: '2018 - 2020'
}
}
},
// Languages Section
languages: {
title: 'Languages',
items: {
english: {
name: 'English',
level: 'C2'
},
serbian: {
name: 'Serbian',
level: 'C2'
},
german: {
name: 'German',
level: 'C2'
},
french: {
name: 'French',
level: 'B2'
},
spanish: {
name: 'Spanish',
level: 'B2'
},
russian: {
name: 'Russian',
level: 'A1'
}
}
},
// Work History
work: {
positions: [
{
period: '08/2023 - Present',
company: 'Ritter Digital GmbH',
title: 'Digital Solutions Consultant',
location: 'Oberhausen',
highlights: [
'ERP consulting and implementation (JTL WaWi)',
'Process automation & full-stack development',
'RFID technology & automation',
'Lead generation & management',
'AI-supported content management'
]
},
{
period: '02/2023 - 08/2023',
company: 'Joyce & Girls Co AG',
title: 'ERP Integration Specialist',
location: 'Köln',
highlights: [
'Complex system integration (Apparel Magic, TradeByte)',
'Server administration and automation',
'Database and API development',
'Digital marketing and campaign analysis'
]
},
{
period: '08/2022 - 01/2023',
company: 'Magnarius',
title: 'RPA Developer & E-Commerce Manager',
location: 'Bergisch Gladbach',
highlights: [
'Shopware 6 development and JTL integration',
'Google Ads automation',
'CMS management and optimization',
'SEO strategy implementation'
]
}
]
}
} as const;
// Type for type safety
export type JourneyTranslations = typeof journey;
+31
View File
@@ -0,0 +1,31 @@
export const schema = {
page: {
name: 'About Damjan Savić',
description: 'Learn more about Damjan Savić, a certified JTL expert with extensive experience in e-commerce and warehouse management solutions.'
},
person: {
jobTitle: 'JTL Integration Expert',
description: 'With extensive experience in integrating and optimizing e-commerce systems, I help companies with the digital transformation of their business processes.',
languages: {
english: 'English',
serbian: 'Serbian',
german: 'German',
french: 'French',
spanish: 'Spanish',
russian: 'Russian'
},
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 for type safety
export type SchemaTranslations = typeof schema;
@@ -0,0 +1,13 @@
export const skillbar = {
// Accessibility labels
ariaLabel: {
skillLevel: 'Skill Level',
progressBar: 'Progress Bar'
},
// Screen reader text
screenReader: {
progress: '{{level}} percent progress for {{skill}}'
}
} as const;
// Type for type safety
export type SkillBarTranslations = typeof skillbar;
@@ -0,0 +1,63 @@
export const skillgroup = {
// Categories
categories: {
development: 'Development',
ecommerce: 'E-Commerce',
marketing: 'Marketing',
automation: 'Automation',
languages: 'Programming Languages',
databases: 'Databases'
},
// Skills by category
skills: {
development: {
frontend: 'Frontend Development',
backend: 'Backend Development',
fullstack: 'Full-Stack Development',
api: 'API Development',
testing: 'Software Testing'
},
ecommerce: {
jtl: 'JTL WaWi',
shopware: 'Shopware',
shopify: 'Shopify',
woocommerce: 'WooCommerce',
magento: 'Magento'
},
marketing: {
seo: 'Search Engine Optimization',
sea: 'Search Engine Advertising',
analytics: 'Web Analytics',
googleAds: 'Google Ads',
metaAds: 'Meta Ads'
},
automation: {
rpa: 'Robotic Process Automation',
workflow: 'Workflow Automation',
cicd: 'CI/CD',
testing: 'Test Automation',
deployment: 'Deployment Automation'
},
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: 'Skill Group',
skillList: 'List of skills in this category'
}
} as const;
// Type for type safety
export type SkillGroupTranslations = typeof skillgroup;
+46
View File
@@ -0,0 +1,46 @@
// en/pages/about/skills.ts
export const skills = {
title: 'Skills',
skillGroups: [
{
category: 'Development',
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: 'System Administration',
items: [
{ name: 'JTL WAWI', level: 85 },
{ name: 'Server', level: 75 },
{ name: 'AirFlow', level: 60 }
]
}
],
ui: {
percentage: 'percent',
levelLabel: 'Level',
skillLevel: '{{level}}% proficiency in {{skill}}'
},
aria: {
skillGroup: 'Skill group for {{category}}',
skillBar: 'Progress bar for {{skill}}',
skillIcon: 'Icon for {{category}}',
selectSkill: 'Select skill'
},
screenReader: {
skillProgress: '{{skill}} with a level of {{level}} percent'
}
} as const;
export type SkillsTranslations = typeof skills;
@@ -0,0 +1,44 @@
export const workflow = {
// Page title
title: 'MY WORKFLOW',
description: 'Systematic approach to software development through defined steps',
// Workflow steps
steps: [
{
number: '01',
title: 'REQUIREMENTS ANALYSIS'
},
{
number: '02',
title: 'ASSESSMENT OF DEADLINES AND CONSTRAINTS'
},
{
number: '03',
title: 'DEVELOPMENT ENVIRONMENT SETUP'
},
{
number: '04',
title: 'PROGRAMMING'
},
{
number: '05',
title: 'TESTING THE RESULTS'
},
{
number: '06',
title: 'CODE SUPPORT AND SCALING'
}
],
// Aria Labels for accessibility
aria: {
workflowSection: 'Workflow Process',
stepNumber: 'Step {{number}}',
stepDescription: 'Workflow step: {{title}}'
},
// Screen Reader texts
screenReader: {
stepProgress: 'Step {{number}} of {{total}}: {{title}}'
}
} as const;
// Type for type safety
export type WorkflowTranslations = typeof workflow;
@@ -0,0 +1,41 @@
// src/i18n/locales/en/pages/contact/contactform.ts
export const contactform = {
// Form Header
title: 'Contact Me',
description: 'Have questions or want to collaborate? Send me a message.',
// Form Fields
name: {
label: 'Name',
placeholder: 'Your full name'
},
email: {
label: 'Email',
placeholder: 'your.email@example.com'
},
message: {
label: 'Message',
placeholder: 'Your message to me...'
},
// Button
submit: 'Send Message',
// Status Messages
successMessage: 'Thank you for your message! I will get back to you as soon as possible.',
errorMessage: 'Sorry, there was an error sending your message. Please try again later.',
// Error Messages
errors: {
nameRequired: 'Please enter your name',
emailRequired: 'Please enter your email address',
emailInvalid: 'Please enter a valid email address',
messageRequired: 'Please enter a message'
},
// Aria Labels
aria: {
form: 'Contact form',
submitting: 'Sending form',
successAlert: 'Success message',
errorAlert: 'Error message'
}
} as const;
// Type for type safety
export type ContactFormTranslations = typeof contactform;
@@ -0,0 +1,27 @@
// src/i18n/locales/en/pages/contact/contactinfo.ts
export const contactinfo = {
// Header
title: 'Contact Information',
description: 'You can reach me through the following channels',
// Contact Method Labels
addressLabel: 'Office Location',
phoneLabel: 'Phone',
emailLabel: 'Email',
// Contact Information
address: 'Rotdornallee, Köln',
phone: '+49 175 695 0979',
email: 'info@damjan-savic.com',
// Additional Information
availabilityNote: 'Business hours: Monday to Friday, 9:00 AM - 5:00 PM',
// Aria Labels
aria: {
contactCard: 'Contact information card',
addressLink: 'Open location in Google Maps',
phoneLink: 'Call',
emailLink: 'Send email',
externalLink: 'Opens in new tab'
}
} as const;
// Type for type safety
export type ContactInfoTranslations = typeof contactinfo;
@@ -0,0 +1,71 @@
// src/i18n/locales/en/pages/contact/index.ts
export const contact = {
breadcrumb: "CONTACT",
hero: {
title: "Let's Work Together",
subtitle: "Have a project in mind? Let's discuss how we can help you achieve your goals."
},
contactInfo: {
title: "Contact Information",
description: "You can reach me through the following channels",
address: {
label: "Office Location",
value: "Rotdornallee, Köln"
},
phone: {
label: "Phone",
value: "+49 175 695 0979"
},
email: {
label: "Email",
value: "info@damjan-savic.com"
},
availabilityNote: "Business hours: Monday to Friday, 9:00 AM - 5:00 PM",
aria: {
contactCard: "Contact information card",
addressLink: "Open location in Google Maps",
phoneLink: "Call",
emailLink: "Send email",
externalLink: "Opens in new tab"
}
},
contactForm: {
title: "Contact Me",
description: "Have questions or want to collaborate? Send me a message.",
name: {
label: "Name",
placeholder: "Your full name"
},
email: {
label: "Email",
placeholder: "your.email@example.com"
},
message: {
label: "Message",
placeholder: "Your message to me..."
},
submit: "Send Message",
successMessage: "Thank you for your message! I will get back to you as soon as possible.",
errorMessage: "Sorry, there was an error sending your message. Please try again later.",
errors: {
nameRequired: "Please enter your name",
emailRequired: "Please enter your email address",
emailInvalid: "Please enter a valid email address",
messageRequired: "Please enter a message"
},
aria: {
form: "Contact form",
submitting: "Sending form",
successAlert: "Success message",
errorAlert: "Error message"
}
}
} as const;
export type ContactTranslations = typeof contact;
export default {
pages: {
contact: contact
}
};
+76
View File
@@ -0,0 +1,76 @@
// src/i18n/locales/en/pages/dashboard.ts
export const dashboard = {
// SEO
seo: {
title: 'Analytics Dashboard',
description: 'Website Analysis Dashboard'
},
// Main headings
header: {
title: 'Analytics Dashboard',
activeUsers: 'active users'
},
// Metric cards
metrics: {
pageViews: {
title: 'Page Views',
perMinute: 'per minute'
},
uniqueVisitors: {
title: 'Unique Visitors',
currentlyActive: 'currently active'
},
conversions: {
title: 'Conversions',
rate: 'conversion rate'
},
timeOnSite: {
title: 'Avg. Time on Site',
bounceRate: 'bounce rate'
}
},
// Top pages section
topPages: {
title: 'Top Pages',
columns: {
path: 'Path',
views: 'Views',
change: 'Change'
}
},
// Event tracking section
events: {
title: 'Event Tracking',
types: {
contactForm: 'Contact Form Submission',
portfolioView: 'Portfolio View',
cvDownload: 'CV Download',
blogRead: 'Blog Read'
}
},
// Status messages
status: {
loading: 'Loading Dashboard...',
error: 'Error loading data',
notAuthenticated: 'Please sign in'
},
// Miscellaneous
misc: {
viewMore: 'View More',
refresh: 'Refresh',
period: {
today: 'Today',
yesterday: 'Yesterday',
last7Days: 'Last 7 Days',
last30Days: 'Last 30 Days',
thisMonth: 'This Month',
lastMonth: 'Last Month'
}
},
// Trends and changes
trends: {
increase: 'Increase',
decrease: 'Decrease',
noChange: 'No Change'
}
};
+9
View File
@@ -0,0 +1,9 @@
// src/i18n/locales/en/pages/home/about.ts
export const about = {
title: 'About Me',
content: 'As a digital transformation consultant, I help companies improve their processes through modern software. I develop solutions for connecting inventory management systems, programs for workflow automation, and RFID applications for better product tracking. At Ritter Digital GmbH, I work with JTL software and develop custom program solutions. Another project involved connecting Breuninger\'s systems with Apparel Magic via TB.One. My goal is to make companies more efficient through software.',
image: {
alt: 'Portrait of Damjan Savić'
}
} as const;
export type AboutTranslations = typeof about;
@@ -0,0 +1,77 @@
// src/i18n/locales/en/pages/home/experience.ts
export const experience = {
title: 'Professional Experience',
navigation: {
prev: '←',
next: '→'
},
positions: [
{
role: 'Consultant Digital Solutions & Developer',
company: 'RITTER Gesellschaft für digitale Geschäftsprozesse mbH',
period: '08/2023 - PRESENT',
highlights: [
'JTL WaWi, WMS and POS consulting & implementation',
'Python-based automation solutions',
'RFID systems and GUI development',
'AI & Business Intelligence'
]
},
{
role: 'ERP Integration Specialist & E-Commerce Developer',
company: 'Joyce & Girls',
period: '01/2023 - 08/2023',
highlights: [
'ApparelMagic & TradeByte integration',
'MariaDB middleware development',
'Windows Server administration',
'Shopify optimization'
]
},
{
role: 'RPA Developer & E-Commerce Manager',
company: 'C&S Marketing',
period: '08/2022 - 01/2023',
highlights: [
'Shopware 6 & JTL integration',
'Python automation',
'Google Ads optimization',
'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',
'Product photography',
'Luxury watch segment sales',
'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',
'Event organization',
'Marketing automation'
]
}
]
} as const;
export type ExperienceTranslations = typeof experience;
@@ -0,0 +1,27 @@
// src/i18n/locales/en/pages/home/expertise.ts
export const expertise = {
title: 'Areas of Expertise',
areas: [
{
title: 'ERP Integration',
description: 'Expert in JTL-Wawi implementation, configuration, and optimization. Specialized in inventory management systems and POS integration.',
skills: ['JTL-Wawi', 'JTL-WMS', 'JTL-POS', 'Apparel Magic']
},
{
title: 'Development',
description: 'Full-stack development with focus on Python automation, React frontends, and database design.',
skills: ['Python', 'React/Next.js', 'MariaDB', 'Docker']
},
{
title: 'E-Commerce',
description: 'Extensive experience with various e-commerce platforms and marketplace integrations.',
skills: ['Shopify', 'Shopware', 'WooCommerce', 'API Integration']
},
{
title: 'Digital Marketing',
description: 'Strategic approach to digital marketing with focus on automation and analytics.',
skills: ['Google Ads', 'Meta Ads', 'SEO', 'Analytics']
}
]
} as const;
export type ExpertiseTranslations = typeof expertise;
+28
View File
@@ -0,0 +1,28 @@
// src/i18n/locales/en/pages/home/hero.ts
export const hero = {
title: 'SOFTWARE ENGINEER',
name: 'DAMJAN SAVIĆ',
cta: 'GET IN TOUCH',
image: {
alt: 'Portrait of Damjan Savić'
},
social: {
getInTouch: 'Get in touch',
linkedin: {
title: 'Visit my LinkedIn profile'
},
github: {
title: 'Visit my GitHub profile'
},
email: {
title: 'Send me an email'
}
},
navigation: {
experience: 'EXPERIENCE',
skills: 'SKILLS',
projects: 'PROJECTS',
about: 'ABOUT'
}
} as const;
export type HeroTranslations = typeof hero;
+25
View File
@@ -0,0 +1,25 @@
// 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;
// Re-export individual sections for direct access
export {
hero,
about,
experience,
expertise,
skills,
projects
};
@@ -0,0 +1,10 @@
// src/i18n/locales/en/pages/home/projects.ts
export const projects = {
title: 'Portfolio',
viewAll: 'All Projects →',
loading: 'Loading projects...',
error: {
loading: 'Error loading projects'
}
} as const;
export type ProjectsTranslations = typeof projects;
+41
View File
@@ -0,0 +1,41 @@
// src/i18n/locales/en/pages/home/skills.ts
export const skills = {
title: 'Skills',
skills: [
{
name: 'ERP',
level: 90,
description: 'Enterprise Resource Planning'
},
{
name: 'Database',
level: 85,
description: 'Database development and administration'
},
{
name: 'E-Commerce',
level: 95,
description: 'Online commerce and platforms'
},
{
name: 'Python',
level: 80,
description: 'Python programming language'
},
{
name: 'React',
level: 75,
description: 'Frontend development with React'
},
{
name: 'Server',
level: 70,
description: 'Server administration'
}
],
aria: {
skillLevel: 'Skill level',
selectSkill: 'Select skill'
}
} as const;
export type SkillsTranslations = typeof skills;
+54
View File
@@ -0,0 +1,54 @@
// src/i18n/locales/en/pages/login.ts
export const login = {
// SEO
seo: {
title: 'Login',
description: 'Sign in to access the dashboard'
},
// Main heading
header: {
title: 'Sign in to Dashboard'
},
// Form
form: {
// Fields
email: {
label: 'Email Address',
placeholder: 'your.email@example.com'
},
password: {
label: 'Password',
placeholder: 'Your password'
},
// Buttons
submit: {
default: 'Sign In',
loading: 'Signing in...'
},
// Error messages
errors: {
default: 'An error has occurred',
invalidCredentials: 'Invalid credentials',
emailRequired: 'Please enter your email address',
passwordRequired: 'Please enter your password',
emailInvalid: 'Please enter a valid email address'
}
},
// Links and help
help: {
forgotPassword: 'Forgot Password?',
needHelp: 'Need Help?',
contactSupport: 'Contact Support'
},
// Status messages
status: {
authenticating: 'Authenticating...',
success: 'Successfully signed in',
redirecting: 'Redirecting to dashboard...'
},
// Security notices
security: {
secureConnection: 'Secure Connection',
privacyNote: 'Your data is transmitted encrypted'
}
};
+19
View File
@@ -0,0 +1,19 @@
// src/i18n/locales/en/pages/notfound.ts
export const notfound = {
// SEO
seo: {
title: '404 - Page Not Found',
description: 'The requested page does not exist.'
},
// Main content
content: {
errorCode: '404',
title: 'Page Not Found',
description: 'The page you are looking for does not exist or has been moved.',
},
// Action buttons
actions: {
goBack: 'Go Back',
homePage: 'Home Page'
}
};
+111
View File
@@ -0,0 +1,111 @@
// src/i18n/locales/en/pages/portfolio.ts
export const portfolio = {
// SEO and meta information
seo: {
title: 'Portfolio - Damjan Savić',
description: 'Discover my projects in JTL integration, e-commerce, and digital transformation.'
},
// Main page
main: {
title: 'Portfolio',
loading: 'Loading projects...',
error: 'Error loading projects',
noProjects: {
title: 'No Projects Found',
description: 'Currently, no projects are available. Please check back later.'
}
},
// Project cards
projectCard: {
date: 'Date',
technologies: 'Technologies',
moreCount: 'more', // for '+X more'
readMore: 'Learn More'
},
// Project details
project: {
navigation: {
back: 'Back to Portfolio',
projectDetails: 'PROJECT DETAILS'
},
metadata: {
date: 'Date',
client: 'Client',
duration: 'Duration',
repository: 'Repository',
documentation: 'Documentation',
technologies: 'Technologies',
live: 'Live Version'
},
sections: {
overview: 'Overview',
challenge: 'Challenge',
solution: 'Solution',
results: 'Results',
systemArchitecture: 'System Architecture',
implementation: 'Implementation',
technologies: 'Technologies Used'
}
},
// Categories and filters
categories: {
all: 'All',
'Data Science': 'Data Science',
'AI Development': 'AI Development',
'Integration': 'Integration',
'Full-Stack Development': 'Full-Stack Development',
'Data Processing': 'Data Processing',
'Content Production': 'Content Production',
'Machine Learning': 'Machine Learning',
'Automation': 'Automation'
},
// Specific projects
projects: {
'ai-data-reader': {
title: 'AI-Based Product Data Management from PDF Files',
description: 'Development of an automated system for extracting and structuring product data from PDF documents'
},
'bi-vision': {
title: 'AI Videos for BI Software',
description: 'Development of AI-powered explainer videos for business intelligence dashboards'
},
'business-intelligence-ai': {
title: 'AI for Business Intelligence',
description: 'Integration of AI models into business intelligence systems for process optimization'
},
'claude-personal-assistant': {
title: 'AI-Based Personal Assistant with Claude AI',
description: 'Development of a personalized AI assistant for professional email communication'
},
'e-commerce-integration': {
title: 'Integration with TradeByte',
description: 'Integration of a Shopify store with JTL-WaWi for optimized inventory management'
},
'jtl-integration-project': {
title: 'JTL Integration Reference Project',
description: 'A complete warehouse system in Krefeld based on JTL'
},
'local-llm-training': {
title: 'Training of Local AI Models',
description: 'Development of a pipeline for training and fine-tuning local AI models'
},
'processautomation': {
title: 'Automation with Python',
description: 'Development of automation solutions for business processes'
},
'rfid-automation': {
title: 'RFID Automation',
description: 'Development of an automated system for creating and printing RFID labels'
},
'timetracking-software': {
title: 'Digital Time Tracking',
description: 'Development of a modern time tracking solution with Next.js, Flask, and MSSQL'
}
},
// Status messages
status: {
loading: 'Loading...',
error: 'An error has occurred',
success: 'Successfully loaded'
}
};
+96
View File
@@ -0,0 +1,96 @@
// src/i18n/locales/en/pages/privacy.ts
export const privacy = {
// SEO and Schema
seo: {
title: 'Privacy Policy',
description: 'Privacy Policy for Damjan Savić\'s portfolio website'
},
schema: {
name: 'Privacy Policy',
description: 'Privacy Policy for Damjan Savić\'s portfolio website'
},
// Main content
content: {
title: 'Privacy Policy',
lastUpdated: 'Last updated: March 10, 2024',
// Navigation
breadcrumbs: {
currentTitle: 'Privacy Policy'
},
// Sections
sections: {
introduction: {
title: '1. Introduction',
content: 'This Privacy Policy explains how we collect, use, and protect your personal data when you use our website.'
},
dataCollection: {
title: '2. Data Collection',
providedInfo: {
title: '2.1 Information You Provide',
intro: 'When using our contact form, we collect:',
items: [
'Name',
'Email address',
'Message content'
]
},
automaticInfo: {
title: '2.2 Automatically Collected Information',
intro: 'We automatically collect:',
items: [
'IP address',
'Browser type',
'Device information',
'Pages visited',
'Time spent on the website'
]
}
},
dataUsage: {
title: '3. Use of Your Data',
intro: 'We use your data for:',
items: [
'Responding to your inquiries',
'Improving our website',
'Analyzing usage patterns',
'Fraud prevention'
]
},
cookies: {
title: '4. Cookies',
intro: 'We use cookies for:',
items: [
'Storing your preferences',
'Analyzing website traffic',
'Understanding user behavior'
]
},
security: {
title: '5. Data Security',
intro: 'We implement appropriate security measures to protect your personal data, including:',
items: [
'Data transmission encryption',
'Regular security assessments',
'Access controls',
'Secure data storage'
]
},
rights: {
title: '6. Your Rights',
intro: 'You have the right to:',
items: [
'Access your personal data',
'Rectify the data',
'Delete the data',
'Object to data processing',
'Data portability'
]
},
contact: {
title: '7. Contact Information',
intro: 'For privacy-related inquiries, contact us at:',
email: 'Email: privacy@damjan-savic.com'
}
}
}
};
+59
View File
@@ -0,0 +1,59 @@
// src/i18n/locales/en/pages/terms.ts
export const terms = {
// SEO and Schema
seo: {
title: 'Terms and Conditions',
description: 'Terms and Conditions for Damjan Savić\'s portfolio website'
},
schema: {
name: 'Terms and Conditions',
description: 'Terms and Conditions for Damjan Savić\'s portfolio website'
},
// Main content
content: {
title: 'Terms and Conditions',
lastUpdated: 'Last updated: March 10, 2024',
// Navigation
breadcrumbs: {
currentTitle: 'Terms and Conditions'
},
// Sections
sections: {
agreement: {
title: '1. Agreement to Terms',
content: 'By accessing our website, you agree to be bound by these Terms and Conditions and to comply with all applicable laws and regulations.'
},
intellectualProperty: {
title: '2. Intellectual Property Rights',
content: 'All content on this website, including but not limited to text, graphics, logos, images, and software, is the property of Damjan Savić and is protected by intellectual property laws.'
},
userResponsibilities: {
title: '3. User Responsibilities',
intro: 'When using our website, you agree to:',
items: [
'Provide accurate information',
'Use the website legally and ethically',
'Not attempt unauthorized access',
'Not disrupt the website\'s operation'
]
},
liability: {
title: '4. Limitation of Liability',
content: 'We are not liable for any indirect, incidental, special, consequential, or punitive damages resulting from your use or inability to use the website.'
},
changes: {
title: '5. Changes to Terms',
content: 'We reserve the right to modify these terms at any time. We will notify users of any material changes by posting the new Terms and Conditions on this page.'
},
governingLaw: {
title: '6. Governing Law',
content: 'These terms are governed by and construed in accordance with the laws of the Federal Republic of Germany, without regard to its conflict of law provisions.'
},
contact: {
title: '7. Contact Information',
intro: 'For questions about these Terms and Conditions, please contact us at:',
email: 'Email: legal@damjan-savic.com'
}
}
}
};
+53
View File
@@ -0,0 +1,53 @@
// src/i18n/locales/en/portfolio/index.ts
import { aiDataReader } from './projects/ai-data-reader';
export const portfolio = {
// Meta information for the portfolio page
seo: {
title: 'Portfolio - Damjan Savić',
description: 'Discover my projects in JTL integration, e-commerce, and digital transformation.'
},
// Portfolio headings and filters
sections: {
title: 'Portfolio',
subtitle: 'Selected projects and references',
filterTitle: 'Categories',
sortTitle: 'Sort'
},
// Filter options
filters: {
all: 'All',
categories: {
'Data Science': 'Data Science',
'AI Development': 'AI Development',
'Integration': 'Integration',
'Full-Stack Development': 'Full-Stack Development',
'Data Processing': 'Data Processing',
'Content Production': 'Content Production',
'Machine Learning': 'Machine Learning',
'Automation': 'Automation'
}
},
// Sort options
sort: {
date: 'Date',
title: 'Title',
category: 'Category'
},
// UI texts
ui: {
loading: 'Loading projects...',
noProjects: 'No projects found',
viewProject: 'View project',
backToPortfolio: 'Back to portfolio',
technologies: 'Technologies',
client: 'Client',
duration: 'Duration',
visitWebsite: 'Visit website',
viewRepository: 'View repository',
viewDocumentation: 'Documentation'
},
// All projects
projects: {
'ai-data-reader': aiDataReader,
}
};
@@ -0,0 +1,107 @@
// src/i18n/locales/en/portfolio/projects/ai-data-reader.ts
export const aiDataReader = {
meta: {
slug: 'ai-data-reader',
title: "AI-Based Product Data Management from PDF Files",
description: "Development of an automated system for extracting and structuring product data from PDF documents",
excerpt: "Integration of Claude AI for intelligent processing of product information and seamless JTL ERP integration.",
date: "2024-02",
category: "Data Processing",
client: "Amazon Seller",
duration: "2 months",
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: "An AI-powered system for automated extraction of product data from PDF documents with direct integration into JTL inventory management systems, developed for maximum efficiency in product data management.",
challenge: {
title: "The Challenge",
description: "Manual processing of product data from PDF documents was time-consuming and error-prone.",
points: [
"Large volumes of PDF documents containing product information",
"Time-intensive manual data entry",
"Inconsistent data quality",
"High personnel requirements"
]
},
solution: {
title: "Our Solution",
description: "Development of an AI-powered system for automated data extraction",
content: "By leveraging Claude AI and modern Python technologies, we created a fully automated solution that processes PDF documents and integrates the extracted data directly into the JTL inventory management system.",
points: [
"Automated PDF processing",
"AI-powered data extraction",
"Intelligent data validation",
"Seamless JTL integration"
]
},
technical: {
title: "Technical Implementation",
description: "The solution is based on a modular Python architecture with several core components:",
points: [
"Robust PDF text extraction with PyPDF",
"AI-powered data extraction with Claude AI",
"Validation through Pydantic Models",
"JTL ERP integration via 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]:
'''Extracts structured data with 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: "Implementation Process",
description: "The automated workflow was implemented in several phases:",
points: [
"PDF batch processing from input directory",
"Intelligent text recognition and structuring",
"Multi-layer validation logic",
"Robust error handling",
"Integration with existing systems"
]
},
results: {
title: "Results and Impact",
description: "The implementation led to significant improvements in business processes:",
points: [
"90% time savings in product data management",
"99% accuracy in data extraction",
"Elimination of manual data entry",
"Standardized product data quality",
"Significantly reduced error rate"
]
},
conclusion: "The developed system has revolutionized product data management. By combining AI technology with automated data processing, we not only drastically increased efficiency but also significantly improved data quality. The project demonstrates impressively how modern AI solutions can solve practical business problems."
}
};
// Re-export for compatibility with the project import system
export default aiDataReader;