Implement robust multi-language support with type-safe translations and locale management in Google Antigravity
# Internationalization (i18n) Patterns for Google Antigravity
Building applications for a global audience requires thoughtful internationalization implementation. This comprehensive guide covers type-safe translation patterns optimized for Google Antigravity IDE and Gemini 3.
## Core i18n Configuration
```typescript
// lib/i18n/config.ts
export const locales = ['en', 'es', 'fr', 'de', 'ja', 'zh'] as const;
export type Locale = (typeof locales)[number];
export const defaultLocale: Locale = 'en';
export const localeNames: Record<Locale, string> = {
en: 'English',
es: 'Español',
fr: 'Français',
de: 'Deutsch',
ja: '日本語',
zh: '中文',
};
// Type-safe translation keys
export interface TranslationKeys {
common: {
welcome: string;
loading: string;
error: string;
success: string;
cancel: string;
confirm: string;
save: string;
delete: string;
};
navigation: {
home: string;
about: string;
contact: string;
settings: string;
};
auth: {
signIn: string;
signOut: string;
signUp: string;
forgotPassword: string;
emailPlaceholder: string;
passwordPlaceholder: string;
};
errors: {
notFound: string;
unauthorized: string;
serverError: string;
networkError: string;
};
}
```
## Translation Provider Implementation
```typescript
// lib/i18n/provider.tsx
import { createContext, useContext, useState, useCallback } from 'react';
import type { Locale, TranslationKeys } from './config';
import { defaultLocale, locales } from './config';
interface I18nContextType {
locale: Locale;
setLocale: (locale: Locale) => void;
t: <K extends keyof TranslationKeys>(
namespace: K,
key: keyof TranslationKeys[K],
params?: Record<string, string | number>
) => string;
formatDate: (date: Date, options?: Intl.DateTimeFormatOptions) => string;
formatNumber: (num: number, options?: Intl.NumberFormatOptions) => string;
formatCurrency: (amount: number, currency?: string) => string;
}
const I18nContext = createContext<I18nContextType | null>(null);
// Dynamic translation loader with caching
const translationCache = new Map<Locale, TranslationKeys>();
async function loadTranslations(locale: Locale): Promise<TranslationKeys> {
if (translationCache.has(locale)) {
return translationCache.get(locale)!;
}
const translations = await import(`./translations/${locale}.json`);
translationCache.set(locale, translations.default);
return translations.default;
}
export function I18nProvider({
children,
initialLocale = defaultLocale
}: {
children: React.ReactNode;
initialLocale?: Locale;
}) {
const [locale, setLocaleState] = useState<Locale>(initialLocale);
const [translations, setTranslations] = useState<TranslationKeys | null>(null);
const setLocale = useCallback(async (newLocale: Locale) => {
if (!locales.includes(newLocale)) return;
const newTranslations = await loadTranslations(newLocale);
setTranslations(newTranslations);
setLocaleState(newLocale);
// Persist preference
document.cookie = `locale=${newLocale};path=/;max-age=31536000`;
document.documentElement.lang = newLocale;
}, []);
const t = useCallback(<K extends keyof TranslationKeys>(
namespace: K,
key: keyof TranslationKeys[K],
params?: Record<string, string | number>
): string => {
if (!translations) return String(key);
let text = translations[namespace]?.[key] as string || String(key);
if (params) {
Object.entries(params).forEach(([k, v]) => {
text = text.replace(new RegExp(`{{${k}}}`, 'g'), String(v));
});
}
return text;
}, [translations]);
const formatDate = useCallback((date: Date, options?: Intl.DateTimeFormatOptions) => {
return new Intl.DateTimeFormat(locale, options).format(date);
}, [locale]);
const formatNumber = useCallback((num: number, options?: Intl.NumberFormatOptions) => {
return new Intl.NumberFormat(locale, options).format(num);
}, [locale]);
const formatCurrency = useCallback((amount: number, currency = 'USD') => {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency,
}).format(amount);
}, [locale]);
return (
<I18nContext.Provider value={{ locale, setLocale, t, formatDate, formatNumber, formatCurrency }}>
{children}
</I18nContext.Provider>
);
}
export function useI18n() {
const context = useContext(I18nContext);
if (!context) throw new Error('useI18n must be used within I18nProvider');
return context;
}
```
## Next.js App Router Integration
```typescript
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { locales, defaultLocale } from './lib/i18n/config';
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
// Check if pathname already has locale
const pathnameHasLocale = locales.some(
locale => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (pathnameHasLocale) return;
// Detect preferred locale
const cookieLocale = request.cookies.get('locale')?.value;
const acceptLanguage = request.headers.get('accept-language');
let locale = defaultLocale;
if (cookieLocale && locales.includes(cookieLocale as any)) {
locale = cookieLocale as any;
} else if (acceptLanguage) {
const preferred = acceptLanguage.split(',')[0].split('-')[0];
if (locales.includes(preferred as any)) {
locale = preferred as any;
}
}
return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url));
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
```
## Best Practices
1. **Type Safety**: Use TypeScript for compile-time translation key validation
2. **Lazy Loading**: Load translations dynamically to reduce initial bundle size
3. **Pluralization**: Handle plural forms correctly for each locale
4. **RTL Support**: Implement right-to-left layout support for Arabic, Hebrew
5. **Date/Number Formatting**: Use Intl APIs for locale-aware formatting
6. **SEO**: Include hreflang tags and localized metadata
7. **Testing**: Create translation coverage tests to catch missing keys
Google Antigravity's Gemini 3 AI understands i18n patterns and can help generate translations while maintaining context and cultural appropriateness across languages.This i18n prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their i18n implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For i18n projects, consider mentioning your framework version, coding style, and any specific libraries you're using.