File size: 45,462 Bytes
2ab46de
43bebf2
f7b52b8
43bebf2
 
 
f7b52b8
43bebf2
 
 
 
 
 
 
 
76840ea
43bebf2
76840ea
43bebf2
76840ea
 
43bebf2
 
 
 
 
f7b52b8
 
 
 
 
 
 
 
43bebf2
 
c10802e
54de1a2
f7b52b8
43bebf2
c10802e
76840ea
c10802e
f7b52b8
c10802e
f7b52b8
 
c10802e
54de1a2
43bebf2
 
c10802e
f7b52b8
c10802e
 
f7b52b8
76840ea
 
 
43bebf2
 
 
 
 
 
 
76840ea
 
 
 
 
 
43bebf2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76840ea
 
 
 
 
43bebf2
 
 
 
 
 
 
 
 
76840ea
 
 
 
 
 
 
 
 
 
43bebf2
 
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
 
76840ea
43bebf2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
76840ea
 
 
 
 
 
 
 
 
 
 
 
 
43bebf2
76840ea
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
import streamlit as st
import json
import os
import pandas as pd
from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, Boolean, Enum, func
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy.exc import IntegrityError
import hashlib
import uuid
import bcrypt
import requests
import random
import enum

# Removed: AI-specific imports to temporarily disable AI features for full app functionality
# from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
# Removed: import torch

# Removed: AI Model Setup and caching
# Removed: tokenizer_ai, model_ai = load_summarizer_components()


class GameType(enum.Enum):
    IDIOM_GUESSER = "IdiomGuesser"
    STORY_STARTER = "StoryStarter"

# --- Configuration ---
if os.environ.get("DATABASE_URL"):
    DATABASE_URL = os.environ.get("DATABASE_URL")
else:
    DATABASE_URL = "sqlite:///fillmyblank.db"

# --- Database Setup (SQLAlchemy) ---
Base = declarative_base()

@st.cache_resource
def get_engine(_db_url):
    try:
        engine = create_engine(_db_url)
        with engine.connect() as connection:
            pass
        return engine
    except Exception as e:
        st.error(f"FATAL ERROR: Could not connect to database on startup: {e}")
        return None

@st.cache_resource
def get_session_local(_engine):
    if _engine:
        return sessionmaker(autocommit=False, autoflush=False, bind=_engine)
    return None

Engine = get_engine(DATABASE_URL)
SessionLocal = get_session_local(Engine)


# --- Database Models ---

class User(Base):
    __tablename__ = "users"
    id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    username = Column(String, unique=True, nullable=False)
    hashed_password = Column(String, nullable=False)
    created_at = Column(DateTime, default=datetime.now)

    def set_password(self, password):
        self.hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

    def check_password(self, password):
        return bcrypt.checkpw(password.encode('utf-8'), self.hashed_password.encode('utf-8'))

class LoreEntry(Base):
    __tablename__ = "lore_entries"
    id = Column(Integer, primary_key=True, index=True)
    text = Column(Text, nullable=False)
    language = Column(String, nullable=False)
    type = Column(String, nullable=False)
    nickname = Column(String, default="Anonymous")
    user_id = Column(String, nullable=True)
    timestamp = Column(DateTime, default=datetime.now)
    city = Column(String, nullable=True)
    state = Column(String, nullable=True)
    country = Column(String, nullable=True)
    ip_address = Column(String, nullable=True)

class GameResponse(Base):
    __tablename__ = "game_responses"
    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(String, nullable=False)
    game_type = Column(Enum(GameType), nullable=False)
    question_text = Column(Text, nullable=False) # E.g., idiom / story starter
    user_response = Column(Text, nullable=False) # E.g., user's situation / story continuation
    is_correct = Column(Boolean, nullable=True) # For guess-based games (will be None for story/situation games)
    score = Column(Integer, default=0) # Points awarded
    user_explanation = Column(Text, nullable=True) # Used for idiom definition or situations now
    language = Column(String, nullable=False)
    timestamp = Column(DateTime, default=datetime.now)

# Create tables if they don't exist
Base.metadata.create_all(bind=Engine)

# --- Session State Initialization ---
if 'user_id' not in st.session_state: st.session_state.user_id = None
if 'username' not in st.session_state: st.session_state.username = None

if 'register_username_input_value' not in st.session_state: st.session_state.register_username_input_value = ""
if 'register_password_input_value' not in st.session_state: st.session_state.register_password_input_value = ""

# Game specific session state
if 'current_idiom' not in st.session_state: st.session_state.current_idiom = None
if 'game_score' not in st.session_state: st.session_state.game_score = 0
if 'idiom_game_state' not in st.session_state: st.session_state.idiom_game_state = "initial"
if 'current_story_starter' not in st.session_state: st.session_state.current_story_starter = None
if 'story_game_state' not in st.session_state: st.session_state.story_game_state = "initial"
if 'user_app_language' not in st.session_state: st.session_state.user_app_language = "English"

# Lore Contribution Form Session State
if "lore_text_input_value" not in st.session_state: st.session_state.lore_text_input_value = ""
if "language_select_value" not in st.session_state: st.session_state.language_select_value = "Select Language"
if "region_select_value" not in st.session_state: st.session_state.region_select_value = "Select State"
if "lore_type_select_value" not in st.session_state: st.session_state.lore_type_select_value = "Select Type"
if "nickname_input_value" not in st.session_state: st.session_state.nickname_input_value = ""
if "agree_to_location_checkbox_value" not in st.session_state: st.session_state.agree_to_location_checkbox_value = False

# Idiom Game Specific Widget Keys
if 'idiom_guess_input' not in st.session_state: st.session_state.idiom_guess_input = ""
if 'idiom_situations_input' not in st.session_state: st.session_state.idiom_situations_input = ""
if 'idiom_hint_shown' not in st.session_state: st.session_state.idiom_hint_shown = False
if 'idiom_explanation_input' not in st.session_state: st.session_state.idiom_explanation_input = ""
if 'explanation_language_select' not in st.session_state: st.session_state.explanation_language_select = "English"

# Story Game Specific Widget Keys
if 'story_continuation_input' not in st.session_state: st.session_state.story_continuation_input = ""


# --- Helper Functions ---

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

def create_user(username, password):
    db = next(get_db())
    existing_user = db.query(User).filter(User.username == username).first()
    if existing_user:
        return None
    new_user = User(username=username)
    new_user.set_password(password)
    db.add(new_user)
    try:
        db.commit()
        db.refresh(new_user)
        return new_user
    except IntegrityError:
        db.rollback()
        return None
    except Exception as e:
        db.rollback()
        st.error(f"An error occurred during registration: {e}")
        return None


def authenticate_user(username, password):
    db = next(get_db())
    user = db.query(User).filter(User.username == username).first()
    
    if not user:
        return None
    
    if user.check_password(password):
        return user
    else:
        return None

def save_lore_data_to_db(entry_data):
    db = next(get_db())
    new_lore = LoreEntry(**entry_data)
    db.add(new_lore)
    db.commit()
    db.refresh(new_lore)
    return new_lore

def load_lore_data_from_db(limit=10):
    db = next(get_db())
    return db.query(LoreEntry).order_by(LoreEntry.timestamp.desc()).limit(limit).all()

def load_user_lore_from_db(user_id, limit=10):
    db = next(get_db())
    return db.query(LoreEntry).filter(LoreEntry.user_id == user_id).order_by(LoreEntry.timestamp.desc()).limit(limit).all()

def save_game_response_to_db(response_data):
    db = next(get_db())
    new_response = GameResponse(**response_data)
    db.add(new_response)
    db.commit()
    db.refresh(new_response)
    return new_response

def load_leaderboard_data(limit=10):
    db = next(get_db())
    leaderboard = db.query(
        User.username,
        func.sum(GameResponse.score).label('total_score')
    ).join(GameResponse, User.id == GameResponse.user_id) \
     .group_by(User.username).order_by(func.sum(GameResponse.score).desc()).limit(limit).all()
    
    return leaderboard


# --- Language Options ---
APP_LANGUAGES = ["English", "Hindi", "Telugu", "Marathi", "Tamil", "Kannada", "Malayalam", "Bengali", "Gujarati", "Punjabi", "Odia", "Assamese", "Urdu"]

# --- MULTILINGUAL IDIOM DATA (AI HINT GENERATION DISABLED) ---
IDIOMS_DATA = {
    "Telugu": [
        {"idiom": "కళ్లు కాయలు కాసేలా చూడటం", "clue": "చాలా కాలం వేచి ఉండటం, కళ్ళు కాయలు కాసేంత వరకు.", "meaning_for_ai": "చాలా కాలం వేచి ఉండటం, కళ్ళు కాయలు కాసేంత వరకు చూడటం, అనగా ఒక విషయం కోసం చాలా ఆసక్తిగా ఎదురుచూడటం."},
        {"idiom": "గోరు చుట్టుపై రోకలి పోటు", "clue": "ఇప్పటికే ఉన్న సమస్యను మరింత దిగజార్చడం, పరిస్థితిని మరింత దారుణంగా మార్చడం.", "meaning_for_ai": "ఇప్పటికే ఉన్న సమస్యను మరింత దిగజార్చడం, పరిస్థితిని మరింత దారుణంగా మార్చడం, ఒక చిన్న కష్టానికి పెద్ద ఆపదను జోడించడం."},
        {"idiom": "మానవుడు తానొకటి తలిస్తే దైవం వేరొకటి తలచును", "clue": "మనిషి ఒకటి అనుకుంటే దేవుడు ఇంకొకటి తలస్తాడు.", "meaning_for_ai": "మనిషి ఒకటి అనుకుంటే దేవుడు ఇంకొకటి తలస్తాడు. మనం ప్రణాళిక వేసుకున్నవి ఎల్లప్పుడూ జరగవు, దైవ సంకల్పం వేరుగా ఉండవచ్చు."},
        {"idiom": "నక్కకు నాగలోకం చూపించడం", "clue": "ఎవరికైనా అసాధ్యమైనదాన్ని లేదా వారి స్థాయికి మించినదాన్ని చూపించడం; అవాస్తవంగా గొప్పలు చెప్పుకోవడం.", "meaning_for_ai": "ఎవరికైనా అసాధ్యమైనదాన్ని లేదా వారి స్థాయికి మించినదాన్ని చూపించడం; అవాస్తవంగా గొప్పలు చెప్పుకోవడం. ఒక చిన్న జంతువుకు పెద్ద లోకాన్ని చూపించడం వంటిది."},
        {"idiom": "అంట్లు కడిగినా సుఖం లేదు", "clue": "కష్టపడి పని చేసినా ఫలితం లేకపోవడం, కృతజ్ఞత లేని పని.", "meaning_for_ai": "కష్టపడి పని చేసినా ఫలితం లేకపోవడం, కృతజ్ఞత లేని పని. ఎంత కష్టపడినా సంతోషం లేదా గుర్తింపు లేకపోవడం."},
    ],
    "Hindi": [
        {"idiom": "हाथी के दांत खाने के और, दिखाने के और", "clue": "जो दिखता है, वह होता नहीं.", "meaning_for_ai": "जो चीज़ दिखती है, वह असलियत में नहीं होती; कथनी और करनी में अंतर होना, पाखंड करना."},
        {"idiom": "ऊंट के मुंह में जीरा", "clue": "ज़रूरत से बहुत कम वस्तु का मिलना.", "meaning_for_ai": "बहुत बड़ी ज़रूरत के लिए बहुत कम वस्तु का मिलना, जिसका कोई खास असर न पड़े."},
        {"idiom": "आसमान से गिरा खजूर पर अटका", "clue": "एक मुश्किल से निकलकर दूसरी मुश्किल में फंस जाना.", "meaning_for_ai": "एक समस्या से बचने के बाद तुरंत दूसरी नई समस्या में फंस जाना."},
        {"idiom": "नाच न जाने आंगन टेढ़ा", "clue": "अपनी अयोग्यता को छिपाने के लिए दूसरों में दोष निकालना.", "meaning_for_ai": "अपनी कमी या अक्षमता को स्वीकार न करके, दूसरों या परिस्थितियों को दोष देना."},
        {"idiom": "जल में रहकर मगर से बैर", "clue": "जिसके अधीन रहना हो, उसी से दुश्मनी करना.", "meaning_for_ai": "जिसके आश्रय में या जिसके साथ रहना हो, उसी से दुश्मनी मोल लेना, जो घातक हो सकता है।"},
    ],
    "English": [
        {"idiom": "Break a leg", "clue": "To wish someone good luck.", "meaning_for_ai": "An idiomatic expression used in theater and other performing arts to wish a performer good luck."},
        {"idiom": "Bite the bullet", "clue": "To endure a difficult situation.", "meaning_for_ai": "To face a difficult and unpleasant situation with courage and fortitude, rather than avoiding it."},
        {"idiom": "Cost an arm and a leg", "clue": "To be very expensive.", "meaning_for_ai": "To be extremely expensive, costing a large amount of money."},
        {"idiom": "Hit the road", "clue": "To leave a place.", "meaning_for_ai": "To begin a journey or to depart from a particular location."},
        {"idiom": "The ball is in your court", "clue": "It's up to you to make the next decision or step.", "meaning_for_ai": "It's your turn to act."},
    ]
}

# NEW: MULTILINGUAL STORY STARTERS DATA
STORY_STARTERS_DATA = {
    "Telugu": [
        {"starter": "పురాతన పల్లెటూరిలో, ఒక వృద్ధురాలు అరణ్యంలో ఒక వింత కాంతిని చూసింది...", "meaning_for_ai": "In an ancient village, an old woman saw a strange light in the forest..."},
        {"starter": "ఆ పర్వతాల మధ్య, ఒకప్పుడు అదృశ్యమైన గుడి ఉంది, దానికి దాని స్వంత రహస్యం ఉంది.", "meaning_for_ai": "Amidst those mountains, there was once a forgotten temple, holding its own secret."},
        {"starter": "రాత్రిపూట, నగర వీధులు నిశ్శబ్దంగా ఉన్నప్పుడు, ఒక పాత రేడియో అకస్మాత్తుగా ప్లే అవ్వడం ప్రారంభించింది...", "meaning_for_ai": "In the dead of night, when city streets were silent, an old radio suddenly began to play..."},
        {"starter": "నేను మొదటిసారి రైలు ఎక్కినప్పుడు, నా పక్కన కూర్చున్న వ్యక్తి ఒక విచిత్రమైన సూట్కేస్ కలిగి ఉన్నాడు.", "meaning_for_ai": "When I first boarded the train, the person sitting next to me had a strange suitcase."},
        {"starter": "పాత మామిడి చెట్టు క్రింద, తరాల నాటి కథలు నిద్రిస్తున్నాయి. ఈ రోజు, వాటిలో ఒకటి మేల్కొంది.", "meaning_for_ai": "Under the old mango tree, stories of generations lie dormant. Today, one of them awoke."},
    ],
    "Hindi": [
        {"starter": "पुराने गाँव में, एक बूढ़ी औरत ने जंगल में एक अजीब रोशनी देखी...", "meaning_for_ai": "In an ancient village, an old woman saw a strange light in the forest..."},
        {"starter": "उन पहाड़ों के बीच, एक समय एक भूला हुआ मंदिर था, जिसका अपना रहस्य था।", "meaning_for_ai": "Amidst those mountains, there was once a forgotten temple, holding its own secret."},
        {"starter": "रात के सन्नाटे में, जब शहर की सड़कें खामोश थीं, एक पुराना रेडियो अचानक बजने लगा...", "meaning_for_ai": "In the dead of night, when city streets were silent, an old radio suddenly began to play..."},
        {"starter": "जब मैं पहली बार ट्रेन में चढ़ा, तो मेरे बगल में बैठे व्यक्ति के पास एक अजीब सूटकेस था।", "meaning_for_ai": "When I first boarded the train, the person sitting next to me had a strange suitcase."},
        {"starter": "पुराने आम के पेड़ के नीचे, पीढ़ियों की कहानियाँ सोई हुई हैं। आज, उनमें से एक जाग उठी।", "meaning_for_ai": "Under the old mango tree, stories of generations lie dormant. Today, one of them awoke."},
    ],
    "English": [
        {"starter": "The old woman found a peculiar, glowing stone at the bottom of the ancient well...", "meaning_for_ai": "A fantasy/mystery starter."},
        {"starter": "It was the day the monsoons arrived early, bringing with them a secret that had been buried for years.", "meaning_for_ai": "A mystery/drama starter."},
        {"starter": "I never believed in magic until the stray dog I rescued started whispering forgotten lullabies.", "meaning_for_ai": "A whimsical/fantasy starter."},
        {"starter": "The aroma of spices filled the narrow alleyway, leading me to a door that wasn't there yesterday.", "meaning_for_ai": "A mystery/adventure starter."},
        {"starter": "The last letter from my grandmother contained not words, but a single, dried marigold petal.", "meaning_for_ai": "A poignant/mystery starter."},
    ]
}

def get_random_story_starter(lang):
    if lang in STORY_STARTERS_DATA and STORY_STARTERS_DATA[lang]:
        return random.choice(STORY_STARTERS_DATA[lang])
    return None

# Removed AI clue generation function, as AI is temporarily disabled
# Replaced with a simple function that returns the hardcoded clue
def get_idiom_clue_simple(idiom_data):
    return idiom_data["clue"] # Use the hardcoded 'clue' field


def get_random_idiom_for_guesser(lang):
    if lang in IDIOMS_DATA and IDIOMS_DATA[lang]:
        chosen_idiom_data = random.choice(IDIOMS_DATA[lang])
        chosen_idiom_data["generated_hint"] = get_idiom_clue_simple(chosen_idiom_data) # Use simple clue
        return chosen_idiom_data
    return None

def get_location_from_ip():
    """Fetches approximate location based on IP address."""
    try:
        response = requests.get("http://ip-api.com/json")
        response.raise_for_status()
        data = response.json()
        if data.get("status") == "success":
            return {
                "city": data.get("city"),
                "state": data.get("regionName"),
                "country": data.get("country"),
                "ip_address": data.get("query")
            }
        else:
            st.warning(f"IP lookup failed: {data.get('message', 'Unknown error')}")
            return None
    except requests.exceptions.RequestException as e:
        st.warning(f"Could not retrieve location from IP: {e}. Please try again later.")
        return None

# --- UI Strings Dictionary ---
UI_STRINGS = {
    "English": {
        "user_account_title": "User Account",
        "logged_in_as": "Logged in as",
        "logout_button": "Logout",
        "login_register_subheader": "Login / Register",
        "login_tab": "Login",
        "register_tab": "Register",
        "username_label": "Username",
        "password_label": "Password",
        "login_button": "Login",
        "invalid_credentials_error": "Invalid username or password.",
        "new_username_label": "New Username",
        "new_password_label": "New Password",
        "register_button": "Register",
        "empty_credentials_error": "Username and password cannot be empty.",
        "user_registered_success": "User ",
        "please_login_msg": " registered successfully! Please login.",
        "username_exists_error": "Username already exists. Please choose a different one.",
        "registration_error": "An error occurred during registration",
        "choose_language_label": "Choose your language for the app experience:",
        "intro_text": "Hey gang! Help us build an AI that understands India's incredible linguistic and cultural vibes. Your contributions will help us train AI models to get the nuances of Indian languages!",
        "contribute_lore_tab": "Contribute Lore",
        "play_game_tab": "Play a Game",
        "leaderboard_tab": "Leaderboard",
        "lore_contribute_subheader": "Contribute Your Lore:",
        "lore_text_label": "Your Lore/Proverb:",
        "lore_text_placeholder": "E.g., 'The quick brown fox jumps over the lazy dog.' or 'Good morning, how are you?'",
        "language_label": "Language:",
        "state_ut_label": "State/Union Territory:",
        "type_of_lore_label": "Type of Lore:",
        "nickname_label": "Your Nickname (Optional, defaults to your username if logged in):",
        "location_optional_text": "**Optional: Add Location Data**",
        "agree_to_location_text": "Allow app to automatically detect my approximate location (via IP address)?",
        "location_info_text": "Your location will be approximated from the server's IP address where the app is running. This is usually city/state level, not precise GPS. **This feature relies on an external API (ip-api.com) and may have usage limits or occasional failures.**",
        "submit_lore_button": "Submit Lore!",
        "empty_lore_error": "🚨 Lore/Proverb field cannot be empty. Spill the tea!",
        "select_language_error": "🚨 Please select a Language.",
        "select_state_error": "🚨 Please select a State/Union Territory.",
        "select_type_error": "🚨 Please select a Type of Lore.",
        "lore_submitted_success": "✅ Lore submitted successfully to the database! Thanks for contributing, legend!",
        "recent_contributions_subheader": "Your Recent Contributions:",
        "no_user_contributions": "You haven't contributed any lore yet! Drop some knowledge above. 🚀",
        "recent_all_lore_subheader": "Recently Collected Lore (from Database):",
        "no_lore_collected": "No lore collected yet! Be the first to drop some knowledge. 🚀",
        "built_with_love": "💖 Built with ❤️ for FillMyBlank.ai",
        "game_play_subheader": "Choose a Game!",
        "idiom_guesser_game_tab": "Idiom Guesser",
        "story_completion_game_tab": "Story Completion",
        "idiom_game_current_score": "Your Idiom Score:",
        "start_new_idiom_game_button": "Start New Idiom Game",
        "idiom_text_label": "**Idiom:**",
        "get_hint_button": "Get a Hint",
        "ai_hint_text": "**Hint:**", # Changed from AI Hint
        "your_situations_label": "Write a few situations where this idiom would fit:",
        "submit_situations_button": "Submit Situations",
        "situations_empty_error": "🚨 Please write some situations for the idiom. Get creative!",
        "idiom_submitted_success": "✅ Situations submitted! Thanks for your valuable contribution!",
        "no_idioms_for_lang": "No idioms available for the selected language. Please select another language or contribute more idioms!",
        "lore_msg_text": "**💬 Lore:**",
        "lang_msg_text": "**🌐 Lang:**",
        "location_msg_text": "**📍 Location:**",
        "type_msg_text": "**🏷️ Type:**",
        "on_msg_text": "**⏰ On:**",
        "by_msg_text": "**👤 By:**",
        "contributor_you": "(You)",
        "contributor_logged_in": "(Logged-in User)",
        "dialog_placeholder": "Dialogue, quote, or local saying",
        "logged_out_success": "Logged out successfully!",
        "welcome_back": "Welcome back",
        "could_not_detect_location_warning": "Could not automatically detect location. Proceeding without location data.",
        "leaderboard_subheader": "Top Idiom Guessers!",
        "leaderboard_username_col": "Username",
        "leaderboard_score_col": "Total Score",
        "no_scores_yet": "No scores recorded yet! Be the first to play and get on the leaderboard. 🚀",
        "story_play_subheader": "Play: Story Completion!",
        "story_starter_text": "**Story Starter:**",
        "your_story_continuation_label": "Your Story Continuation:",
        "submit_story_button": "Submit Story",
        "story_submitted_success": "✅ Story submitted! Thanks for your creative contribution!",
        "no_starters_for_lang": "No story starters available for the selected language. Please select another language or contribute more stories!",
        "story_empty_error": "🚨 Your story continuation cannot be empty. Get creative!"
    },
    "Telugu": {
        "user_account_title": "వినియోగదారు ఖాతా",
        "logged_in_as": "లాగిన్ అయ్యారు",
        "logout_button": "లాగ్ అవుట్",
        "login_register_subheader": "లాగిన్ / నమోదు",
        "login_tab": "లాగిన్",
        "register_tab": "నమోదు",
        "username_label": "వినియోగదారు పేరు",
        "password_label": "పాస్‌వర్డ్",
        "login_button": "లాగిన్",
        "invalid_credentials_error": "చెల్లని వినియోగదారు పేరు లేదా పాస్‌వర్డ్.",
        "new_username_label": "కొత్త వినియోగదారు పేరు",
        "new_password_label": "కొత్త పాస్‌వర్డ్",
        "register_button": "నమోదు",
        "empty_credentials_error": "వినియోగదారు పేరు మరియు పాస్‌వర్డ్ ఖాళీగా ఉండకూడదు.",
        "user_registered_success": "వినియోగదారు ",
        "please_login_msg": " విజయవంతంగా నమోదు చేయబడింది! దయచేసి లాగిన్ చేయండి.",
        "username_exists_error": "వినియోగదారు పేరు ఇప్పటికే ఉంది. దయచేసి మరొకటి ఎంచుకోండి.",
        "registration_error": "నమోదు సమయంలో లోపం సంభవించింది",
        "choose_language_label": "యాప్ అనుభవం కోసం మీ భాషను ఎంచుకోండి:",
        "intro_text": "భారతదేశం యొక్క అద్భుతమైన భాషా మరియు సాంస్కృతిక వైవిధ్యాన్ని అర్థం చేసుకునే AIని రూపొందించడంలో మాకు సహాయం చేయండి. మీ సహకారం భారతీయ భాషల సూక్ష్మ నైపుణ్యాలను అర్థం చేసుకోవడానికి AI నమూనాలకు సహాయపడుతుంది!",
        "contribute_lore_tab": "మీ కథనాన్ని అందించండి",
        "play_game_tab": "ఆట ఆడండి",
        "leaderboard_tab": "లీడర్‌బోర్డ్",
        "lore_contribute_subheader": "మీ కథనాన్ని అందించండి:",
        "lore_text_label": "మీ కథనం/సామెత:",
        "lore_text_placeholder": "ఉదా: 'అతి సర్వత్ర వర్జయేత్.' (ఎక్కువగా ఏదైనా చెడ్డది.)",
        "language_label": "భాష:",
        "state_ut_label": "రాష్ట్రం/కేంద్ర పాలిత ప్రాంతం:",
        "type_of_lore_label": "కథనం రకం:",
        "nickname_label": "మీ మారుపేరు (ఐచ్ఛికం, లాగిన్ అయితే మీ వినియోగదారు పేరుకి డిఫాల్ట్ అవుతుంది):",
        "location_optional_text": "**ఐచ్ఛికం: స్థాన డేటాను జోడించండి**",
        "agree_to_location_text": "అప్లికేషన్ నా సుమారు స్థానాన్ని స్వయంచాలకంగా గుర్తించడానికి అనుమతించాలా (IP చిరునామా ద్వారా)?",
        "location_info_text": "మీ స్థానం అప్లికేషన్ నడుస్తున్న సర్వర్ IP చిరునామా నుండి అంచనా వేయబడుతుంది. ఇది సాధారణంగా నగరం/రాష్ట్ర స్థాయి, ఖచ్చితమైన GPS కాదు. **ఈ ఫీచర్ బాహ్య API (ip-api.com)పై ఆధారపడి ఉంటుంది మరియు వినియోగ పరిమితులు లేదా అప్పుడప్పుడు వైఫల్యాలు ఉండవచ్చు.**",
        "submit_lore_button": "కథనాన్ని సమర్పించండి!",
        "empty_lore_error": "🚨 కథనం/సామెత ఖాళీగా ఉండకూడదు.",
        "select_language_error": "🚨 దయచేసి ఒక భాషను ఎంచుకోండి.",
        "select_state_error": "🚨 దయచేసి ఒక రాష్ట్రాన్ని/కేంద్ర పాలిత ప్రాంతాన్ని ఎంచుకోండి.",
        "select_type_error": "🚨 దయచేసి ఒక రకాన్ని ఎంచుకోండి.",
        "lore_submitted_success": "✅ కథనం డేటాబేస్‌లో విజయవంతంగా సమర్పించబడింది! సహకరించినందుకు ధన్యవాదాలు, లెజెండ్!",
        "recent_contributions_subheader": "మీ ఇటీవలి సహకారాలు:",
        "no_user_contributions": "మీరు ఇంకా ఎటువంటి కథనాన్ని అందించలేదు!",
        "recent_all_lore_subheader": "ఇటీవలి సేకరించిన కథనం (డేటాబేస్ నుండి):",
        "no_lore_collected": "ఇంకా కథనం సేకరించబడలేదు!",
        "built_with_love": "💖 FillMyBlank.ai కోసం ప్రేమతో రూపొందించబడింది",
        "game_play_subheader": "ఆటను ఎంచుకోండి!",
        "idiom_guesser_game_tab": "ఇడియమ్ గెసర్",
        "story_completion_game_tab": "కథనం పూర్తి",
        "idiom_game_current_score": "మీ ఇడియమ్ స్కోర్:",
        "start_new_idiom_game_button": "కొత్త ఇడియమ్ ఆట ప్రారంభించండి",
        "idiom_text_label": "**జాతీయం:**",
        "get_hint_button": "సూచన పొందండి",
        "ai_hint_text": "**సూచన:**",
        "your_situations_label": "ఈ జాతీయం సరిపోయే కొన్ని సందర్భాలను వ్రాయండి:",
        "submit_situations_button": "సందర్భాలను సమర్పించండి",
        "situations_empty_error": "🚨 దయచేసి జాతీయం కోసం కొన్ని సందర్భాలను వ్రాయండి. సృజనాత్మకంగా ఉండండి!",
        "idiom_submitted_success": "✅ సందర్భాలు సమర్పించబడ్డాయి! మీ విలువైన సహకారానికి ధన్యవాదాలు!",
        "no_idioms_for_lang": "ఎంచుకున్న భాషకు జాతీయాలు అందుబాటులో లేవు. దయచేసి మరొక భాషను ఎంచుకోండి లేదా మరిన్ని జాతీయాలను అందించండి!",
        "lore_msg_text": "**💬 కథనం:**",
        "lang_msg_text": "**🌐 భాష:**",
        "location_msg_text": "**📍 స్థానం:**",
        "type_msg_text": "**🏷️ రకం:**",
        "on_msg_text": "**⏰ సమయం:**",
        "by_msg_text": "**👤 ద్వారా:**",
        "contributor_you": "(మీరు)",
        "contributor_logged_in": "(లాగిన్ అయిన వినియోగదారు)",
        "dialog_placeholder": "సంభాషణ, కోట్ లేదా స్థానిక సామెత",
        "logged_out_success": "విజయవంతంగా లాగ్ అవుట్ అయ్యారు!",
        "welcome_back": "తిరిగి స్వాగతం",
        "could_not_detect_location_warning": "స్థానాన్ని స్వయంచాలకంగా గుర్తించలేకపోయింది. స్థాన డేటా లేకుండా కొనసాగుతోంది.",
        "leaderboard_subheader": "టాప్ ఇడియమ్ గెసర్లు!",
        "leaderboard_username_col": "వినియోగదారు పేరు",
        "leaderboard_score_col": "మొత్తం స్కోర్",
        "no_scores_yet": "ఇంకా స్కోర్‌లు నమోదు కాలేదు! లీడర్‌బోర్డ్‌లో చేరడానికి మొదట ఆట ఆడండి. 🚀",
        "story_play_subheader": "ఆడండి: కథనం పూర్తి!",
        "story_starter_text": "**కథనం ప్రారంభం:**",
        "your_story_continuation_label": "మీ కథనం కొనసాగింపు:",
        "submit_story_button": "కథనాన్ని సమర్పించండి",
        "story_submitted_success": "✅ కథనం సమర్పించబడింది! మీ సృజనాత్మక సహకారానికి ధన్యవాదాలు!",
        "no_starters_for_lang": "ఎంచుకున్న భాషకు కథనం ప్రారంభాలు అందుబాటులో లేవు. దయచేసి మరొక భాషను ఎంచుకోండి లేదా మరిన్ని కథనాలను అందించండి!",
        "story_empty_error": "🚨 మీ కథనం కొనసాగింపు ఖాళీగా ఉండకూడదు. సృజనాత్మకంగా ఉండండి!"
    },
    "Hindi": {
        "user_account_title": "उपयोगकर्ता खाता",
        "logged_in_as": "के रूप में लॉग इन किया गया",
        "logout_button": "लॉग आउट",
        "login_register_subheader": "लॉगिन / रजिस्टर",
        "login_tab": "लॉगिन",
        "register_tab": "रजिस्टर",
        "username_label": "उपयोगकर्ता नाम",
        "password_label": "पासवर्ड",
        "login_button": "लॉगिन",
        "invalid_credentials_error": "अमान्य उपयोगकर्ता नाम या पासवर्ड।",
        "new_username_label": "नया उपयोगकर्ता नाम",
        "new_password_label": "नया पासवर्ड",
        "register_button": "रजिस्टर",
        "empty_credentials_error": "उपयोगकर्ता नाम और पासवर्ड खाली नहीं हो सकते।",
        "user_registered_success": "उपयोगकर्ता ",
        "please_login_msg": " सफलतापूर्वक पंजीकृत! कृपया लॉगिन करें।",
        "username_exists_error": "उपयोगकर्ता नाम पहले से मौजूद है। कृपया कोई दूसरा चुनें।",
        "registration_error": "पंजीकरण के दौरान एक त्रुटि हुई",
        "choose_language_label": "ऐप अनुभव के लिए अपनी भाषा चुनें:",
        "intro_text": "नमस्ते गैंग! भारत की अविश्वसनीय भाषाई और सांस्कृतिक विविधता को समझने वाले एक AI के निर्माण में हमारी मदद करें। आपका योगदान AI मॉडल को भारतीय भाषाओं की बारीकियों को समझने में मदद करेगा!",
        "contribute_lore_tab": "ज्ञान योगदान करें",
        "play_game_tab": "खेल खेलें",
        "leaderboard_tab": "लीडरबोर्ड",
        "lore_contribute_subheader": "अपना ज्ञान योगदान करें:",
        "lore_text_label": "आपका ज्ञान/मुहावरा:",
        "lore_text_placeholder": "उदाहरण: 'हाथी के दांत खाने के और, दिखाने के और'",
        "language_label": "भाषा:",
        "state_ut_label": "राज्य/केंद्र शासित प्रदेश:",
        "type_of_lore_label": "ज्ञान का प्रकार:",
        "nickname_label": "आपका उपनाम (वैकल्पिक, लॉगिन होने पर आपके उपयोगकर्ता नाम पर डिफ़ॉल्ट होगा):",
        "location_optional_text": "**वैकल्पिक: स्थान डेटा जोड़ें**",
        "agree_to_location_text": "क्या ऐप को मेरी अनुमानित स्थिति (IP पते के माध्यम से) स्वचालित रूप से पता लगाने की अनुमति दें?",
        "location_info_text": "आपकी स्थिति का अनुमान उस सर्वर के IP पते से लगाया जाएगा जहां ऐप चल रहा है। यह आमतौर पर शहर/राज्य स्तर का होता है, सटीक GPS नहीं। **यह सुविधा बाहरी API (ip-api.com) पर निर्भर करती है और इसमें उपयोग सीमाएं या कभी-कभी विफलताएं हो सकती हैं।**",
        "submit_lore_button": "ज्ञान सबमिट करें!",
        "empty_lore_error": "🚨 ज्ञान/मुहावरा खाली नहीं हो सकता।",
        "select_language_error": "🚨 कृपया एक भाषा चुनें।",
        "select_state_error": "🚨 कृपया एक राज्य/केंद्र शासित प्रदेश चुनें।",
        "select_type_error": "🚨 कृपया एक प्रकार चुनें।",
        "lore_submitted_success": "✅ ज्ञान डेटाबेस में सफलतापूर्वक सबमिट किया गया! योगदान के लिए धन्यवाद, लीजेंड!",
        "recent_contributions_subheader": "आपके हालिया योगदान:",
        "no_user_contributions": "आपने अभी तक कोई ज्ञान योगदान नहीं किया है!",
        "recent_all_lore_subheader": "हाल ही में एकत्र किया गया ज्ञान (डेटाबेस से):",
        "no_lore_collected": "अभी तक कोई ज्ञान एकत्र नहीं किया गया है!",
        "built_with_love": "💖 FillMyBlank.ai के लिए प्यार से बनाया गया",
        "game_play_subheader": "एक खेल चुनें!",
        "idiom_guesser_game_tab": "मुहावरा पहचानें",
        "story_completion_game_tab": "कहानी पूरी करें",
        "idiom_game_current_score": "आपका मुहावरा स्कोर:",
        "start_new_idiom_game_button": "नया मुहावरा खेल शुरू करें",
        "idiom_text_label": "**मुहावरा:**",
        "get_hint_button": "एक संकेत प्राप्त करें",
        "ai_hint_text": "**संकेत:**",
        "your_situations_label": "कुछ ऐसी स्थितियाँ लिखें जहाँ यह मुहावरा उपयुक्त हो:",
        "submit_situations_button": "स्थितियाँ सबमिट करें",
        "situations_empty_error": "🚨 कृपया मुहावरे के लिए कुछ स्थितियाँ लिखें। रचनात्मक बनें!",
        "idiom_submitted_success": "✅ स्थितियाँ सबमिट की गईं! आपके बहुमूल्य योगदान के लिए धन्यवाद!",
        "no_idioms_for_lang": "चयनित भाषा के लिए कोई मुहावरे उपलब्ध नहीं हैं। कृपया कोई अन्य भाषा चुनें या और कहानियाँ योगदान करें!",
        "lore_msg_text": "**💬 ज्ञान:**",
        "lang_msg_text": "**🌐 भाषा:**",
        "location_msg_text": "**📍 स्थान:**",
        "type_msg_text": "**🏷️ प्रकार:**",
        "on_msg_text": "**⏰ समय:**",
        "by_msg_text": "**👤 द्वारा:**",
        "contributor_you": "(आप)",
        "contributor_logged_in": "(लॉगिन किया हुआ उपयोगकर्ता)",
        "dialog_placeholder": "संवाद, उद्धरण या स्थानीय कहावत",
        "logged_out_success": "सफलतापूर्वक लॉग आउट हो गए!",
        "welcome_back": "आपका स्वागत है",
        "could_not_detect_location_warning": "स्थान का स्वचालित रूप से पता नहीं चल सका। स्थान डेटा के बिना आगे बढ़ रहा है।",
        "leaderboard_subheader": "शीर्ष मुहावरा पहचानने वाले!",
        "leaderboard_username_col": "उपयोगकर्ता नाम",
        "leaderboard_score_col": "कुल स्कोर",
        "no_scores_yet": "अभी तक कोई स्कोर दर्ज नहीं किया गया है! लीडरबोर्ड पर आने के लिए सबसे पहले खेलें।",
        "story_play_subheader": "खेलें: कहानी पूरी करें!",
        "story_starter_text": "**कहानी की शुरुआत:**",
        "your_story_continuation_label": "आपकी कहानी जारी रखें:",
        "submit_story_button": "कहानी सबमिट करें",
        "story_submitted_success": "✅ कहानी सबमिट की गई! आपके रचनात्मक योगदान के लिए धन्यवाद!",
        "no_starters_for_lang": "चयनित भाषा के लिए कोई कहानी शुरुआती उपलब्ध नहीं हैं। कृपया कोई अन्य भाषा चुनें या और कहानियाँ योगदान करें!",
        "story_empty_error": "🚨 आपकी कहानी जारी नहीं रह सकती। रचनात्मक बनें!"
    }
}