Why We Use getI18n with Object Structures Instead of JSON Files in next-intl
While next-intl encourages using JSON files for translation, we found object-based structures loaded via getI18n to be more flexible and maintainable—especially for dynamic content like FAQs and service lists.
When working with next-intl
for internationalization in a Next.js project, the common approach is to store translations in flat JSON files like this:
// messages/en.json
{
"faq.q1": "What is your service?",
"faq.a1": "We provide..."
}
However, in our production projects, we’ve shifted to using structured TypeScript objects, loaded dynamically via getI18n(locale):
// i18n/en.ts
export const en = {
faq: {
items: [
{ question: "What is your service?", answer: "We provide..." },
...
]
}
}
Why We Prefer Object-Based Translations Over JSON
1. Better for Structured Content (FAQs, Lists, Services)
When dealing with a list of items—such as FAQs—JSON requires naming keys like q1, a1, q2, a2, etc. Adding a new entry means:
- Updating multiple JSON files (e.g., en.json, zh.json)
- Updating the React component logic to handle new keys
With object-based arrays, you simply add a new item to the list. No component changes needed.
2. Improved Developer Experience
With TypeScript, object-based translations offer:
- Autocompletion and type safety
- Early error detection for missing or incorrect keys
- Clear structure when working with nested or grouped content
3. Easier to Maintain and Scale
Large JSON files can become hard to navigate and manage. Object-based files allow:
- Modular organization by page or feature (faq.ts, home.ts, etc.)
- Better version control and collaboration across teams
4. Cleaner Component Logic
With structured content, components don’t need to map or manually resolve keys:
{t.faq.items.map((item, index) => (
<FaqItem key={index} question={item.question} answer={item.answer} />
))}
This is simpler and more maintainable than hardcoding t('faq.q1'), t('faq.a1'), etc.
Conclusion
While JSON-based translation files are standard, we’ve found that using structured objects with getI18n(locale) provides better flexibility, especially for dynamic, list-based content.
For complex websites and multilingual SaaS platforms, this approach dramatically improves maintainability, scalability, and developer experience.