CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-aria--i18n

Comprehensive internationalization support for React applications with locale-aware hooks and utilities

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

server-support.mddocs/

Server-Side Rendering Support

Components and utilities for server-side localization with client hydration support, enabling seamless internationalization in SSR applications.

Capabilities

PackageLocalizationProvider Component

Server-only component that injects localized strings into the initial HTML for client-side hydration.

/**
 * A PackageLocalizationProvider can be rendered on the server to inject the localized strings
 * needed by the client into the initial HTML.
 * @param props - Configuration for package localization
 * @returns JSX.Element for server-side rendering or null on client
 */
function PackageLocalizationProvider(props: PackageLocalizationProviderProps): JSX.Element | null;

interface PackageLocalizationProviderProps {
  /** The target locale for the injected strings */
  locale: string;
  /** Package localization strings organized by package name */
  strings: PackageLocalizedStrings;
  /** Optional CSP nonce for inline script security */
  nonce?: string;
}

type PackageLocalizedStrings = {
  [packageName: string]: Record<string, LocalizedString>;
};

Usage Examples:

// Server-side usage (Next.js, Express, etc.)
import { PackageLocalizationProvider } from "@react-aria/i18n/server";

const localizationStrings = {
  "@myapp/components": {
    "welcome": "Welcome to our application",
    "login": "Log in",
    "logout": "Log out"
  },
  "@myapp/forms": {
    "required": "This field is required",
    "invalid_email": "Please enter a valid email"
  }
};

function ServerApp({ locale, nonce }: { locale: string; nonce?: string }) {
  return (
    <html>
      <head>
        <PackageLocalizationProvider
          locale={locale}
          strings={localizationStrings}
          nonce={nonce}
        />
      </head>
      <body>
        <div id="root">
          {/* Your app content */}
        </div>
      </body>
    </html>
  );
}

// Next.js integration example
import { GetServerSideProps } from "next";

export const getServerSideProps: GetServerSideProps = async (context) => {
  const locale = context.locale || "en-US";
  
  // Load localization strings for the specific locale
  const strings = await loadLocalizationStrings(locale);
  
  return {
    props: {
      locale,
      strings
    }
  };
};

function MyPage({ locale, strings }: { locale: string; strings: PackageLocalizedStrings }) {
  return (
    <>
      <Head>
        <PackageLocalizationProvider 
          locale={locale}
          strings={strings}
        />
      </Head>
      <main>
        {/* Your page content */}
      </main>
    </>
  );
}

// Express.js integration example
import express from "express";
import { renderToString } from "react-dom/server";

app.get("*", (req, res) => {
  const locale = req.headers["accept-language"]?.split(",")[0] || "en-US";
  const strings = getLocalizationStrings(locale);
  
  const html = renderToString(
    <PackageLocalizationProvider 
      locale={locale} 
      strings={strings}
    />
  );
  
  res.send(`
    <!DOCTYPE html>
    <html>
      <head>${html}</head>
      <body>
        <div id="root">${/* app content */}</div>
      </body>
    </html>
  `);
});

getPackageLocalizationScript Function

Utility function that generates the script content for injecting localized strings into HTML.

/**
 * Returns the content for an inline <script> tag to inject localized strings into initial HTML.
 * @param locale - The target locale string
 * @param strings - Package localization strings to inject
 * @returns String content for inline script tag
 */
function getPackageLocalizationScript(locale: string, strings: PackageLocalizedStrings): string;

Usage Examples:

import { getPackageLocalizationScript } from "@react-aria/i18n/server";

// Manual script injection
function manualScriptInjection() {
  const locale = "es-ES";
  const strings = {
    "@myapp/ui": {
      "save": "Guardar",
      "cancel": "Cancelar",
      "delete": "Eliminar"
    }
  };
  
  const scriptContent = getPackageLocalizationScript(locale, strings);
  
  // Use with template engines
  const html = `
    <!DOCTYPE html>
    <html>
      <head>
        <script>${scriptContent}</script>
      </head>
      <body>
        <!-- App content -->
      </body>
    </html>
  `;
  
  return html;
}

// Custom server rendering with security headers
function secureScriptInjection(nonce: string) {
  const locale = "fr-FR";
  const strings = {
    "@myapp/dashboard": {
      "overview": "Aperçu",
      "settings": "Paramètres",
      "profile": "Profil"
    }
  };
  
  const scriptContent = getPackageLocalizationScript(locale, strings);
  
  return `<script nonce="${nonce}">${scriptContent}</script>`;
}

// Integration with build-time optimization
function buildTimeOptimization() {
  const supportedLocales = ["en-US", "es-ES", "fr-FR", "de-DE"];
  const allStrings = loadAllLocalizationStrings();
  
  // Pre-generate scripts for each locale
  const precompiledScripts = supportedLocales.reduce((acc, locale) => {
    const localeStrings = filterStringsByLocale(allStrings, locale);
    acc[locale] = getPackageLocalizationScript(locale, localeStrings);
    return acc;
  }, {} as Record<string, string>);
  
  // Save to build artifacts for runtime use
  return precompiledScripts;
}

Server-Side Locale Detection

Utilities for detecting and handling locales in server environments.

Common Patterns:

// Express.js locale detection
function detectLocaleFromRequest(req: express.Request): string {
  // Priority: URL param > Accept-Language header > default
  const urlLocale = req.query.locale as string;
  const headerLocale = req.headers["accept-language"]?.split(",")[0];
  
  return urlLocale || headerLocale || "en-US";
}

// Next.js automatic locale detection
export const getServerSideProps: GetServerSideProps = async ({ locale, req }) => {
  // Next.js automatically detects locale from routing or headers
  const detectedLocale = locale || "en-US";
  
  const strings = await loadStringsForLocale(detectedLocale);
  
  return {
    props: {
      locale: detectedLocale,
      strings
    }
  };
};

// Custom locale validation and fallback
function validateAndFallbackLocale(requestedLocale: string): string {
  const supportedLocales = ["en-US", "es-ES", "fr-FR", "de-DE"];
  const normalizedLocale = requestedLocale.toLowerCase();
  
  // Exact match
  if (supportedLocales.includes(requestedLocale)) {
    return requestedLocale;
  }
  
  // Language-only fallback (e.g., "es" -> "es-ES")
  const languageOnly = requestedLocale.split("-")[0];
  const languageMatch = supportedLocales.find(locale => 
    locale.startsWith(languageOnly)
  );
  
  return languageMatch || "en-US";
}

Hydration Considerations

Important considerations for client-side hydration with server-injected localization.

Best Practices:

// Client-side hydration handling
import { I18nProvider, useLocalizedStringFormatter } from "@react-aria/i18n";

function ClientApp({ serverLocale }: { serverLocale: string }) {
  // Use server locale initially to prevent hydration mismatches
  const [locale, setLocale] = useState(serverLocale);
  
  useEffect(() => {
    // After hydration, can update to browser preference if desired
    const browserLocale = navigator.language;
    if (browserLocale !== serverLocale) {
      // Optionally update locale based on user preference
      setLocale(browserLocale);
    }
  }, [serverLocale]);
  
  return (
    <I18nProvider locale={locale}>
      <App />
    </I18nProvider>
  );
}

// Preventing hydration warnings with SSR-safe components
function SSRSafeLocaleDisplay() {
  const [isClient, setIsClient] = useState(false);
  const { locale } = useLocale();
  
  useEffect(() => {
    setIsClient(true);
  }, []);
  
  if (!isClient) {
    // Return server-safe content
    return <span>Loading locale...</span>;
  }
  
  return <span>Current locale: {locale}</span>;
}

// Error boundary for localization failures
class LocalizationErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, errorInfo) {
    console.error("Localization error:", error, errorInfo);
  }
  
  render() {
    if (this.state.hasError) {
      return <div>Localization failed. Falling back to default content.</div>;
    }
    
    return this.props.children;
  }
}

Performance Optimization

Techniques for optimizing server-side localization performance.

// String compression and caching
const localizationCache = new Map<string, PackageLocalizedStrings>();

function getCachedStrings(locale: string): PackageLocalizedStrings {
  if (!localizationCache.has(locale)) {
    const strings = loadLocalizationStrings(locale);
    localizationCache.set(locale, strings);
  }
  
  return localizationCache.get(locale)!;
}

// Lazy loading of locale strings
async function lazyLoadStrings(locale: string, packages: string[]) {
  const promises = packages.map(pkg => 
    import(`./locales/${locale}/${pkg}.json`)
  );
  
  const results = await Promise.all(promises);
  
  return packages.reduce((acc, pkg, index) => {
    acc[pkg] = results[index].default;
    return acc;
  }, {} as PackageLocalizedStrings);
}

// Build-time string optimization
function optimizeStringsForProduction(strings: PackageLocalizedStrings) {
  // Remove developer comments and descriptions
  const optimized = {};
  
  for (const [pkg, pkgStrings] of Object.entries(strings)) {
    optimized[pkg] = {};
    for (const [key, value] of Object.entries(pkgStrings)) {
      if (typeof value === "string") {
        optimized[pkg][key] = value;
      } else {
        // Remove description, keep only message
        optimized[pkg][key] = value.message;
      }
    }
  }
  
  return optimized as PackageLocalizedStrings;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-aria--i18n

docs

context-locale.md

date-time-formatting.md

index.md

number-list-formatting.md

server-support.md

string-localization.md

tile.json