My Biggest Mistake: Why You Should i18n Your Next.js App From Day One
I built a split-bill application called FAMI-KAN (originally for the Japanese market) using Next.js 15 App Router and Supabase. Since I built it mostly through "Vibe Coding" (coding iteratively with AI agents like Claude/Gemini), feature development was incredibly fast. I have absolutely zero professional programming experience, yet AI allowed me to build a fully functional product. I thought I was a genius.
Then, X (Twitter) expanded its multilingual features. Suddenly, global traffic was a real possibility. I realized: If people from around the world click my app link from X and see only Japanese, my user journey is completely broken.
So, I decided to translate my app into 8 languages.
"It should be easy with AI, right?" I thought.
I was dead wrong.
Not building with i18n (next-intl) from Day 1 was the biggest mistake of this project. Even with the power of Vibe Coding, migrating an existing, monolithic codebase was pure hell.
Here is the story of how I survived the migration, the unexpected limits of AI in this process, and how it worked out in the end.
The Nightmare: The 5,000-Line Component
In the beginning, I didn't separate my UI text into JSON dictionaries. I just hardcoded Japanese strings directly into the components. My main event detail page (page.tsx) had ballooned to over 5,000 lines of complex, state-heavy React code.
My First Attempt: I asked the AI agent: "Find all Japanese text in this 5,000-line file and replace it with useTranslations()."
The AI's Failure: The AI completely broke down. It hit context window limits, truncated the output, and hallucinated variables. The app wouldn't even compile.
The Solution: I had to stop treating the AI like a magic wand.
Instead of asking AI to rewrite the React component directly, I asked the AI to write a Node.js AST (Abstract Syntax Tree) replacement script. I ran the script locally to safely extract and replace strings with t('...') in chunks. Lesson learned: Don't let AI edit massive files directly; let AI write the tools to edit them.
Surviving Next.js 15: The "Knowledge Cutoff" Trap
Choosing a translation library was another hurdle. I went with next-intl because of its App Router support. However, my Vibe Coding approach hit a brick wall.
The AI's Failure: Most AI models are trained on data up to 2023 or early 2024. Next.js 15 introduced a strict new rule: params in dynamic routes (like [locale]) must be a Promise. The AI kept generating old Next.js 14 code (params.locale), causing the compiler (tsc --noEmit) to scream at me with endless errors.
The Solution: As a non-programmer, I didn't know how to fix it by reading the official docs. Instead, I had to blindly copy-paste the angry compiler errors back to the AI, over and over, forcing the AI to self-correct and update its own context through brute force. Lesson learned: Vibe Coding is amazing, but AI's outdated knowledge will make you fight the modern compiler.
Protecting My Hard-Earned SEO
One of my biggest fears was destroying the SEO I had built for the Japanese market.
If I changed the root URL structure, my existing indexed pages and backlinks from blogs would die. I explicitly instructed the AI: "Do not touch the existing routing structure for Japanese. Only add /en/ or /es/ as subdirectories for other languages."
Thanks to next-intl's middleware, I achieved this. The root / remains Japanese (protecting SEO), while /en/ handles the new English traffic. Additionally, the AI helped me build a dynamic sitemap.ts to output hreflang tags correctly.
Localization > Translation (When AI Got Too Creative)
My app generates sample demo data for first-time users.
In Japanese, the demo event was "The Tabei Family's Trip to Okinawa."
The Translation Issue: If I just literally translated it, English users would see "Trip to Okinawa." Sure, they might know Tokyo or Kyoto, but Okinawa isn't exactly relatable to everyone globally.
The Solution (The AI's Surprising Play): I told the AI: "Make the demo data more natural for global users."
I expected it to just use "Tokyo Trip" or "Kyoto Trip." But to my surprise, the AI went full localization mode. It decided to completely rewrite the demo context for each language!
- Spanish version: "The Garcia Family's Trip to CancΓΊn"
- French version: "The Martin Family's Trip to Nice"
- Hindi version: "The Sharma Family's Trip to Shimla"
It was hilarious that the AI completely ignored my original Japanese context, but honestly, it was the right move. This level of cultural empathy makes the app feel native to users around the world.
Bonus: Localizing for AI Crawlers (llms.txt)
Finally, we are in the era of Generative Engine Optimization (GEO). Users aren't just searching Google; they are asking ChatGPT and Gemini.
I didn't just translate the UI. I instructed the AI to create a /en/llms.txt and /en/llms-full.txt file for English AI crawlers. Now, when an English user asks an AI, "What is a good app to split travel costs based on ratios?", the AI has direct, English-localized markdown context to read and recommend my app.
Conclusion
If you are starting a new Next.js project today, put next-intl in from Day 1. Even if you only support your native language. Hardcoding strings will punish you later.
Vibe coding is an incredible superpower. It allowed meβa solo developer with zero programming backgroundβto push a massive 8-language update in a matter of days. But AI still has its limits, from context windows to outdated framework knowledge.
If you found this story helpful, you can check out FAMI-KAN here. I'll also be launching on Product Hunt early next month, so any feedback on the English UI would be greatly appreciated!
(You can find me building in public on X at @vibe_archi)
Top comments (0)