React
Next.js
Internacionalização
i18n
Frontend

Internationalisierungs-Good Practices (i18n) in React und Next.js im Jahr 2025

Internationalisierungs-Good Practices (i18n) in React und Next.js im Jahr 2025

In einer zunehmend vernetzten digitalen Welt ist die Entwicklung von Webanwendungen für globale Benutzer kein Unterscheidungsmerkmal mehr, sondern eine Notwendigkeit. Die Internationalisierung (i18n) ist zu einem entscheidenden Bestandteil der modernen Anwendungsentwicklung geworden und ermöglicht es Ihrem Produkt, unterschiedliche Zielgruppen unabhängig von Sprache, Region oder kulturellen Vorlieben zu erreichen.

In diesem Artikel werden wir Best Practices, Tools und Strategien für die Implementierung einer effektiven Internationalisierung in React- und Next.js-Anwendungen im Jahr 2025 untersuchen und praktische Beispiele und Lösungen für häufige Herausforderungen bereitstellen.

Grundlagen der Internationalisierung

Was ist i18n und warum ist es wichtig?

Der Begriff „i18n“ ist eine Abkürzung für „Internationalisierung“ (der Buchstabe „i“, gefolgt von 18 Buchstaben und endend mit „n“). Dabei handelt es sich um den Prozess des Entwurfs und der Entwicklung von Softwareanwendungen, die ohne technische oder Codeänderungen an verschiedene Sprachen und Regionen angepasst werden können.

Im Jahr 2025 wird die Bedeutung von i18n durch mehrere Faktoren verstärkt:

  1. Globale Reichweite: Anwendungen mit mehrsprachiger Unterstützung können internationale Märkte erreichen und ihre Benutzerbasis erweitern.
  2. Benutzererfahrung: Benutzer fühlen sich wohler und engagierter, wenn sie mit Anwendungen in ihrer Muttersprache interagieren.
  3. Einhaltung gesetzlicher Vorschriften: In vielen Ländern gibt es gesetzliche Anforderungen an digitale Systeme zur Unterstützung lokaler Sprachen.
  4. Wettbewerbsvorteil: Gut internationalisierte Anwendungen stechen auf wettbewerbsintensiven globalen Märkten hervor.

Unterschied zwischen i18n, l10n und g11n

Es ist wichtig, den Unterschied zwischen den in diesem Bereich häufig verwendeten Begriffen zu verstehen:

  • Internationalisierung (i18n): Prozess des Entwurfs und der Entwicklung eines Produkts, damit es an verschiedene Sprachen und Regionen angepasst werden kann.
  • Lokalisierung (l10n): Prozess der Anpassung eines internationalisierten Produkts an einen bestimmten Standort oder Markt, einschließlich der Übersetzung von Texten und der Anpassung kultureller Elemente.
  • Globalisierung (g11n): Geschäftsstrategie, die sowohl i18n als auch l10n abdeckt und alle Aspekte der Einführung eines Produkts auf globale Märkte berücksichtigt.

Moderne Bibliotheken und Tools für i18n in React

i18n-Ökosystem im Jahr 2025

Das Internationalisierungsökosystem für React hat sich in den letzten Jahren erheblich weiterentwickelt. Hier sind die beliebtesten und fortschrittlichsten Bibliotheken im Jahr 2025:

1. React-i18next

Der react-i18next ist nach wie vor eine der robustesten und beliebtesten Lösungen und wird weiterentwickelt, um den modernen Anforderungen gerecht zu werden:

// Configuração básica do react-i18next em 2025 import i18n from 'i18next'; import { initReactI18next, useTranslation } from 'react-i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import Backend from 'i18next-http-backend'; i18n // Carregamento sob demanda de traduções .use(Backend) // Detecção automática de idioma .use(LanguageDetector) // Integração com React .use(initReactI18next) .init({ fallbackLng: 'pt-BR', supportedLngs: ['pt-BR', 'en-US', 'es', 'fr', 'zh-CN'], // Novo em 2025: Detecção avançada de idioma com preferências de usuário detection: { order: ['localStorage', 'navigator', 'querystring', 'cookie'], caches: ['localStorage'], cookieExpirationDate: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365), lookupQuerystring: 'lng', lookupCookie: 'i18n', }, // Novo em 2025: Cache inteligente com estratégia adaptativa backend: { loadPath: '/locales//.json', requestOptions: { cache: 'smart-default', // Nova estratégia de cache adaptativa }, }, interpolation: { escapeValue: false, // React já escapa por padrão format: function(value, format, lng) { // Novo suporte para formatação avançada if (format === 'uppercase') return value.toUpperCase(); if (format === 'currency') return new Intl.NumberFormat(lng, { style: 'currency', currency: 'BRL' }).format(value); return value; } }, // Novo em 2025: Análise de uso de traduções para otimização telemetry: { enabled: process.env.NODE_ENV === 'development', endpoint: '/api/i18n-telemetry', sampleRate: 0.1 } }); export default i18n;

2. ICU-Format mit React-Intl

Das ICU-Format (International Components for Unicode) hat sich zum vorherrschenden Standard für den Umgang mit internationalisierten Texten entwickelt:

// Exemplo usando react-intl com sintaxe ICU moderna import React from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; function ProductDetails({ product, inventory, lastUpdated }) { const intl = useIntl(); return ( <div className="product-card"> <h2>{product.name}</h2> {/* Pluralização avançada */} <FormattedMessage id="product.inventory" defaultMessage="{inventory, plural, =0 {Fora de estoque} one {Última unidade disponível!} other {# unidades em estoque}}" values= /> {/* Formatação de data relativa */} <FormattedMessage id="product.lastUpdated" defaultMessage="Atualizado {lastUpdated, relativeTime, style=long}" values= /> {/* Formatação de valores variáveis dependentes de idioma */} <p> {intl.formatMessage( { id: 'product.price', defaultMessage: 'Preço: {price, number, currency}' }, { price: product.price } )} </p> {/* Formatação condicional com seleção */} <FormattedMessage id="product.status" defaultMessage="{status, select, new {Novo} sale {Promoção} limited {Edição limitada} other {Regular}}" values= /> </div> ); }

3. LinguiJS: Eine leistungsstarke Alternative

LinguiJS erfreut sich aufgrund seiner Einfachheit und Leistung großer Beliebtheit:

// Exemplo com Lingui v5 (versão 2025) import React from 'react'; import { Trans, Plural, t } from '@lingui/macro'; function ShoppingCart({ items, totalPrice, lastUpdated }) { return ( <div className="shopping-cart"> <h2><Trans id="cart.title">Seu Carrinho</Trans></h2> <Plural value={items.length} zero={<Trans id="cart.empty">Seu carrinho está vazio</Trans>} one={<Trans id="cart.oneItem">1 item no carrinho</Trans>} other={<Trans id="cart.items">{items.length} itens no carrinho</Trans>} /> {items.map(item => ( <div key={item.id} className="cart-item"> <span>{item.name}</span> <span>{t({ id: 'cart.item.price', message: 'Preço: {price, number, currency}', values: { price: item.price } })}</span> </div> ))} <div className="cart-footer"> <div className="total"> <Trans id="cart.total" values=> Total: {totalPrice, number, currency} </Trans> </div> <div className="updated"> <Trans id="cart.updated" values=> Atualizado em {lastUpdated, date, long} </Trans> </div> </div> </div> ); }

Implementierung von i18n in Next.js

Next.js hat sich als eines der beliebtesten React-Frameworks etabliert und seine Internationalisierungsfähigkeiten haben sich im Jahr 2025 erheblich weiterentwickelt.

Moderne i18n-Konfiguration in Next.js

Der integrierte Ansatz von Next.js für i18n ist robuster geworden:

// next.config.js em 2025 /** @type {import('next').NextConfig} */ const nextConfig = { i18n: { // Idiomas suportados locales: ['pt-BR', 'en-US', 'es', 'fr', 'zh-CN'], // Idioma padrão defaultLocale: 'pt-BR', // Novos recursos em 2025 localeDetection: true, // Detecção automática de idioma automaticLocalePrefix: true, // Novo em 2025 - prefixos de URL simplificados // Domínios específicos por idioma (para SEO otimizado) domains: [ { domain: 'meuapp.com.br', defaultLocale: 'pt-BR', }, { domain: 'myapp.com', defaultLocale: 'en-US', }, { domain: 'miapp.es', defaultLocale: 'es', }, ], // Novo em 2025: estratégia de fallback para conteúdo parcialmente traduzido fallbackStrategy: 'partial', // Padrões de URL que não devem ser traduzidos excludeFromTranslation: [ '/api/*', '/admin/*', '/static/*', ], }, // Outras configurações do Next.js }; module.exports = nextConfig;

Verwenden von Übersetzungen in Server- und Clientkomponenten

Next.js App Router führte eine klare Trennung zwischen Server- und Client-Komponenten ein, die i18n-spezifische Ansätze erfordert:

// Exemplo para componentes Server no Next.js App Router // Em /app/[lang]/layout.tsx import { Locale } from '@/i18n/config'; import { getTranslations } from '@/i18n/server'; export default async function RootLayout({ children, params: { lang } }: { children: React.ReactNode; params: { lang: Locale }; }) { // Obter traduções no servidor const { t } = await getTranslations(lang, 'common'); return ( <html lang={lang}> <body> <header> <h1>{t('site.title')}</h1> <nav> <ul> <li>{t('nav.home')}</li> <li>{t('nav.products')}</li> <li>{t('nav.contact')}</li> </ul> </nav> </header> <main>{children}</main> <footer>{t('site.footer')}</footer> </body> </html> ); } // Para componentes Client 'use client'; import { useTranslation } from '@/i18n/client'; import { useParams } from 'next/navigation'; export default function LanguageSwitcher() { const params = useParams(); const lang = params.lang as Locale; const { t } = useTranslation(lang, 'common'); return ( <div className="language-selector"> <p>{t('language.select')}</p> <select> <option value="pt-BR">{t('language.portuguese')}</option> <option value="en-US">{t('language.english')}</option> <option value="es">{t('language.spanish')}</option> </select> </div> ); }

Implementierung einer Komplettlösung

Um zu zeigen, wie alles zusammenhängt, finden Sie hier eine vollständigere App Router-Implementierung von Next.js:

// Em /i18n/config.ts export const defaultLocale = 'pt-BR'; export const locales = ['pt-BR', 'en-US', 'es', 'fr', 'zh-CN'] as const; export type Locale = typeof locales[number]; // Em /i18n/server.ts import { createInstance } from 'i18next'; import resourcesToBackend from 'i18next-resources-to-backend'; import { initReactI18next } from 'react-i18next/initReactI18next'; import { Locale, defaultLocale } from './config'; export async function getTranslations(locale: Locale, namespace: string) { const i18nInstance = createInstance(); await i18nInstance .use(initReactI18next) .use(resourcesToBackend((language: string, ns: string) => import(`./locales/${language}/${ns}.json`))) .init({ lng: locale, fallbackLng: defaultLocale, supportedLngs: locales, defaultNS: 'common', ns: namespace, fallbackNS: 'common', }); return { t: i18nInstance.getFixedT(locale, namespace), i18n: i18nInstance }; } // Em /middleware.ts - para roteamento e redirecionamento baseado em idioma import { NextRequest, NextResponse } from 'next/server'; import { match as matchLocale } from '@formatjs/intl-localematcher'; import Negotiator from 'negotiator'; import { locales, defaultLocale } from './i18n/config'; function getLocale(request: NextRequest): string { // Simulando cabeçalhos para o negotiator const headers = { 'accept-language': request.headers.get('accept-language') || defaultLocale }; const languages = new Negotiator({ headers }).languages(); // Usar @formatjs/intl-localematcher para escolher o melhor idioma const locale = matchLocale(languages, locales, defaultLocale); return locale; } export function middleware(request: NextRequest) { const pathname = request.nextUrl.pathname; // Verificar se a URL já inclui uma localidade const pathnameHasLocale = locales.some( locale => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` ); if (pathnameHasLocale) return NextResponse.next(); // Redirecionar se a localidade não estiver na URL const locale = getLocale(request); const newUrl = new URL(`/${locale}${pathname}`, request.url); return NextResponse.redirect(newUrl); } export const config = { matcher: [ // Excluir arquivos estáticos e API '/((?!api|_next/static|_next/image|favicon.ico).*)', ], };

Architektonische Entscheidungen, die wichtig sind

Über Bibliotheken hinaus ist eine gute Internationalisierung in erster Linie eine architektonische Entscheidung. Drei Auswahlmöglichkeiten definieren, wie nachhaltig der mehrsprachige Betrieb im Laufe der Zeit sein wird.

Die erste besteht darin, den Inhalt von Anfang an vom Code zu trennen. Zeichenfolgen sollten niemals in Komponenten eingebettet werden. Sie gehören zu versionierten Übersetzungsdateien, die nach Namensräumen organisiert sind, sodass Übersetzer und Entwickler arbeiten können, ohne das Territorium des anderen zu betreten. Die zweite besteht darin, Pluralisierung, Geschlecht und Formatierung von Zahlen, Datumsangaben und Währungen als die Verantwortung der i18n-Bibliothek zu behandeln und nicht als im Code verteilte Bedingungen, da diese Regeln von Sprache zu Sprache auf eine Art und Weise variieren, die nicht mit der Zeichenfolgenverkettung gelöst werden kann. Die dritte besteht darin, auf Routing-Ebene eine klare Strategie für die Spracherkennung, URL-Präfixe und den Fallback für teilweise übersetzte Inhalte zu definieren, um sicherzustellen, dass jeder Benutzer in der richtigen Sprache ankommt, ohne dass dabei Seiten unterbrochen werden.

Im App Router von Next.js bedeutet dies, bewusst zu entscheiden, was auf dem Server übersetzt und was an den Client geliefert wird, und gleichzeitig möglichst viel Übersetzung auf dem Server zu belassen, um das an den Browser gesendete JavaScript zu reduzieren.

Fazit

Internationalisierung ist keine optionale Funktion mehr, sondern Teil der Grundlage jedes Produkts mit globalen Ambitionen. In React und Next.js bietet das 2025-Ökosystem ausgereifte Tools, react-i18next, react-intl mit ICU und LinguiJS, die alles von fortgeschrittener Pluralisierung bis hin zu gebietsschemasensitiver Formatierung abdecken können.

Der Unterschied liegt jedoch selten in der gewählten Bibliothek, sondern in der Disziplin der Architektur: Inhalte vom Code trennen, sprachliche Regeln an diejenigen delegieren, die damit umzugehen wissen, und als erstklassiger Bürger das Sprachrouting gestalten. Teams, die i18n vom ersten Commit an als strategische Entscheidung betrachten, erreichen neue Märkte schneller und mit weniger Nacharbeit als diejenigen, die es auf einen späteren Zeitpunkt verschieben.

Lesen Sie auch