import streamlit as st import streamlit.components.v1 as components import random import re import time import html as html_lib import requests from datetime import datetime # ============================================================ # PAGE CONFIGURATION # ============================================================ st.set_page_config( page_title="LinkedIn Translator | Normal English β†’ LinkedIn Language", page_icon="πŸ’Ό", layout="wide", initial_sidebar_state="expanded", ) # ============================================================ # SESSION STATE INITIALIZATION # ============================================================ if "history" not in st.session_state: st.session_state.history = [] if "theme" not in st.session_state: st.session_state.theme = "dark" if "translation_count" not in st.session_state: st.session_state.translation_count = 0 if "last_output" not in st.session_state: st.session_state.last_output = "" if "last_input" not in st.session_state: st.session_state.last_input = "" if "last_style" not in st.session_state: st.session_state.last_style = "" if "was_spun" not in st.session_state: st.session_state.was_spun = False if "last_ai_used" not in st.session_state: st.session_state.last_ai_used = False # ============================================================ # STYLE DEFINITIONS # ============================================================ STYLES = { "Corporate Buzzword 🏒": { "key": "corporate", "desc": "Synergy, leverage, and moving the needle. Sound important while saying nothing.", "color": "#0A66C2", }, "Humble Brag 😌": { "key": "humblebrag", "desc": "Humbled. Honored. Blessed. Modesty is just another word for showing off.", "color": "#E7A33E", }, "Hustle Culture πŸ’ͺ": { "key": "hustle", "desc": "5AM wakeups, no days off, and questionable life choices.", "color": "#FF6B35", }, "Thought Leader 🧠": { "key": "thoughtleader", "desc": "Hot takes nobody asked for. Let that sink in.", "color": "#7B68EE", }, "Tech Bro πŸš€": { "key": "techbro", "desc": "Shipping, iterating, and disrupting. What's your stack?", "color": "#00D4AA", }, "Motivational Speaker πŸ”₯": { "key": "motivational", "desc": "REMINDER: You are a warrior. Act like it.", "color": "#FF4500", }, "Maximum Cringe 😬": { "key": "maxcringe", "desc": "All LinkedIn stereotypes combined. You've been warned.", "color": "#FF1493", }, } EXAMPLE_INPUTS = [ "I got a new job", "I lost my job", "I learned Python today", "I woke up early today", "I made a mistake at work", "We had a meeting about the project", "I had coffee this morning", "I failed my interview", ] # ============================================================ # THEMING / CSS # ============================================================ def inject_css(theme): if theme == "dark": css = """ """ else: css = """ """ st.markdown(css, unsafe_allow_html=True) # ============================================================ # POSITIVITY SPIN LAYER # ============================================================ POSITIVITY_SPINS = [ (r'\bI lost my job\b', "I've embraced a new chapter in my career journey"), (r'\bI got fired\b', "I was given the freedom to pursue bigger things"), (r'\bI was fired\b', "I was given the freedom to pursue bigger things"), (r'\bI got laid off\b', "I was presented with an unexpected career pivot"), (r'\bI was laid off\b', "I was presented with an unexpected career pivot"), (r'\bI was let go\b', "I was released to explore new horizons"), (r'\bI was made redundant\b', "I was offered a clean slate to reinvent myself"), (r'\bI was terminated\b', "I was given a bold opportunity to start fresh"), (r'\bI\'m unemployed\b', "I\'m in between exciting opportunities"), (r'\bunemployed\b', "between opportunities"), (r'\bI got downsized\b', "I was given the gift of a fresh start"), (r'\bI quit my job\b', "I courageously chose to bet on myself"), (r'\bI resigned\b', "I boldly decided it was time for my next act"), (r'\bI walked out\b', "I took a bold stand for my values"), (r'\bI failed\b', "I discovered a powerful lesson"), (r'\bI failed at\b', "I learned immensely from"), (r'\bI failed my\b', "I had a growth experience with my"), (r'\bfailure\b', "stepping stone"), (r'\bI made a mistake\b', "I had a breakthrough learning moment"), (r'\bI messed up\b', "I found an unexpected growth opportunity"), (r'\bI screwed up\b', "I stumbled onto a valuable lesson"), (r'\bI was wrong\b', "I evolved my perspective"), (r'\bI ruined\b', "I transformed"), (r'\bI gave up\b', "I courageously redirected my energy"), (r'\bI was rejected\b', "I was redirected toward something better"), (r'\bI got rejected\b', "I was protected from the wrong path"), (r'\bI got turned down\b', "I was being saved for the right opportunity"), (r'\bI didn\'t get the job\b', "The right role is still finding me"), (r'\bI didn\'t get accepted\b', "I was being guided to my true path"), (r'\bI failed my interview\b', "My interview became a masterclass in growth"), (r'\brejected\b', "redirected"), (r'\bI\'m struggling\b', "I\'m in the crucible that forges future leaders"), (r'\bI\'m stuck\b', "I\'m in a season of preparation for something great"), (r'\bI\'m lost\b', "I\'m exploring uncharted territory with curiosity"), (r'\bI\'m confused\b', "I\'m navigating a beautiful period of discovery"), (r'\bI\'m overwhelmed\b', "I\'m being stretched into the leader I\'m meant to be"), (r'\bI\'m stressed\b', "I\'m being forged in the fire of purpose"), (r'\bI\'m exhausted\b', "I\'m pouring everything into what matters"), (r'\bI\'m tired\b', "I\'m investing my energy in meaningful work"), (r'\bI\'m burned out\b', "I\'m taking a well-deserved season of renewal"), (r'\bI\'m broken\b', "I\'m being rebuilt stronger than ever"), (r'\bI\'m sad\b', "I\'m processing deep emotions that make me human"), (r'\bI\'m depressed\b', "I\'m navigating a chapter that will inspire others someday"), (r'\bI\'m anxious\b', "I\'m being called to trust the process"), (r'\bI\'m lonely\b', "I\'m in a sacred season of self-discovery"), (r'\bI can\'t find a job\b', "I\'m being selective about my next career move"), (r'\bI can\'t do this\b', "I\'m being challenged to grow beyond my comfort zone"), (r'\bI can\'t\b', "I\'m still learning to"), (r'\bnothing is working\b', "I\'m in the messy middle of my breakthrough"), (r'\bnothing works\b', "every attempt brings me closer to the answer"), (r'\bI hate my job\b', "I\'m being called to find work that aligns with my purpose"), (r'\bI hate\b', "I\'m deeply motivated to transform"), (r'\bI don\'t like\b', "I\'m inspired to improve"), (r'\bI\'m broke\b', "I\'m investing in experiences over material things"), (r'\bI have no money\b', "I\'m resource-rich in ways that matter most"), (r'\bI\'m poor\b', "I\'m building wealth in character and resilience"), (r'\bI was demoted\b', "I was given the chance to reconnect with the frontline"), (r'\bI got demoted\b', "I was invited back to where the real impact happens"), (r'\bI got dumped\b', "I was freed to focus on becoming my best self"), (r'\bwe broke up\b', "we each graduated to our next chapter of growth"), (r'\bterrible\b', "challenging yet transformative"), (r'\bhorrible\b', "an invitation to grow"), (r'\bawful\b', "a catalyst for change"), (r'\bworst\b', "most defining"), (r'\bdisaster\b', "opportunity in disguise"), (r'\bcatastrophe\b', "turning point"), (r'\bnightmare\b', "defining challenge that shaped me"), (r'\bproblem\b', "opportunity"), (r'\bissue\b', "growth area"), (r'\bweakness\b', "opportunity for development"), ] def apply_positivity_spin(text): original = text for pattern, replacement in POSITIVITY_SPINS: text = re.sub(pattern, replacement, text, flags=re.IGNORECASE) was_spun = (text != original) return text, was_spun # ============================================================ # TRANSLATION ENGINE β€” RULE-BASED # ============================================================ def apply_replacements(text, style): universal = [ (r'\bvery good\b', 'absolutely phenomenal'), (r'\bvery bad\b', 'a tremendous growth opportunity'), (r'\bworked hard\b', 'poured my heart and soul'), (r'\bsuccessful\b', 'wildly successful'), ] for pattern, repl in universal: text = re.sub(pattern, repl, text, flags=re.IGNORECASE) all_replacements = { "corporate": [ (r'\bjob\b', 'role within the organizational ecosystem'), (r'\bwork\b', 'value-adding initiative'), (r'\bmeeting\b', 'strategic alignment session'), (r'\bhelp\b', 'provide cross-functional bandwidth for'), (r'\bidea\b', 'actionable insight with measurable ROI'), (r'\bplan\b', 'strategic roadmap with key milestones'), (r'\bproject\b', 'flagship initiative'), (r'\bteam\b', 'high-performing squad'), (r'\bboss\b', 'key stakeholder'), (r'\bchange\b', 'paradigm shift'), (r'\bthink\b', 'ideate'), (r'\buse\b', 'leverage'), (r'\bstart\b', 'kick off'), (r'\bimprove\b', 'move the needle on'), (r'\btalk\b', 'circle back on'), (r'\blearn\b', 'deep dive into'), (r'\bmake\b', 'operationalize'), (r'\bimportant\b', 'mission-critical'), (r'\bfast\b', 'with velocity and agility'), (r'\bbig\b', 'at scale'), (r'\bnew\b', 'net-new'), (r'\btogether\b', 'synergistically'), (r'\bgood\b', 'high-impact'), (r'\bdo\b', 'execute against'), (r'\bneed\b', 'have identified a requirement for'), (r'\btry\b', 'explore the feasibility of'), (r'\bsend\b', 'cascade'), (r'\bfix\b', 'remediate'), (r'\bcheck\b', 'socialize'), ], "humblebrag": [ (r'\bI got\b', 'I was humbled and honored to receive'), (r'\bI achieved\b', 'I was blessed to achieve'), (r'\bI won\b', "By God's grace, I was awarded"), (r'\bI was promoted\b', 'I was graciously entrusted with an expanded role'), (r'\bgood\b', 'beyond what I deserve'), (r'\bhired\b', 'welcomed into an incredible family'), (r'\bpromoted\b', 'given an opportunity I scarcely deserve'), (r'\baward\b', 'a recognition that left me speechless'), (r'\bexcited\b', 'humbled beyond words'), (r'\bproud\b', 'overcome with gratitude'), (r'\bhappy\b', 'blessed beyond measure'), (r'\bsuccessful\b', 'overwhelmed by the kindness of the universe'), ], "hustle": [ (r'\bwoke up\b', 'was already grinding while others were sleeping'), (r'\bworked\b', 'was putting in the work'), (r'\bsleep\b', 'sleep is for the weak'), (r'\brest\b', "rest? Never heard of her"), (r'\bjob\b', 'grind'), (r'\bwork\b', 'the hustle'), (r'\beffort\b', 'relentless dedication'), (r'\bgood\b', 'next level'), (r'\bsuccess\b', 'the result of outworking everyone'), (r'\bhard\b', 'the price of greatness'), (r'\bfailed\b', 'one step closer to the goal'), (r'\btrying\b', 'committing 110%'), (r'\bday off\b', "what's that?"), (r'\bweekend\b', 'just another opportunity to grind'), ], "thoughtleader": [ (r'\bI think\b', 'My contrarian take:'), (r'\bI believe\b', "Here's the truth nobody wants to hear:"), (r'\bI learned\b', 'What I discovered will change how you see everything:'), (r'\bI found\b', 'The insight that changed my perspective:'), (r'\bimportant\b', 'the single most overlooked truth'), (r'\bgood\b', 'what the top 1% understand'), (r'\bpeople\b', 'most people'), (r'\badvice\b', 'the uncomfortable truth'), ], "techbro": [ (r'\bmade\b', 'shipped'), (r'\bbuilt\b', 'shipped'), (r'\bcreated\b', 'shipped'), (r'\bstarted\b', 'launched my MVP'), (r'\blearned\b', 'leveled up in'), (r'\bjob\b', 'role in the trenches'), (r'\bwork\b', "what I'm building"), (r'\bproject\b', "side project that's about to be huge"), (r'\bidea\b', 'the next big thing'), (r'\bteam\b', 'my co-founders and I'), (r'\bcompany\b', 'my startup'), (r'\bmoney\b', 'runway'), (r'\bgood\b', 'absolutely cracked'), (r'\bfast\b', 'at breakneck speed'), (r'\bimprove\b', 'iterate on'), (r'\bchange\b', 'disrupt'), (r'\bplan\b', 'product roadmap'), (r'\bnew\b', 'net-new'), ], "motivational": [ (r'\bgood\b', 'UNSTOPPABLE'), (r'\bhard\b', 'THE FIRE THAT FORGES CHAMPIONS'), (r'\btired\b', 'RECHARGING FOR GREATNESS'), (r'\bscared\b', 'ABOUT TO DO SOMETHING BRAVE'), (r"\bcan't\b", "HAVEN'T YET"), (r'\bimpossible\b', 'A CHALLENGE WORTH CONQUERING'), ], "maxcringe": [ (r'\bgood\b', 'absolutely GAME-CHANGING and MIND-BLOWING'), (r'\bwork\b', 'value-adding, paradigm-shifting hustle'), (r'\bjob\b', 'purpose-driven mission'), (r'\bteam\b', 'squad of absolute ROCKSTARS'), (r'\bsuccess\b', 'WILD, UNPRECEDENTED success'), (r'\blearned\b', 'had my MIND BLOWN learning'), (r'\bexcited\b', 'BEYOND HUMBLED and literally SHAKING with excitement'), (r'\bimportant\b', 'MISSION-CRITICAL and NON-NEGOTIABLE'), (r'\bgreat\b', 'PHENOMENAL and WORLD-CLASS'), ], } replacements = all_replacements.get(style, all_replacements["maxcringe"]) for pattern, repl in replacements: text = re.sub(pattern, repl, text, flags=re.IGNORECASE) return text def apply_template(text, style): templates = { "corporate": { "prefixes": [ "Thrilled to announce that ", "Excited to share that ", "Pleased to report that ", "After extensive cross-functional alignment, ", "Following a comprehensive deep dive, ", ], "suffixes": [ "\n\nThe synergies here are truly remarkable. Looking forward to circling back on next steps. πŸ’Ό", "\n\nThis represents a significant value-add for all stakeholders. Let's take this offline to discuss further. πŸ“Š", "\n\nThe ROI on this initiative speaks for itself. Excited to operationalize at scale. 🎯", "\n\nKey takeaway: when we align our strategic priorities and execute with velocity, the results speak for themselves. πŸ’Ό", ], }, "humblebrag": { "prefixes": [ "Humbled and honored to share that ", "I don't say this to brag, but ", "Still processing the fact that ", "Overwhelmed with gratitude that ", "Pinch me moment: ", "Blessed beyond measure to announce that ", ], "suffixes": [ "\n\nI am not worthy of this blessing. Grateful beyond words. πŸ™βœ¨", "\n\nThis wouldn't have been possible without my village. I'm just so humbled. πŸ˜ŒπŸ’«", "\n\nFeeling so much gratitude. If I can achieve this, anyone can. πŸ™", "\n\nHumbled. Honored. Blessed. Grateful. Overwhelmed. πŸ™βœ¨πŸ’«", ], }, "hustle": { "prefixes": [ "While you were sleeping, ", "While others were resting, ", "No days off. ", "The grind doesn't stop. ", "4:30 AM. Coffee. Grind. Repeat. ", "While they were making excuses, ", ], "suffixes": [ "\n\nπŸ’€ Sleep is for the weak. πŸ’ͺ Grind never stops. πŸ”₯ No excuses.", "\n\nThe grindset is real. While they sleep, we grind. While they complain, we build. πŸ’ͺπŸ”₯", "\n\nRemember: The only thing standing between you and your dreams is the snooze button. ⏰πŸ’ͺ", "\n\nπŸ”₯ Success isn't given. It's earned. On the grind. Every. Single. Day. πŸ’ͺ", ], }, "thoughtleader": { "prefixes": [ "Hot take: ", "Unpopular opinion: ", "Here's what nobody tells you: ", "Let that sink in: ", "I've been saying this for years: ", "A thread 🧡: ", ], "suffixes": [ "\n\nLet that sink in. 🧠\n\nAgree? Drop a πŸ‘\nDisagree? Let's debate.", "\n\nI said what I said. 🎀 The truth hurts, but it also sets you free. 🧠", "\n\nMost won't understand this. The ones who do? They're already ahead. πŸ§ πŸ’‘", "\n\nSave this post. Come back to it in 6 months. You'll see. 🧠⏰", ], }, "techbro": { "prefixes": [ "πŸš€ Just shipped: ", "⚑ Building in public update: ", "πŸ’» Late night coding session results: ", "πŸ”₯ What I learned while building: ", "πŸ› οΈ MVP update: ", ], "suffixes": [ "\n\nπŸš€ Shipping > Talking. Building > Planning. Iterating > Perfecting. Let's go! ⚑", "\n\nShip fast. Break things. Iterate. Scale. Repeat. πŸš€βš‘ #BuildInPublic", "\n\nIf you're not embarrassed by your first version, you shipped too late. πŸš€ Shipped. Learned. Iterating. ⚑", ], }, "motivational": { "prefixes": [ "πŸ”₯ REMINDER: ", "⚑ WAKE UP CALL: ", "πŸ’« TRUTH BOMB: ", "🌟 DON'T SCROLL PAST THIS: ", "✨ READ THIS IF YOU'RE STRUGGLING: ", "πŸ‘‘ DAILY AFFIRMATION: ", ], "suffixes": [ "\n\n✨ Your only limit is you. Believe it. Achieve it. πŸ”₯\n\nLike if you agree. Share if you care. Comment 'YES' if you're ready.", "\n\nπŸ’ͺ You are stronger than you think. Braver than you believe. ✨\n\nTag someone who needs to hear this today.", "\n\nπŸ”₯ The comeback is ALWAYS greater than the setback. Keep pushing. Keep going. ✨\n\nWho's with me? Drop a πŸ”₯ below.", "\n\n✨ Remember: Every expert was once a beginner. Your time is NOW. πŸ’ͺ\n\nShare this with someone who needs it.", ], }, "maxcringe": { "prefixes": [ "🚨 STOP SCROLLING! 🚨\n\nHumbled. Honored. Blessed. Thrilled. Overwhelmed. Grateful. Shaking. ", "I literally can't even right now. ", "THIS IS NOT A DRILL πŸ”₯πŸ”₯πŸ”₯\n\nHumbled and honored to announce that ", "Pinch me. Slap me. Call me crazy. ", "πŸš€πŸ’₯ GAME. CHANGER. πŸ’₯πŸš€\n\n", ], "suffixes": [ "\n\nπŸ™ Humbled. Honored. Blessed. Grateful. Overwhelmed. Literally shaking.\n\nπŸ’₯ Agree? Like!\nπŸ’¬ Disagree? Comment!\nπŸ”„ Care? Share!\n\n#Grateful #Blessed #Humbled #LinkedInLife #Motivation #Hustle #Grind #Success", "\n\nThis is what they don't teach you in school. πŸŽ“βŒ\n\nπŸ”₯πŸ”₯πŸ”₯\n\nWho else relates? Comment 'YES' below!\n\n#Leadership #Success #Motivation #Inspiration #Hustle #Grindset #Mindset #Growth #Goals #DreamBig", "\n\nLet that sink in. 🧠 Now circle back and leverage this. πŸ’Ό Then go grind. πŸ’ͺ And ship it. πŸš€\n\nBEYOND HUMBLED. πŸ™βœ¨πŸ”₯πŸ’«\n\n#Synergy #Hustle #Grindset #Leadership #ThoughtLeadership #BuildInPublic #Grateful #Blessed #Mindset #10x #Scale #Disrupt", "\n\nIf this post inspired even ONE person, it was worth it. πŸ₯ΊπŸ™\n\nπŸ‘‰ Like if you're a GO-GETTER\nπŸ‘‰ Comment if you're UNSTOPPABLE\nπŸ‘‰ Share if you DARE TO DREAM\n\n#Motivation #Inspiration #Leadership #Blessed #Humble #Grind #Success #Winning #Champion #Mindset", ], }, } template = templates.get(style, templates["maxcringe"]) prefix = random.choice(template["prefixes"]) suffix = random.choice(template["suffixes"]) if text and text[0].islower(): text = text[0].upper() + text[1:] return f"{prefix}{text}{suffix}" def add_emojis(text, style): emoji_sets = { "corporate": ["πŸ“Š", "πŸ“ˆ", "🎯", "πŸ’Ό", "🏒", "πŸ’‘", "πŸ“‹", "πŸ”‘", "βš™οΈ"], "humblebrag": ["πŸ™", "✨", "πŸ’«", "😌", "🌟", "πŸ₯Ί", "πŸ’", "πŸ¦‹", "πŸ’Ž"], "hustle": ["πŸ’ͺ", "πŸ”₯", "⏰", "πŸƒ", "πŸ’¨", "πŸ‹οΈ", "🦁", "⚑", "🎯"], "thoughtleader": ["🧠", "πŸ’‘", "πŸ€”", "πŸ‘οΈ", "πŸŽ™οΈ", "πŸ”", "πŸ“Œ", "βš–οΈ"], "techbro": ["πŸš€", "⚑", "πŸ’»", "πŸ› οΈ", "πŸ”§", "πŸ“±", "πŸ€–", "⌨️", "πŸ–₯️"], "motivational": ["πŸ”₯", "✨", "πŸ’ͺ", "🌟", "πŸ’«", "πŸ‘‘", "🦁", "⭐", "πŸ†"], "maxcringe": ["πŸ”₯", "πŸš€", "πŸ’ͺ", "πŸ™", "✨", "πŸ’«", "🧠", "πŸ’Ό", "⚑", "πŸ“ˆ", "🎯", "πŸ’Ž", "πŸ‘‘", "🌟", "πŸ‘"], } emojis = emoji_sets.get(style, emoji_sets["maxcringe"]) sentences = re.split(r'(?<=[.!?])\s+', text) result = [] for i, sentence in enumerate(sentences): result.append(sentence) if i < len(sentences) - 1 and random.random() > 0.45: result.append(f" {random.choice(emojis)}") text = " ".join(result) return text def add_hashtags(text, style): hashtags = { "corporate": ["#Leadership", "#Strategy", "#Innovation", "#BusinessGrowth", "#Management", "#StakeholderValue"], "humblebrag": ["#Blessed", "#Grateful", "#Humbled", "#Honored", "#Thankful", "#Overwhelmed"], "hustle": ["#Hustle", "#Grind", "#NoDaysOff", "#5AMClub", "#Motivation", "#Grindset", "#EntrepreneurLife"], "thoughtleader": ["#ThoughtLeadership", "#HotTake", "#UnpopularOpinion", "#ThinkDifferent", "#Contrarian", "#Insights"], "techbro": ["#BuildInPublic", "#StartupLife", "#Shipping", "#TechStartup", "#MVP", "#Disrupt", "#Iteration"], "motivational": ["#Motivation", "#Inspiration", "#BelieveInYourself", "#NeverGiveUp", "#DreamBig", "#YouGotThis"], "maxcringe": ["#LinkedInLife", "#Grateful", "#Blessed", "#Humbled", "#Hustle", "#Leadership", "#Motivation", "#Inspiration", "#Growth", "#Mindset", "#Success", "#10x", "#Disrupt", "#Synergy", "#Grind"], } tags = hashtags.get(style, hashtags["maxcringe"]) num_tags = random.randint(3, min(6, len(tags))) selected = random.sample(tags, num_tags) return f"{text}\n\n{' '.join(selected)}" def translate_with_rules(text, style_name): style_info = STYLES.get(style_name, STYLES["Maximum Cringe 😬"]) style_key = style_info["key"] text, was_spun = apply_positivity_spin(text) result = apply_replacements(text, style_key) result = apply_template(result, style_key) result = add_emojis(result, style_key) result = add_hashtags(result, style_key) return result, was_spun # ============================================================ # TRANSLATION ENGINE β€” AI-POWERED # ============================================================ def translate_with_ai(text, style_name, api_key): style_info = STYLES.get(style_name, STYLES["Maximum Cringe 😬"]) style_key = style_info["key"] style_prompts = { "corporate": ( "exaggerated corporate buzzword LinkedIn speak. Use synergy, leverage, paradigm shift, " "circle back, deep dive, move the needle, operationalize, net-new, mission-critical, " "value-add, stakeholders, cross-functional. IMPORTANT: Always spin anything negative " "into a positive opportunity. Never say anything bad directly." ), "humblebrag": ( "humble brag LinkedIn speak. Start with being humbled and honored, mention blessings " "and gratitude while definitely bragging. Say things like 'I don't say this to brag but...' " "then brag. IMPORTANT: Always spin anything negative into a blessing in disguise." ), "hustle": ( "hustle culture LinkedIn speak. 5AM grind, no days off, outwork everyone, grindset, " "beast mode. IMPORTANT: Always spin anything negative as fuel for the grind, a stepping " "stone, or being tested by the universe." ), "thoughtleader": ( "thought leader LinkedIn speak. Hot takes, unpopular opinions, 'let that sink in', " "contrarian takes nobody asked for. IMPORTANT: Always spin negatives as profound lessons " "or hidden truths that most people miss." ), "techbro": ( "tech bro LinkedIn speak. Shipping, building in public, MVP, PMF, disrupting, iterating, " "scaling. IMPORTANT: Always spin negatives as pivots, learning experiences, or 'iterating " "on the product'. Never admit failure, only pivoting." ), "motivational": ( "over-the-top motivational speaker LinkedIn speak. ALL CAPS REMINDERS, you are enough, " "believe in yourself, never give up, inspirational but cringe. IMPORTANT: Always spin " "negatives as SETBACKS that are really SETUPS for COMEBACKS." ), "maxcringe": ( "maximum cringe LinkedIn speak. Combine ALL LinkedIn stereotypes: corporate buzzwords, " "humble brags, hustle culture, excessive emojis, hashtag everything, call to actions like " "'comment YES'. IMPORTANT: ALWAYS spin anything negative into something positive. If someone " "lost their job, say they 'embraced a new chapter'. If they failed, say they 'discovered a " "powerful lesson'. NEVER be negative. Everything is a blessing, opportunity, or stepping stone." ), } style_prompt = style_prompts.get(style_key, style_prompts["maxcringe"]) prompt = f"""[INST] You are the LinkedIn Language Translator. Your #1 rule: NEVER say anything negative directly. Everything must be spun positive. Lost a job = "new chapter". Failed = "discovered a lesson". Fired = "freed to pursue bigger things". Convert the following normal English into {style_prompt}. Only output the LinkedIn post, nothing else. No explanations. No quotes around the output. Normal English: {text}[/INST]""" models = [ "HuggingFaceH4/zephyr-7b-beta", "mistralai/Mistral-7B-Instruct-v0.2", "microsoft/phi-2", ] last_error = None for model in models: try: api_url = f"https://api-inference.huggingface.co/models/{model}" headers = {"Authorization": f"Bearer {api_key}"} payload = { "inputs": prompt, "parameters": { "max_new_tokens": 400, "temperature": 0.9, "top_p": 0.95, "do_sample": True, "return_full_text": False, }, } response = requests.post(api_url, headers=headers, json=payload, timeout=60) if response.status_code == 200: result = response.json() if isinstance(result, list) and len(result) > 0: generated = result[0].get("generated_text", "").strip() for tag in ["", "", "[/INST]", "[INST]"]: generated = generated.replace(tag, "") generated = generated.strip() if len(generated) > 20: return generated, None elif response.status_code == 503: try: error_info = response.json() wait_time = min(error_info.get("estimated_time", 20), 30) except Exception: wait_time = 15 time.sleep(wait_time) response = requests.post(api_url, headers=headers, json=payload, timeout=60) if response.status_code == 200: result = response.json() if isinstance(result, list) and len(result) > 0: generated = result[0].get("generated_text", "").strip() for tag in ["", "", "[/INST]", "[INST]"]: generated = generated.replace(tag, "") generated = generated.strip() if len(generated) > 20: return generated, None else: last_error = f"Model {model}: HTTP {response.status_code}" elif response.status_code == 401: return None, "Invalid API token. Check your HuggingFace token and try again." elif response.status_code == 429: last_error = f"Rate limited on {model}. Trying next..." time.sleep(2) continue else: last_error = f"Model {model}: HTTP {response.status_code}" continue except requests.exceptions.Timeout: last_error = f"Model {model} timed out." continue except Exception as e: last_error = f"Error with {model}: {str(e)[:80]}" continue return None, last_error or "All AI models unavailable. Using rule-based fallback." # ============================================================ # UTILITY FUNCTIONS # ============================================================ def calculate_cringe_score(text): buzzwords = [ 'synergy', 'leverage', 'paradigm', 'circle back', 'deep dive', 'bandwidth', 'humbled', 'honored', 'blessed', 'grateful', 'overwhelmed', 'hustle', 'grind', '5am', 'no days off', 'hot take', 'let that sink in', 'unpopular opinion', 'shipping', 'building in public', 'mvp', 'disrupt', 'reminder', 'game-changer', 'net-new', 'mission-critical', 'rockstar', 'thought leader', 'grindset', '10x', 'pmf', 'new chapter', 'opportunity', 'blessing in disguise', 'redirected', 'season of', 'growth opportunity', ] text_lower = text.lower() score = 0 for word in buzzwords: score += text_lower.count(word) * 3 emoji_pattern = re.compile( "[" "\U0001F600-\U0001F64F" "\U0001F300-\U0001F5FF" "\U0001F680-\U0001F6FF" "\U0001F1E0-\U0001F1FF" "\U00002702-\U000027B0" "\U0001F900-\U0001F9FF" "\U00002600-\U000026FF" "\U0000FE00-\U0000FE0F" "\U0001FA00-\U0001FA6F" "\U0001FA70-\U0001FAFF" "\U000027BF" "]+", flags=re.UNICODE, ) score += len(emoji_pattern.findall(text)) * 1 score += len(re.findall(r'#\w+', text)) * 2 score += len(re.findall(r'\b[A-Z]{3,}\b', text)) * 2 ctas = ['like if', 'share if', 'comment below', 'drop a', 'tag someone', 'agree?', 'who else', 'comment yes', 'read this', 'stop scrolling'] for cta in ctas: if cta in text_lower: score += 4 return min(100, score) def get_cringe_level(score): if score <= 20: return "Mildly Corporate", "#4CAF50" elif score <= 40: return "Buzzword Alert", "#8BC34A" elif score <= 60: return "Pretty Cringe", "#FFC107" elif score <= 80: return "Maximum Cringe", "#FF5722" else: return "Nuclear Cringe ☒️", "#F44336" # ============================================================ # MAIN APP # ============================================================ def main(): inject_css(st.session_state.theme) # ---- SIDEBAR ---- with st.sidebar: st.markdown("## βš™οΈ Settings") # Theme toggle st.markdown("#### 🎨 Theme") col_t1, col_t2 = st.columns(2) with col_t1: if st.button("πŸŒ™ Dark", use_container_width=True, type="primary" if st.session_state.theme == "dark" else "secondary"): st.session_state.theme = "dark" st.rerun() with col_t2: if st.button("β˜€οΈ Light", use_container_width=True, type="primary" if st.session_state.theme == "light" else "secondary"): st.session_state.theme = "light" st.rerun() st.markdown("
", unsafe_allow_html=True) # Style selector st.markdown("#### 🎭 Translation Style") style_names = list(STYLES.keys()) selected_style = st.selectbox( "Choose your LinkedIn persona:", style_names, index=0, label_visibility="collapsed", ) style_info = STYLES[selected_style] fg = "#c9d1d9" if st.session_state.theme == "dark" else "#24292f" st.markdown( f"
" f"{style_info['desc']}
", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) # AI Mode st.markdown("#### πŸ€– AI Mode") use_ai = st.toggle("Enable AI Translation", value=False) if use_ai: st.caption("Uses HuggingFace Inference API for smarter, more creative translations.") # Using key="hf_api_key" persists the token in session state automatically st.text_input( "HF API Token", type="password", placeholder="hf_xxxxxxxxxxxxx", help="Get a free token at huggingface.co/settings/tokens", key="hf_api_key" ) # Read from session state so it persists across reruns hf_api_key = st.session_state.get("hf_api_key", "") if not hf_api_key: st.warning("⚠️ Enter your free HF token for AI mode. Falls back to rules if empty.") else: hf_api_key = "" st.markdown("
", unsafe_allow_html=True) # Stats st.markdown("#### πŸ“Š Stats") col_s1, col_s2 = st.columns(2) with col_s1: st.markdown( f"
{st.session_state.translation_count}
" f"
Translations
", unsafe_allow_html=True, ) with col_s2: st.markdown( f"
{len(st.session_state.history)}
" f"
In History
", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) # History st.markdown("#### πŸ“œ History") if st.session_state.history: if st.button("πŸ—‘οΈ Clear History", use_container_width=True): st.session_state.history = [] st.rerun() for item in reversed(st.session_state.history[-10:]): truncated_input = item["input"][:50] + ("..." if len(item["input"]) > 50 else "") style_color = STYLES.get(item["style"], {}).get("color", "#0A66C2") source_icon = "πŸ€–" if item.get("ai") else "βš™οΈ" st.markdown( f"
" f"{item['style'].split(' ')[0]} " f"{source_icon}
" f"Input: {html_lib.escape(truncated_input)}
" f"Time: {item['time']} β€’ Cringe: {item['cringe']}/100" f"
", unsafe_allow_html=True, ) else: st.caption("No translations yet. Start translating!") # ---- MAIN CONTENT ---- # Header st.markdown('

LinkedIn Translator

', unsafe_allow_html=True) st.markdown('

Transform normal English into the language of LinkedIn 🀝

', unsafe_allow_html=True) # Example chips st.markdown("##### πŸ’‘ Try an example:") chip_cols = st.columns(4) for i, example in enumerate(EXAMPLE_INPUTS[:8]): col_idx = i % 4 with chip_cols[col_idx]: if st.button(example, key=f"ex_{i}", use_container_width=True): st.session_state.input_area = example st.rerun() st.markdown("
", unsafe_allow_html=True) # Input / Output columns col_input, col_output = st.columns(2) with col_input: st.markdown( "
πŸ“ Normal English
", unsafe_allow_html=True, ) input_text = st.text_area( "Enter your text:", height=200, label_visibility="collapsed", placeholder="Type something normal here...\n\ne.g., I lost my job", key="input_area", ) char_count = len(input_text) if input_text else 0 word_count = len(input_text.split()) if input_text and input_text.strip() else 0 st.markdown( f"
" f"{word_count} words β€’ {char_count}/2000 characters
", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) with col_output: st.markdown( "
πŸ’Ό LinkedIn Language
", unsafe_allow_html=True, ) if st.session_state.last_output: safe_output = html_lib.escape(st.session_state.last_output).replace("\n", "
") # Build tags row tags = [] if st.session_state.get("last_ai_used"): tags.append('πŸ€– AI Generated') else: tags.append('βš™οΈ Rule-Based') if st.session_state.get("was_spun"): tags.append('✨ Positivity Spin') tags_html = f"
{'' .join(tags)}
" st.markdown( f"{tags_html}
{safe_output}
", unsafe_allow_html=True, ) else: st.markdown( "
Your LinkedIn masterpiece will appear here ✨
", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) # Action buttons col_b1, col_b2, col_b3, col_b4 = st.columns([2, 1, 1, 1]) with col_b1: translate_btn = st.button("πŸ”„ **Translate to LinkedIn**", use_container_width=True, type="primary") with col_b2: copy_btn = st.button("πŸ“‹ Copy", use_container_width=True) with col_b3: clear_btn = st.button("πŸ—‘οΈ Clear", use_container_width=True) with col_b4: download_btn = st.download_button( "πŸ’Ύ Save", data=st.session_state.last_output or "", file_name="linkedin_post.txt", mime="text/plain", use_container_width=True, disabled=not st.session_state.last_output, ) # ---- BUTTON ACTIONS ---- if translate_btn: if not input_text or not input_text.strip(): st.toast("⚠️ Please enter some text to translate!", icon="⚠️") elif len(input_text) > 2000: st.toast("⚠️ Text too long! Max 2000 characters.", icon="⚠️") else: with st.spinner("πŸ”„ Translating to LinkedIn-speak..."): output_text = "" was_spun = False ai_used = False ai_error = None if use_ai and hf_api_key: output_text, ai_error = translate_with_ai(input_text, selected_style, hf_api_key) if output_text: ai_used = True st.toast("βœ… AI translation complete!", icon="πŸ€–") else: output_text, was_spun = translate_with_rules(input_text, selected_style) if ai_error: st.toast(f"⚠️ AI unavailable β€” {ai_error}", icon="⚑") else: st.toast("⚠️ AI unavailable β€” used rule-based fallback.", icon="⚑") else: output_text, was_spun = translate_with_rules(input_text, selected_style) time.sleep(0.3) st.toast("βœ… Translation complete!", icon="πŸ’Ό") # Store results st.session_state.last_output = output_text st.session_state.last_input = input_text st.session_state.last_style = selected_style st.session_state.was_spun = was_spun st.session_state.last_ai_used = ai_used st.session_state.translation_count += 1 cringe = calculate_cringe_score(output_text) st.session_state.history.append({ "input": input_text, "output": output_text, "style": selected_style, "cringe": cringe, "time": datetime.now().strftime("%H:%M"), "ai": ai_used, "spun": was_spun, }) st.rerun() if copy_btn: if st.session_state.last_output: safe_text = st.session_state.last_output.replace("\\", "\\\\").replace("`", "\\`").replace("$", "\\$").replace("\n", "\\n") components.html( f""" """, height=0, ) st.toast("πŸ“‹ Copied to clipboard!", icon="βœ…") else: st.toast("⚠️ Nothing to copy!", icon="⚠️") if clear_btn: st.session_state.last_output = "" st.session_state.last_input = "" st.session_state.was_spun = False st.session_state.last_ai_used = False st.session_state.input_area = "" st.rerun() # ---- CRINGE METER ---- if st.session_state.last_output: st.markdown("
", unsafe_allow_html=True) cringe_score = calculate_cringe_score(st.session_state.last_output) cringe_level, cringe_color = get_cringe_level(cringe_score) st.markdown("##### πŸ“Š Cringe Meter") col_cm1, col_cm2 = st.columns([3, 1]) with col_cm1: st.markdown( f"
" f"
" f"
", unsafe_allow_html=True, ) with col_cm2: st.markdown( f"
" f"{cringe_score}/100 β€” {cringe_level}
", unsafe_allow_html=True, ) # Show spin notice if st.session_state.get("was_spun"): st.info("✨ **Positivity Spin Applied** β€” Negative phrases were automatically rephrased because on LinkedIn, everything is an opportunity! 🌈") # ---- FOOTER ---- st.markdown("

", unsafe_allow_html=True) footer_color = "#484f58" if st.session_state.theme == "dark" else "#8b949e" st.markdown( f"
" f"Built with ❀️ and excessive buzzwords β€’ LinkedIn Translator v2.1
" f"Rule-based translation always works β€’ Add HF API token for AI-powered translations
" f"✨ Positivity Spin: Because on LinkedIn, nothing is ever truly negative" f"
", unsafe_allow_html=True, ) if __name__ == "__main__": main()