i18n: Building Apps for Indian Languages
1.4 billion Indians speak 22 official languages. Supporting Indian languages isn't optional for apps targeting India.
Character Encoding and Fonts
UTF-8: Always use UTF-8. It supports all Unicode characters including Devanagari (Hindi), Tamil, Telugu, Kannada, Malayalam, and others.
<!-- Always include -->
<meta charset="UTF-8" />
Web fonts: System fonts often lack proper rendering for Indian scripts. Use Google Fonts or similar:
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari&display=swap');
body {
font-family: 'Noto Sans Devanagari', sans-serif;
}
Font pairing: Match fonts for body and headings:
- Body: Noto Sans Devanagari
- Headings: Noto Sans Devanagari Bold
Translation Management
Separate content from code: Never hardcode strings.
// Bad
<button>Click Here</button>
// Good
<button>{t('common.clickHere')}</button>
Use i18n library: next-i18next, i18next, or similar.
// i18n.config.js
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'hi', 'ta', 'te'],
},
ns: ['common', 'navigation', 'footer'],
defaultNS: 'common',
}
// pages/index.tsx
import { useTranslation } from 'next-i18next'
export default function Home() {
const { t } = useTranslation()
return <h1>{t('common:welcome')}</h1>
}
Translation files:
// public/locales/en/common.json
{
"welcome": "Welcome",
"clickHere": "Click Here"
}
// public/locales/hi/common.json
{
"welcome": "स्वागत है",
"clickHere": "यहां क्लिक करें"
}
Pluralization and Gender
Languages have complex rules for plurals and gender.
// i18n handles this
t('items', { count: 1 }) // Returns singular form
t('items', { count: 5 }) // Returns plural form
// Hindi example:
// 1 item → "1 वस्तु है"
// 5 items → "5 वस्तुएं हैं"
Date and Number Formatting
Don't assume US format (MM/DD/YYYY). Use locale-aware formatting:
// Bad: Hard-coded format
const date = '12/25/2025' // Is this Dec 25 or something else?
// Good: Locale-aware
const date = new Intl.DateTimeFormat('hi-IN', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(new Date())
// Output in Hindi: "25 दिसंबर 2025"
// Numbers
const number = new Intl.NumberFormat('hi-IN', {
style: 'currency',
currency: 'INR',
}).format(1000)
// Output: "₹ 1,000.00"
Text Direction
Most Indian scripts are left-to-right (LTR). Arabic and Hebrew are right-to-left (RTL). Even if supporting only Indian languages, implement RTL support for future expansion:
<html dir="ltr">
<!-- or dir="rtl" for RTL languages -->
</html>
CSS adjustments for RTL:
.sidebar {
margin-left: 20px; /* LTR */
}
[dir="rtl"] .sidebar {
margin-right: 20px; /* RTL */
margin-left: 0;
}
/* Or use logical properties (modern CSS) */
.sidebar {
margin-inline-start: 20px; /* Works for both LTR and RTL */
}
Keyboard Layouts
Indian language input requires special keyboards (Indic Input Method Editor). Browser support varies:
- Android: Native support for Hindi, Tamil, etc.
- iOS: Limited support; users often use third-party apps.
- Web: Browser input methods work if system is configured.
Test on real devices.
Translation Workflow
- English source: Write all strings in English.
- Export strings: Extract translatable strings via i18n extraction tool.
- Translation: Send to native translators (not Google Translate; regional nuances matter).
- Review: Translators review for context and accuracy.
- Import: Load translations into app.
- QA: Test each language variant (text overflow, truncation, formatting).
Context Matters
Words without context are misleading. For example, "नमस्ते" (Namaste) is formal; "हाय" (Hi) is casual. Provide context to translators:
{
"greeting_formal": "नमस्ते", // Hindi formal greeting
"greeting_casual": "हाय" // Hindi casual greeting
}
Testing
Test each language thoroughly:
- Text overflow: Hindi words are longer than English.
overflow: hiddenclips unexpectedly. - Font rendering: Some characters combine (Devanagari combining marks). Fonts handle this inconsistently.
- Number formats: Ensure currency, percentages display correctly.
- Input validation: Some languages have different character validation rules.
Real Example
A fintech app targeting India:
English version: "Transfer amount" Hindi version: "स्थानांतरण राशि" Tamil version: "மாற்று தொகை"
All three load based on user preference. If user switches to Hindi, entire app re-renders in Hindi—no page refresh, seamless transition.
Frequently asked questions
Should I use Google Translate for Indian languages?
No. Machine translation misses cultural nuances and context. Hire native translators. Google Translate is acceptable only for initial drafts.
What font should I use for Hindi text?
Noto Sans Devanagari (Google Fonts) is reliable and comprehensive. Avoid generic sans-serif fonts; they often lack proper script rendering.
How do I handle text overflow in Hindi?
Hindi text is ~30% longer than English. Design with wider containers, allow text wrapping, and test on real content.