openfree commited on
Commit
f4f75b1
·
verified ·
1 Parent(s): 470dd49

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +329 -37
app.py CHANGED
@@ -10,9 +10,304 @@ from travel import (
10
  run_task
11
  )
12
 
13
- # Set page configuration with modern theme
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  st.set_page_config(
15
- page_title="Globetrotter AI: Your AI Agent for Travelling",
16
  page_icon="✈️",
17
  layout="wide",
18
  initial_sidebar_state="expanded"
@@ -233,19 +528,19 @@ st.markdown("""
233
  # Helper function to download HTML file
234
  def get_download_link(text_content, filename):
235
  b64 = base64.b64encode(text_content.encode()).decode()
236
- href = f'<a class="download-link" href="data:text/plain;base64,{b64}" download="{filename}"><i>📥</i> Download Itinerary as Text</a>'
237
  return href
238
 
239
  # Updated helper function to display modern progress with a single UI element
240
  def display_modern_progress(current_step, total_steps=6):
241
  if 'progress_steps' not in st.session_state:
242
  st.session_state.progress_steps = {
243
- 0: {'status': 'pending', 'name': 'Destination Research'},
244
- 1: {'status': 'pending', 'name': 'Accommodation'},
245
- 2: {'status': 'pending', 'name': 'Transportation'},
246
- 3: {'status': 'pending', 'name': 'Activities'},
247
- 4: {'status': 'pending', 'name': 'Dining'},
248
- 5: {'status': 'pending', 'name': 'Itinerary Creation'}
249
  }
250
 
251
  # Update the current step status
@@ -416,13 +711,13 @@ if 'form_submitted' not in st.session_state:
416
  st.session_state.form_submitted = False
417
 
418
  # Modern animated header
419
- st.markdown('''
420
  <div class="animate-in" style="text-align: center;">
421
  <div style="margin-bottom: 20px;">
422
  <img src="https://img.icons8.com/fluency/96/travel-card.png" width="90"
423
  style="filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));">
424
  </div>
425
- <h1 class="main-header">Globetrotter AI: Your AI Agent for Travelling</h1>
426
  <p style="font-size: 1.2rem; color: #6c757d; margin-bottom: 25px;">
427
  ✨ Create your personalized AI-powered travel itinerary in minutes! ✨
428
  </p>
@@ -447,7 +742,7 @@ with st.sidebar:
447
 
448
  # About section with modern container
449
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
450
- st.markdown("### 🌟 About")
451
  st.info(
452
  "This AI-powered tool creates a personalized travel itinerary based on your preferences. "
453
  "Fill in the form and let our specialized travel agents plan your perfect trip!"
@@ -456,7 +751,7 @@ with st.sidebar:
456
 
457
  # How it works with steps and icons
458
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
459
- st.markdown("### 🔍 How it works")
460
  st.markdown("""
461
  <ol style="padding-left: 25px;">
462
  <li><b>🖊️ Enter</b> your travel details</li>
@@ -487,7 +782,7 @@ with st.sidebar:
487
  if not st.session_state.generation_complete:
488
  # Sleek form with minimal design
489
  st.markdown('<div class="modern-card animate-in">', unsafe_allow_html=True)
490
- st.markdown("<h3 style='font-weight: 600; color: var(--primary-dark); display: flex; align-items: center; gap: 10px;'><span style='font-size: 20px;'>✈️</span> Create Your Itinerary</h3>", unsafe_allow_html=True)
491
 
492
  # Minimalist description
493
  st.markdown("""
@@ -500,14 +795,13 @@ if not st.session_state.generation_complete:
500
 
501
  with col1:
502
  st.markdown('<p style="font-weight: 500; color: var(--primary); font-size: 14px; margin-bottom: 12px;">Trip Details</p>', unsafe_allow_html=True)
503
- origin = st.text_input("Origin", placeholder="e.g., New York, USA")
504
- destination = st.text_input("Destination", placeholder="e.g., Paris, France")
505
 
506
  # Minimalist date picker
507
  st.markdown('<p style="margin-bottom: 5px; font-size: 14px;">Travel Dates</p>', unsafe_allow_html=True)
508
  start_date = st.date_input("Start Date", min_value=datetime.now(), label_visibility="collapsed")
509
- end_date = start_date + timedelta(days=7)
510
- duration = st.slider("Duration (days)", min_value=1, max_value=30, value=7)
511
  end_date = start_date + timedelta(days=duration-1)
512
  st.markdown(f'<p style="font-size: 13px; color: var(--text-muted); margin-top: 5px;">{start_date.strftime("%b %d")} - {end_date.strftime("%b %d, %Y")}</p>', unsafe_allow_html=True)
513
 
@@ -531,7 +825,7 @@ if not st.session_state.generation_complete:
531
  placeholder="Dietary restrictions, accessibility needs...")
532
 
533
  # Submit button with enhanced styling
534
- submit_button = st.form_submit_button("🚀 Create My Personal Travel Itinerary")
535
 
536
  st.markdown('</div>', unsafe_allow_html=True)
537
 
@@ -633,19 +927,19 @@ Special Requirements: {user_input['special_requirements']}
633
 
634
  # Show request details in the details tab
635
  with details_tab:
636
- st.markdown("#### Your Travel Request")
637
- st.markdown(f"**Destination:** {user_input['destination']}")
638
- st.markdown(f"**From:** {user_input['origin']}")
639
- st.markdown(f"**When:** {user_input['travel_dates']} ({user_input['duration']} days)")
640
- st.markdown(f"**Budget:** {user_input['budget'].title()}")
641
- st.markdown(f"**Travel Style:** {user_input['travel_style']}")
642
  if user_input['preferences']:
643
  st.markdown(f"**Interests:** {user_input['preferences']}")
644
  if user_input['special_requirements']:
645
  st.markdown(f"**Special Requirements:** {user_input['special_requirements']}")
646
 
647
  with progress_tab:
648
- # Create a persistent placeholder for progress display to avoid duplication
649
  if 'progress_placeholder' not in st.session_state:
650
  st.session_state.progress_placeholder = st.empty()
651
  with st.session_state.progress_placeholder.container():
@@ -660,7 +954,7 @@ Special Requirements: {user_input['special_requirements']}
660
  output_container = st.container()
661
  with output_container:
662
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
663
- st.markdown("### 🌟 Live Agent Outputs")
664
  st.info("Our AI agents will show their work here as they create your itinerary")
665
  st.markdown('</div>', unsafe_allow_html=True)
666
 
@@ -890,7 +1184,7 @@ if st.session_state.generation_complete:
890
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
891
 
892
  # Modern tabs for different views
893
- itinerary_tab, details_tab, download_tab = st.tabs(["🗒️ Full Itinerary", "💼Details", "💾 Download & Share"])
894
 
895
  with itinerary_tab:
896
  # Preview the itinerary as text
@@ -923,13 +1217,11 @@ if st.session_state.generation_complete:
923
  st.markdown("### 🍽️ Dining Recommendations")
924
  st.markdown(st.session_state.results["dining_info"])
925
 
926
-
927
-
928
  with download_tab:
929
  col1, col2 = st.columns([2, 1])
930
 
931
  with col1:
932
- st.markdown("### Save Your Itinerary")
933
  st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
934
 
935
  # Display stylized download button
@@ -948,18 +1240,18 @@ if st.session_state.generation_complete:
948
  st.markdown("</div>", unsafe_allow_html=True)
949
 
950
  # Share options
951
- st.markdown("### Share Your Itinerary")
952
  st.markdown("*Coming soon: Email your itinerary or share via social media.*")
953
 
954
  with col2:
955
  # QR code placeholder for future implementation
956
- st.markdown("### Save for Mobile")
957
  st.markdown("*Coming soon: QR code for easy access on your phone*")
958
 
959
  st.markdown('</div>', unsafe_allow_html=True)
960
 
961
  # Add a reset button to create a new itinerary
962
- if st.button("🔄 Plan Another Trip", key="reset_button"):
963
  # Reset the session state
964
  st.session_state.generated_itinerary = None
965
  st.session_state.generation_complete = False
@@ -969,9 +1261,9 @@ if st.session_state.generation_complete:
969
  st.experimental_rerun()
970
 
971
  # Footer for the app
972
- st.markdown("""
973
  <div style="margin-top: 50px; text-align: center; padding: 20px; color: #6c757d; font-size: 0.8rem;">
974
- <p>Built with ❤️ for you</p>
975
  </div>
976
  """, unsafe_allow_html=True)
977
 
@@ -1007,4 +1299,4 @@ st.markdown("""
1007
  <p>Built with ❤️ for You</p>
1008
  </div>
1009
  </div>
1010
- """, unsafe_allow_html=True)
 
10
  run_task
11
  )
12
 
13
+ # ------------------------------------------
14
+ # 다국어 지원을 위한 번역 사전 및 헬퍼 함수
15
+ # ------------------------------------------
16
+ translations = {
17
+ "en": {
18
+ "page_title": "Globetrotter AI: Your AI Agent for Travelling",
19
+ "header": "Globetrotter AI: Your AI Agent for Travelling",
20
+ "create_itinerary": "Create Your Itinerary",
21
+ "trip_details": "Trip Details",
22
+ "origin": "Origin",
23
+ "destination": "Destination",
24
+ "travel_dates": "Travel Dates",
25
+ "duration": "Duration (days)",
26
+ "preferences": "Preferences",
27
+ "additional_preferences": "Additional Preferences",
28
+ "interests": "Interests",
29
+ "special_requirements": "Special Requirements",
30
+ "submit": "🚀 Create My Personal Travel Itinerary",
31
+ "request_details": "Your Travel Request",
32
+ "from": "From",
33
+ "when": "When",
34
+ "budget": "Budget",
35
+ "travel_style": "Travel Style",
36
+ "live_agent_outputs": "Live Agent Outputs",
37
+ "full_itinerary": "Full Itinerary",
38
+ "details": "Details",
39
+ "download_share": "Download & Share",
40
+ "save_itinerary": "Save Your Itinerary",
41
+ "plan_another_trip": "🔄 Plan Another Trip",
42
+ "about": "About",
43
+ "how_it_works": "How it works",
44
+ "travel_agents": "Travel Agents",
45
+ "share_itinerary": "Share Your Itinerary",
46
+ "save_for_mobile": "Save for Mobile",
47
+ "built_with": "Built with ❤️ for you"
48
+ },
49
+ "ko": {
50
+ "page_title": "Globetrotter AI: 당신의 여행을 위한 AI 에이전트",
51
+ "header": "Globetrotter AI: 당신의 여행을 위한 AI 에이전트",
52
+ "create_itinerary": "여행 일정 생성",
53
+ "trip_details": "여행 세부 정보",
54
+ "origin": "출발지",
55
+ "destination": "목적지",
56
+ "travel_dates": "여행 날짜",
57
+ "duration": "기간 (일수)",
58
+ "preferences": "선호사항",
59
+ "additional_preferences": "추가 선호사항",
60
+ "interests": "관심사",
61
+ "special_requirements": "특별 요구사항",
62
+ "submit": "🚀 나만의 여행 일정 생성",
63
+ "request_details": "여행 요청 정보",
64
+ "from": "출발지",
65
+ "when": "여행 기간",
66
+ "budget": "예산",
67
+ "travel_style": "여행 스타일",
68
+ "live_agent_outputs": "실시간 에이전트 결과",
69
+ "full_itinerary": "전체 일정",
70
+ "details": "세부사항",
71
+ "download_share": "다운로드 및 공유",
72
+ "save_itinerary": "일정 저장",
73
+ "plan_another_trip": "🔄 다른 여행 계획",
74
+ "about": "소개",
75
+ "how_it_works": "작동 방식",
76
+ "travel_agents": "여행 에이전트",
77
+ "share_itinerary": "일정 공유",
78
+ "save_for_mobile": "모바일 저장",
79
+ "built_with": "당신을 위해 ❤️ 만들어졌습니다"
80
+ },
81
+ "ja": {
82
+ "page_title": "Globetrotter AI: あなたの旅行のためのAIエージェント",
83
+ "header": "Globetrotter AI: あなたの旅行のためのAIエージェント",
84
+ "create_itinerary": "旅行プラン作成",
85
+ "trip_details": "旅行詳細",
86
+ "origin": "出発地",
87
+ "destination": "目的地",
88
+ "travel_dates": "旅行日程",
89
+ "duration": "期間(日数)",
90
+ "preferences": "好み",
91
+ "additional_preferences": "追加の好み",
92
+ "interests": "興味",
93
+ "special_requirements": "特別な要件",
94
+ "submit": "🚀 私のための旅行プラン作成",
95
+ "request_details": "旅行リクエスト",
96
+ "from": "出発地",
97
+ "when": "旅行期間",
98
+ "budget": "予算",
99
+ "travel_style": "旅行スタイル",
100
+ "live_agent_outputs": "リアルタイムエージェント出力",
101
+ "full_itinerary": "全行程",
102
+ "details": "詳細",
103
+ "download_share": "ダウンロードと共有",
104
+ "save_itinerary": "旅行プランを保存",
105
+ "plan_another_trip": "🔄 他の旅行を計画",
106
+ "about": "概要",
107
+ "how_it_works": "使い方",
108
+ "travel_agents": "旅行エージェント",
109
+ "share_itinerary": "旅行プランを共有",
110
+ "save_for_mobile": "モバイル保存",
111
+ "built_with": "愛を込めて作られました"
112
+ },
113
+ "zh": {
114
+ "page_title": "Globetrotter AI:您的旅行 AI 代理",
115
+ "header": "Globetrotter AI:您的旅行 AI 代理",
116
+ "create_itinerary": "创建您的行程",
117
+ "trip_details": "旅行详情",
118
+ "origin": "出发地",
119
+ "destination": "目的地",
120
+ "travel_dates": "旅行日期",
121
+ "duration": "天数",
122
+ "preferences": "偏好",
123
+ "additional_preferences": "其他偏好",
124
+ "interests": "兴趣",
125
+ "special_requirements": "特殊需求",
126
+ "submit": "🚀 创建我的个性化行程",
127
+ "request_details": "您的旅行请求",
128
+ "from": "出发地",
129
+ "when": "旅行时间",
130
+ "budget": "预算",
131
+ "travel_style": "旅行风格",
132
+ "live_agent_outputs": "实时代理输出",
133
+ "full_itinerary": "完整行程",
134
+ "details": "详情",
135
+ "download_share": "下载与分享",
136
+ "save_itinerary": "保存行程",
137
+ "plan_another_trip": "🔄 计划另一趟旅行",
138
+ "about": "关于",
139
+ "how_it_works": "工作原理",
140
+ "travel_agents": "旅行代理",
141
+ "share_itinerary": "分享行程",
142
+ "save_for_mobile": "保存到手机",
143
+ "built_with": "用❤️为您制作"
144
+ },
145
+ "es": {
146
+ "page_title": "Globetrotter AI: Tu Agente de IA para Viajar",
147
+ "header": "Globetrotter AI: Tu Agente de IA para Viajar",
148
+ "create_itinerary": "Crea Tu Itinerario",
149
+ "trip_details": "Detalles del Viaje",
150
+ "origin": "Origen",
151
+ "destination": "Destino",
152
+ "travel_dates": "Fechas del Viaje",
153
+ "duration": "Duración (días)",
154
+ "preferences": "Preferencias",
155
+ "additional_preferences": "Preferencias Adicionales",
156
+ "interests": "Intereses",
157
+ "special_requirements": "Requisitos Especiales",
158
+ "submit": "🚀 Crea Mi Itinerario Personalizado",
159
+ "request_details": "Tu Solicitud de Viaje",
160
+ "from": "Desde",
161
+ "when": "Cuándo",
162
+ "budget": "Presupuesto",
163
+ "travel_style": "Estilo de Viaje",
164
+ "live_agent_outputs": "Salidas en Vivo del Agente",
165
+ "full_itinerary": "Itinerario Completo",
166
+ "details": "Detalles",
167
+ "download_share": "Descargar y Compartir",
168
+ "save_itinerary": "Guardar Itinerario",
169
+ "plan_another_trip": "🔄 Planear Otro Viaje",
170
+ "about": "Acerca de",
171
+ "how_it_works": "Cómo Funciona",
172
+ "travel_agents": "Agentes de Viaje",
173
+ "share_itinerary": "Compartir Itinerario",
174
+ "save_for_mobile": "Guardar para Móvil",
175
+ "built_with": "Hecho con ❤️ para ti"
176
+ },
177
+ "fr": {
178
+ "page_title": "Globetrotter AI : Votre Agent IA pour Voyager",
179
+ "header": "Globetrotter AI : Votre Agent IA pour Voyager",
180
+ "create_itinerary": "Créez Votre Itinéraire",
181
+ "trip_details": "Détails du Voyage",
182
+ "origin": "Origine",
183
+ "destination": "Destination",
184
+ "travel_dates": "Dates du Voyage",
185
+ "duration": "Durée (jours)",
186
+ "preferences": "Préférences",
187
+ "additional_preferences": "Préférences Supplémentaires",
188
+ "interests": "Centres d'intérêt",
189
+ "special_requirements": "Exigences Spéciales",
190
+ "submit": "🚀 Créez Mon Itinéraire Personnalisé",
191
+ "request_details": "Votre Demande de Voyage",
192
+ "from": "De",
193
+ "when": "Quand",
194
+ "budget": "Budget",
195
+ "travel_style": "Style de Voyage",
196
+ "live_agent_outputs": "Résultats en Direct de l'Agent",
197
+ "full_itinerary": "Itinéraire Complet",
198
+ "details": "Détails",
199
+ "download_share": "Télécharger et Partager",
200
+ "save_itinerary": "Enregistrer l'Itinéraire",
201
+ "plan_another_trip": "🔄 Planifier un Autre Voyage",
202
+ "about": "À Propos",
203
+ "how_it_works": "Fonctionnement",
204
+ "travel_agents": "Agents de Voyage",
205
+ "share_itinerary": "Partager l'Itinéraire",
206
+ "save_for_mobile": "Enregistrer pour Mobile",
207
+ "built_with": "Conçu avec ❤️ pour vous"
208
+ },
209
+ "de": {
210
+ "page_title": "Globetrotter AI: Ihr KI-Reiseassistent",
211
+ "header": "Globetrotter AI: Ihr KI-Reiseassistent",
212
+ "create_itinerary": "Erstellen Sie Ihre Reiseroute",
213
+ "trip_details": "Reisedetails",
214
+ "origin": "Abfahrtsort",
215
+ "destination": "Zielort",
216
+ "travel_dates": "Reisedaten",
217
+ "duration": "Dauer (Tage)",
218
+ "preferences": "Vorlieben",
219
+ "additional_preferences": "Zusätzliche Vorlieben",
220
+ "interests": "Interessen",
221
+ "special_requirements": "Besondere Anforderungen",
222
+ "submit": "🚀 Erstellen Sie meine personalisierte Reiseroute",
223
+ "request_details": "Ihre Reiseanfrage",
224
+ "from": "Von",
225
+ "when": "Wann",
226
+ "budget": "Budget",
227
+ "travel_style": "Reisestil",
228
+ "live_agent_outputs": "Live Agent Ausgaben",
229
+ "full_itinerary": "Komplette Reiseroute",
230
+ "details": "Details",
231
+ "download_share": "Herunterladen & Teilen",
232
+ "save_itinerary": "Reiseroute speichern",
233
+ "plan_another_trip": "🔄 Plane eine weitere Reise",
234
+ "about": "Über",
235
+ "how_it_works": "Wie es funktioniert",
236
+ "travel_agents": "Reiseassistenten",
237
+ "share_itinerary": "Reiseroute teilen",
238
+ "save_for_mobile": "Für Mobilgeräte speichern",
239
+ "built_with": "Mit ❤️ für Sie gebaut"
240
+ },
241
+ "ar": {
242
+ "page_title": "Globetrotter AI: وكيل السفر الذكي الخاص بك",
243
+ "header": "Globetrotter AI: وكيل السفر الذكي الخاص بك",
244
+ "create_itinerary": "إنشاء خط سير الرحلة",
245
+ "trip_details": "تفاصيل الرحلة",
246
+ "origin": "المغادرة من",
247
+ "destination": "الوجهة",
248
+ "travel_dates": "تواريخ السفر",
249
+ "duration": "المدة (بالأيام)",
250
+ "preferences": "التفضيلات",
251
+ "additional_preferences": "تفضيلات إضافية",
252
+ "interests": "الاهتمامات",
253
+ "special_requirements": "المتطلبات الخاصة",
254
+ "submit": "🚀 إنشاء خط سير الرحلة الشخصي",
255
+ "request_details": "طلب السفر الخاص بك",
256
+ "from": "من",
257
+ "when": "متى",
258
+ "budget": "الميزانية",
259
+ "travel_style": "أسلوب السفر",
260
+ "live_agent_outputs": "مخرجات الوكيل المباشرة",
261
+ "full_itinerary": "خط سير الرحلة الكامل",
262
+ "details": "التفاصيل",
263
+ "download_share": "تنزيل ومشاركة",
264
+ "save_itinerary": "حفظ خط سير الرحلة",
265
+ "plan_another_trip": "🔄 خطط لرحلة أخرى",
266
+ "about": "حول",
267
+ "how_it_works": "كيف يعمل",
268
+ "travel_agents": "وكلاء السفر",
269
+ "share_itinerary": "شارك خط سير الرحلة",
270
+ "save_for_mobile": "حفظ للهاتف المحمول",
271
+ "built_with": "مصنوع بحب من أجلك"
272
+ }
273
+ }
274
+
275
+ # 번역 헬퍼 함수: 선택된 언어에 따라 키 값을 반환합니다.
276
+ def t(key):
277
+ lang = st.session_state.get("selected_language", "en")
278
+ return translations[lang].get(key, key)
279
+
280
+ # ---------------------------
281
+ # 세션 초기화
282
+ # ---------------------------
283
+ if 'selected_language' not in st.session_state:
284
+ st.session_state.selected_language = "en" # 기본은 영어
285
+
286
+ # ------------------------------------------
287
+ # 사이드바에 언어 선택 위젯 추가
288
+ # ------------------------------------------
289
+ with st.sidebar:
290
+ language = st.selectbox(
291
+ "Language / 언어 / 言語 / 语言 / Idioma / Langue / Sprache / اللغة",
292
+ ["English", "한국어", "日本語", "中文", "Español", "Français", "Deutsch", "العربية"]
293
+ )
294
+ lang_map = {
295
+ "English": "en",
296
+ "한국어": "ko",
297
+ "日本語": "ja",
298
+ "中文": "zh",
299
+ "Español": "es",
300
+ "Français": "fr",
301
+ "Deutsch": "de",
302
+ "العربية": "ar"
303
+ }
304
+ st.session_state.selected_language = lang_map.get(language, "en")
305
+
306
+ # ------------------------------------------
307
+ # 페이지 설정 (번역 적용)
308
+ # ------------------------------------------
309
  st.set_page_config(
310
+ page_title=t("page_title"),
311
  page_icon="✈️",
312
  layout="wide",
313
  initial_sidebar_state="expanded"
 
528
  # Helper function to download HTML file
529
  def get_download_link(text_content, filename):
530
  b64 = base64.b64encode(text_content.encode()).decode()
531
+ href = f'<a class="download-link" href="data:text/plain;base64,{b64}" download="{filename}"><i>📥</i> {t("save_itinerary")}</a>'
532
  return href
533
 
534
  # Updated helper function to display modern progress with a single UI element
535
  def display_modern_progress(current_step, total_steps=6):
536
  if 'progress_steps' not in st.session_state:
537
  st.session_state.progress_steps = {
538
+ 0: {'status': 'pending', 'name': t("trip_details")},
539
+ 1: {'status': 'pending', 'name': t("about")}, # Accommodation
540
+ 2: {'status': 'pending', 'name': t("travel_style")}, # Transportation
541
+ 3: {'status': 'pending', 'name': t("live_agent_outputs")}, # Activities
542
+ 4: {'status': 'pending', 'name': t("download_share")}, # Dining
543
+ 5: {'status': 'pending', 'name': t("full_itinerary")}
544
  }
545
 
546
  # Update the current step status
 
711
  st.session_state.form_submitted = False
712
 
713
  # Modern animated header
714
+ st.markdown(f'''
715
  <div class="animate-in" style="text-align: center;">
716
  <div style="margin-bottom: 20px;">
717
  <img src="https://img.icons8.com/fluency/96/travel-card.png" width="90"
718
  style="filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));">
719
  </div>
720
+ <h1 class="main-header">{t("header")}</h1>
721
  <p style="font-size: 1.2rem; color: #6c757d; margin-bottom: 25px;">
722
  ✨ Create your personalized AI-powered travel itinerary in minutes! ✨
723
  </p>
 
742
 
743
  # About section with modern container
744
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
745
+ st.markdown(f"### 🌟 {t('about')}")
746
  st.info(
747
  "This AI-powered tool creates a personalized travel itinerary based on your preferences. "
748
  "Fill in the form and let our specialized travel agents plan your perfect trip!"
 
751
 
752
  # How it works with steps and icons
753
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
754
+ st.markdown(f"### 🔍 {t('how_it_works')}")
755
  st.markdown("""
756
  <ol style="padding-left: 25px;">
757
  <li><b>🖊️ Enter</b> your travel details</li>
 
782
  if not st.session_state.generation_complete:
783
  # Sleek form with minimal design
784
  st.markdown('<div class="modern-card animate-in">', unsafe_allow_html=True)
785
+ st.markdown(f"<h3 style='font-weight: 600; color: var(--primary-dark); display: flex; align-items: center; gap: 10px;'><span style='font-size: 20px;'>✈️</span> {t('create_itinerary')}</h3>", unsafe_allow_html=True)
786
 
787
  # Minimalist description
788
  st.markdown("""
 
795
 
796
  with col1:
797
  st.markdown('<p style="font-weight: 500; color: var(--primary); font-size: 14px; margin-bottom: 12px;">Trip Details</p>', unsafe_allow_html=True)
798
+ origin = st.text_input(t("origin"), placeholder="e.g., New York, USA")
799
+ destination = st.text_input(t("destination"), placeholder="e.g., Paris, France")
800
 
801
  # Minimalist date picker
802
  st.markdown('<p style="margin-bottom: 5px; font-size: 14px;">Travel Dates</p>', unsafe_allow_html=True)
803
  start_date = st.date_input("Start Date", min_value=datetime.now(), label_visibility="collapsed")
804
+ duration = st.slider(t("duration"), min_value=1, max_value=30, value=7)
 
805
  end_date = start_date + timedelta(days=duration-1)
806
  st.markdown(f'<p style="font-size: 13px; color: var(--text-muted); margin-top: 5px;">{start_date.strftime("%b %d")} - {end_date.strftime("%b %d, %Y")}</p>', unsafe_allow_html=True)
807
 
 
825
  placeholder="Dietary restrictions, accessibility needs...")
826
 
827
  # Submit button with enhanced styling
828
+ submit_button = st.form_submit_button(t("submit"))
829
 
830
  st.markdown('</div>', unsafe_allow_html=True)
831
 
 
927
 
928
  # Show request details in the details tab
929
  with details_tab:
930
+ st.markdown("#### " + t("request_details"))
931
+ st.markdown(f"**{t('destination')}:** {user_input['destination']}")
932
+ st.markdown(f"**{t('from')}:** {user_input['origin']}")
933
+ st.markdown(f"**{t('when')}:** {user_input['travel_dates']} ({user_input['duration']} days)")
934
+ st.markdown(f"**{t('budget')}:** {user_input['budget'].title()}")
935
+ st.markdown(f"**{t('travel_style')}:** {user_input['travel_style']}")
936
  if user_input['preferences']:
937
  st.markdown(f"**Interests:** {user_input['preferences']}")
938
  if user_input['special_requirements']:
939
  st.markdown(f"**Special Requirements:** {user_input['special_requirements']}")
940
 
941
  with progress_tab:
942
+ # Create a persistent placeholder for progress display to avoid duplication
943
  if 'progress_placeholder' not in st.session_state:
944
  st.session_state.progress_placeholder = st.empty()
945
  with st.session_state.progress_placeholder.container():
 
954
  output_container = st.container()
955
  with output_container:
956
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
957
+ st.markdown("### 🌟 " + t("live_agent_outputs"))
958
  st.info("Our AI agents will show their work here as they create your itinerary")
959
  st.markdown('</div>', unsafe_allow_html=True)
960
 
 
1184
  st.markdown('<div class="modern-card">', unsafe_allow_html=True)
1185
 
1186
  # Modern tabs for different views
1187
+ itinerary_tab, details_tab, download_tab = st.tabs([f"🗒️ {t('full_itinerary')}", f"💼 {t('details')}", f"💾 {t('download_share')}"])
1188
 
1189
  with itinerary_tab:
1190
  # Preview the itinerary as text
 
1217
  st.markdown("### 🍽️ Dining Recommendations")
1218
  st.markdown(st.session_state.results["dining_info"])
1219
 
 
 
1220
  with download_tab:
1221
  col1, col2 = st.columns([2, 1])
1222
 
1223
  with col1:
1224
+ st.markdown("### " + t("save_itinerary"))
1225
  st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
1226
 
1227
  # Display stylized download button
 
1240
  st.markdown("</div>", unsafe_allow_html=True)
1241
 
1242
  # Share options
1243
+ st.markdown("### " + t("share_itinerary"))
1244
  st.markdown("*Coming soon: Email your itinerary or share via social media.*")
1245
 
1246
  with col2:
1247
  # QR code placeholder for future implementation
1248
+ st.markdown("### " + t("save_for_mobile"))
1249
  st.markdown("*Coming soon: QR code for easy access on your phone*")
1250
 
1251
  st.markdown('</div>', unsafe_allow_html=True)
1252
 
1253
  # Add a reset button to create a new itinerary
1254
+ if st.button(t("plan_another_trip"), key="reset_button"):
1255
  # Reset the session state
1256
  st.session_state.generated_itinerary = None
1257
  st.session_state.generation_complete = False
 
1261
  st.experimental_rerun()
1262
 
1263
  # Footer for the app
1264
+ st.markdown(f"""
1265
  <div style="margin-top: 50px; text-align: center; padding: 20px; color: #6c757d; font-size: 0.8rem;">
1266
+ <p>{t("built_with")}</p>
1267
  </div>
1268
  """, unsafe_allow_html=True)
1269
 
 
1299
  <p>Built with ❤️ for You</p>
1300
  </div>
1301
  </div>
1302
+ """, unsafe_allow_html=True)