Gemeinsame Strings

So internationalisieren Sie Strings, die in mehreren Komponenten und Dateien verwendet werden

Gemeinsame Strings sind Textwerte, die an mehreren Stellen in Ihrer Anwendung verwendet werden – etwa Navigationslabels, Formularmeldungen oder Konfigurationsdaten. Anstatt die Übersetzungslogik überall zu duplizieren, verwenden Sie msg, um Strings für die Übersetzung zu markieren, und useMessages, um sie zu dekodieren.

Das Problem mit gemeinsam genutzten Inhalten

Betrachten Sie diese Navigationskonfiguration, die in Ihrer gesamten App verwendet wird:

// navData.ts
export const navData = [
  {
    label: 'Startseite',
    description: 'Die Startseite',
    href: '/'
  },
  {
    label: 'Über uns', 
    description: 'Informationen über das Unternehmen',
    href: '/about'
  }
];

Um das zu internationalisieren, müssten Sie in der Regel:

  1. Es in eine Funktion umwandeln, die eine Übersetzungsfunktion entgegennimmt
  2. Jede Verwendung so anpassen, dass die Funktion mit t aufgerufen wird
  3. Die zusätzliche Komplexität in Ihrem Code verwalten

Das verursacht Wartungsaufwand und erschwert die Lesbarkeit Ihres Codes. Die Funktion msg löst das, indem sie ermöglicht, Strings direkt im Code für die Übersetzung zu markieren und sie bei Bedarf zu decodieren.

Schnellstart

Verwenden Sie msg, um Zeichenketten zu markieren, und useMessages, um sie zu dekodieren:

// navData.ts - Strings für Übersetzung markieren
import { msg } from 'gt-react';

export const navData = [
  {
    label: msg('Startseite'),
    description: msg('Die Startseite'), 
    href: '/'
  },
  {
    label: msg('Über uns'),
    description: msg('Informationen über das Unternehmen'),
    href: '/about'
  }
];
// Komponenten-Verwendung - Markierte Strings dekodieren
import { useMessages } from 'gt-react';
import { navData } from './navData';

function Navigation() {
  const m = useMessages();
  
  return (
    <nav>
      {navData.map((item) => (
        <a key={item.href} href={item.href} title={m(item.description)}>
          {m(item.label)}
        </a>
      ))}
    </nav>
  );
}

Funktionsweise von Shared Strings

Das Shared-String-System arbeitet in zwei Phasen:

  1. Markierungsphase: msg codiert Strings mit Übersetzungsmetadaten
  2. Dekodierungsphase: useMessages decodiert und übersetzt die Strings
// msg() kodiert den String mit Metadaten
const encoded = msg('Hello, world!');
console.log(encoded); // "Hello, world!:eyIkX2hhc2giOiJkMjA3MDliZGExNjNlZmM2In0="

// useMessages() dekodiert und übersetzt
const m = useMessages();
const translated = m(encoded); // "Hello, world!" in der Sprache des Benutzers

Encoded strings von msg können nicht direkt verwendet werden – sie müssen mit useMessages decodiert werden.

Komponenten

Verwenden Sie den Hook useMessages:

import { useMessages } from 'gt-react';

const encodedString = msg('Hallo, Welt!');

function MyComponent() {
  const m = useMessages();
  return <div>{m(encodedString)}</div>;
}

Ursprüngliche Strings mit decodeMsg abrufen

Manchmal müssen Sie auf den ursprünglichen String ohne Übersetzung zugreifen, zum Beispiel für Logging, Debugging oder Vergleiche. Verwenden Sie decodeMsg, um den Originaltext zu extrahieren:

import { decodeMsg } from 'gt-react';

const encoded = msg('Hallo, Welt!');
const original = decodeMsg(encoded); // "Hallo, Welt!" (original)
const translated = m(encoded); // "Hallo, Welt!" (in der Sprache des Nutzers)

// Nützlich für Logging oder Debugging
console.log('Original-String:', decodeMsg(encoded));
console.log('Übersetzter String:', m(encoded));

Anwendungsfälle für decodeMsg

  • Entwicklung & Debugging: Ursprüngliche Strings zur Fehleranalyse protokollieren
  • Standardwert-Behandlung: Originaltext verwenden, wenn Übersetzungen fehlschlagen
  • String-Vergleiche: Mit bekannten Originalwerten vergleichen
  • Analytics: Nutzung des Originaltexts nachverfolgen
// Beispiel: Standardwert-Behandlung
function getDisplayText(encodedStr) {
  const m = useMessages();
  try {
    return m(encodedStr);
  } catch (error) {
    console.warn('Übersetzung fehlgeschlagen, verwende Original:', decodeMsg(encodedStr));
    return decodeMsg(encodedStr);
  }
}

Verwendung von Variables

Für Zeichenketten mit dynamischem Inhalt verwenden Sie Platzhalter und übergeben variables:

// String mit Variablen markieren
const items = 100;
export const pricing = [
  {
    name: 'Basic',
    price: 100,
    description: msg('Der Basic-Plan enthält {items} Artikel', { items })
  }
];
// Verwendung in Komponente
function PricingCard() {
  const m = useMessages();
  
  return (
    <div>
      <h3>{pricing[0].name}</h3>
      <p>{m(pricing[0].description)}</p>
    </div>
  );
}

ICU Message Format

Für fortgeschrittenes Formatting verwenden Sie die ICU-Syntax:

const count = 10;
const message = msg('Es {count, plural, =0 {sind keine Artikel} =1 {ist ein Artikel} other {sind {count} Artikel}} im Warenkorb', { count });

Erfahren Sie mehr über das ICU Message Format in der Unicode-Dokumentation.

Beispiele

// config/navigation.ts
import { msg } from 'gt-react';

export const mainNav = [
  {
    label: msg('Startseite'),
    href: '/',
    icon: 'home'
  },
  {
    label: msg('Produkte'),
    href: '/products', 
    icon: 'package'
  },
  {
    label: msg('Über uns'),
    href: '/about',
    icon: 'info'
  }
];

export const footerLinks = [
  {
    title: msg('Unternehmen'),
    links: [
      { label: msg('Über uns'), href: '/about' },
      { label: msg('Karriere'), href: '/careers' },
      { label: msg('Kontakt'), href: '/contact' }
    ]
  },
  {
    title: msg('Support'), 
    links: [
      { label: msg('Hilfe-Center'), href: '/help' },
      { label: msg('Dokumentation'), href: '/docs' },
      { label: msg('API-Referenz'), href: '/api' }
    ]
  }
];
// components/Navigation.tsx
import { useMessages } from 'gt-react';
import { mainNav } from '../config/navigation';

function Navigation() {
  const m = useMessages();
  
  return (
    <nav>
      {mainNav.map((item) => (
        <a key={item.href} href={item.href}>
          <Icon name={item.icon} />
          {m(item.label)}
        </a>
      ))}
    </nav>
  );
}

Formularkonfiguration

// config/forms.ts
import { msg } from 'gt-react';

export const formMessages = {
  placeholders: {
    email: msg('Geben Sie Ihre E-Mail-Adresse ein'),
    password: msg('Geben Sie Ihr Passwort ein'),
    message: msg('Geben Sie hier Ihre Nachricht ein...')
  },
  actions: {
    send: msg('Nachricht senden'),
    save: msg('Änderungen speichern'),
    cancel: msg('Abbrechen')
  },
  validation: {
    required: msg('Dieses Feld ist erforderlich'),
    email: msg('Bitte geben Sie eine gültige E-Mail-Adresse ein'),
    minLength: msg('Mindestens {min} Zeichen erforderlich', { min: 8 }),
    maxLength: msg('Darf {max} Zeichen nicht überschreiten', { max: 100 })
  },
  success: {
    saved: msg('Änderungen erfolgreich gespeichert'),
    sent: msg('Nachricht erfolgreich gesendet'),
    updated: msg('Profil aktualisiert')
  },
  errors: {
    network: msg('Netzwerkfehler – bitte erneut versuchen'),
    server: msg('Serverfehler – bitte wenden Sie sich an den Support'),
    timeout: msg('Zeitüberschreitung bei der Anfrage – bitte erneut versuchen')
  }
};
// components/ContactForm.tsx
import { useMessages } from 'gt-react';
import { formMessages } from '../config/forms';

function ContactForm() {
  const m = useMessages();
  const [errors, setErrors] = useState({});
  
  return (
    <form>
      <input 
        type="email"
        placeholder={m(formMessages.placeholders.email)}
        required
      />
      {errors.email && <span>{m(formMessages.validation.email)}</span>}
      
      <button type="submit">
        {m(formMessages.actions.send)}
      </button>
    </form>
  );
}

Dynamische Inhaltserzeugung

// utils/productData.ts
import { msg } from 'gt-react';

function mockProducts() {
  return [
    { name: 'iPhone 15', company: 'Apple', category: 'Elektronik' },
    { name: 'Galaxy S24', company: 'Samsung', category: 'Elektronik' }
  ];
}

export function getProductData() {
  const products = mockProducts();
  
  return products.map(product => ({
    ...product,
    description: msg('{name} ist ein {category}-Produkt von {company}', {
      name: product.name,
      category: product.category,
      company: product.company
    })
  }));
}
// components/ProductList.tsx
import { useMessages } from 'gt-react';
import { getProductData } from '../utils/productData';

function ProductList() {
  const m = useMessages();
  const products = getProductData();
  
  return (
    <div>
      {products.map(product => (
        <div key={product.name}>
          <h3>{product.name}</h3>
          <p>{m(product.description)}</p>
        </div>
      ))}
    </div>
  );
}

Häufige Probleme

Encoded Strings direkt verwenden

Verwenden Sie die Ausgabe von msg niemals direkt:

// ❌ Falsch - encoded string direkt verwendet
const encoded = msg('Hello, world!');
return <div>{encoded}</div>; // Zeigt encoded string, nicht die Übersetzung

// ✅ Richtig - den String zuerst dekodieren  
const encoded = msg('Hello, world!');
const m = useMessages();
return <div>{m(encoded)}</div>; // Zeigt die korrekte Übersetzung

Dynamische Inhalte in msg()

Strings müssen zur Build-Zeit bekannt sein:

// ❌ Falsch - dynamisches Template-Literal
const name = 'John';
const message = msg(`Hello, ${name}`); // Build-Zeit-Fehler

// ✅ Richtig - verwende variables  
const name = 'John';
const message = msg('Hello, {name}', { name });

Das Entschlüsseln vergessen

Jede msg-Zeichenfolge muss entschlüsselt werden:

// ❌ Dekodierung fehlt
const config = {
  title: msg('Dashboard'),
  subtitle: msg('Willkommen zurück')
};

// Später in der Komponente - Dekodierung vergessen
return <h1>{config.title}</h1>; // Zeigt encoded string

// ✅ Korrekt - beim Verwenden dekodieren
const m = useMessages();
return <h1>{m(config.title)}</h1>; // Zeigt übersetzten Titel

Nächste Schritte

Wie ist dieser Leitfaden?

Gemeinsame Strings