CodeGym /Kurse /ChatGPT Apps /Woher die Locale nehmen: openai/locale, _meta["openai/use...

Woher die Locale nehmen: openai/locale, _meta["openai/userLocation"]

ChatGPT Apps
Level 9 , Lektion 1
Verfügbar

1. Warum es wichtig ist, die Locale von der Plattform zu nutzen – und den Nutzer nicht jedes Mal zu fragen

Geht man Lokalisierung „altmodisch“ an, lautet die Logik meist: ein modales Fenster „Sprache wählen“ anzeigen und das Ergebnis in localStorage speichern. In ChatGPT‑Apps ist der Ansatz anders: Wir haben bereits eine smarte Plattform, und sie liefert großzügig Signale zu Sprache und Region. Wir sollten lernen, diese zu nutzen – und den Nutzer nicht mit überflüssigen Fragen zu belästigen.

ChatGPT fügt in jede Anfrage an Ihre App dem Kontext hinzu:

  • die bevorzugte Locale des Nutzers (Sprache + Region) – im Feld openai/locale / _meta["openai/locale"];
  • die Geolokation/Region des Nutzers – im Feld _meta["openai/userLocation"].

Auf der Widget‑Seite (Frontend) erhalten Sie die locale über window.openai oder einen SDK‑Hook; auf der MCP/Backend‑Seite – über _meta in der MCP‑Anfrage.

Am Ende sieht ein normaler Ablauf so aus: Der Nutzer schreibt „Finde ein Geschenk für meine Mutter bis 50 Euro“. ChatGPT kennt bereits seine locale und userLocation, die Plattform übergibt diese Signale an Ihre App, und Sie:

  • zeigen die UI in einer verständlichen Sprache,
  • laden den richtigen Sprachkatalog,
  • formatieren Preise in der passenden Währung und im passenden Format.

Ohne den separaten Dialog „Übrigens, welche Sprache bevorzugen Sie?“.

2. Signal Nr. 1: openai/locale — Sprache und Region des Nutzers

Was ist das für ein Feld und wie sieht es aus

openai/locale ist ein String im BCP‑47‑Format, das Sie sicher schon gesehen haben: "en", "en-US", "ru", "ru-RU", "uk-UA" usw.

Wichtig ist, dass die Plattform:

  • nur die Sprache senden kann ("en", "ru"),
  • oder Sprache + Region ("en-US", "en-GB", "fr-CA").

BCP‑47 ist ein Standard, mit dem sowohl die Intl-APIs im Browser als auch die meisten i18n‑Bibliotheken hervorragend arbeiten. Das heißt, openai/locale können Sie nahezu direkt in Intl.NumberFormat, in Ihre Übersetzungs‑Engine und in Ihre Tools durchreichen.

Wo ist die Locale im Widget verfügbar

Im benutzerdefinierten UI, das in ChatGPT gerendert wird, stellt das Apps SDK das globale Objekt window.openai bereit, das eine locale enthält.

Typischerweise sieht das so aus (TypeScript, Next.js 16, unser Widget GiftGenius):

// src/app/widgets/gift-widget.tsx
declare global {
  interface Window {
    openai?: { locale?: string };
  }
}

function getOpenAiLocale(): string {
  if (typeof window === "undefined") return "en";
  return window.openai?.locale || "en";
}

In einer echten Anwendung ist es praktischer, einen Hook zu erstellen, der sowohl in der ChatGPT‑Sandbox als auch in Storybook funktioniert:

// src/app/hooks/useOpenAiLocale.ts
import { useEffect, useState } from "react";

export function useOpenAiLocale(defaultLocale: string = "en") {
  const [locale, setLocale] = useState(defaultLocale);

  useEffect(() => {
    if (typeof window === "undefined") return;
    const next = window.openai?.locale || defaultLocale;
    setLocale(next);
  }, [defaultLocale]);

  return locale;
}

Jetzt in jeder Komponente:

import { useOpenAiLocale } from "../hooks/useOpenAiLocale";

export function GiftHeader() {
  const locale = useOpenAiLocale();

  return (
    <h2>
      {/* später kommt hier t('titles.gift_search') */}
      {locale.startsWith("ru") ? "Geschenksuche" : "Gift search"}
    </h2>
  );
}

In Vorlesung 4 lagern wir alle Strings sauber in Wörterbücher aus, aber schon jetzt haben wir die UI an ein echtes Signal der Plattform gebunden und nicht an ein zufälliges navigator.language. Dieser Hook ist sehr spezialisiert; in einem realen Projekt baut man ihn bequem auf einem allgemeineren Mechanismus für den Zugriff auf ChatGPT‑Globals auf – darauf kommen wir weiter unten zurück.

Wo ist die Locale im MCP/Backend verfügbar

Wenn ChatGPT ein MCP‑Tool aufruft, übergibt das SDK _meta["openai/locale"] in der JSON‑RPC‑Anfrage. Auf einem TypeScript‑Server (unser GiftGenius‑MCP) ist das normalerweise im zweiten Argument des Tool‑Handlers verfügbar.

Beispiel:

// src/mcp/server.ts
import { McpServer } from "@openai/mcp-sdk";

const server = new McpServer();

server.registerTool(
  "suggest_gifts",
  {
    title: "Geschenkempfehlungen",
    description: "Schlägt eine Liste von Geschenken basierend auf Präferenzen vor",
    inputSchema: {
      type: "object",
      properties: {
        recipient: { type: "string" },
        budget: { type: "number" }
      },
      required: ["recipient", "budget"]
    }
  },
  async ({ input }, extra) => {
    const locale = extra?._meta?.["openai/locale"] || "en";
    // anschließend kann der richtige Katalog geladen werden
    const gifts = await loadGiftCatalog(locale);
    // ...
    return {
      content: [
        {
          type: "text",
          text: `Found ${gifts.length} gifts for locale ${locale}`
        }
      ],
      structuredContent: { gifts }
    };
  }
);

So „lebt“ die locale durch den gesamten Stack: ChatGPT → Apps SDK → Ihr MCP‑Server.

Insight

Jedes MCP‑Tool auf dem Server hat den Parameter extra, in den der MCP‑Server alle Daten legt, die nicht in das inputSchema passen. Hier ein Beispiel für ein solches Objekt:

{
  sessionId: undefined,			// immer undefined, verwenden Sie `openai/subject` unten
  _meta: {
    'openai/userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36',
    'openai/locale': 'en-US',		// Locale des Nutzerrechners; kann sich von der Sprache im Chat unterscheiden
    'openai/userLocation': {		// recht genaue Nutzerposition
      city: 'London',
      region: 'London City',
      country: 'GB',
      timezone: 'Europe/London',
      latitude: '5.45466',
      longitude: '-0.52380'
    },
    timezone_offset_minutes: -240,	// Zeitzonenversatz in Minuten
    'openai/subject': 'v1/sEtRuS92UEOPNdwzEUZORfeOKf7XSk2KZoIUGfAsb68BzZ8h5FAOgrH'	// dies ist die sessionId
  },
  authInfo: undefined,
  requestId: 1,
  requestInfo: {
    headers: {
      accept: 'application/json, text/event-stream',
      'accept-encoding': 'gzip, deflate, br, zstd',
      'access-control-allow-headers': '*',
      'access-control-allow-methods': 'GET,POST,PUT,DELETE,OPTIONS',
      'access-control-allow-origin': '*',
      'content-length': '542',
      'content-type': 'application/json',
      host: 'test.ngrok.app',					// ursprüngliche Domain der Anwendung
      'mcp-protocol-version': '2025-11-25',	
      traceparent: '00-69399d3a000000004fb8cc13dc3a2203-8748a8698107eb34-00',
      tracestate: 'dd=s:-1;p:01514e334c1ccef5;t.dm:-3',
      'user-agent': 'openai-mcp/1.0.0',
      'x-datadog-parent-id': '6089244476286233754',
      'x-datadog-sampling-priority': '-1',
      'x-datadog-tags': '_dd.p.tid=69399c3a00000000,_dd.p.dm=-3',
      'x-datadog-trace-id': '5744565710382309891',
      'x-forwarded-for': '199.210.139.232',
      'x-forwarded-host': 'test.ngrok.app',
      'x-forwarded-port': '3001',
      'x-forwarded-proto': 'https'
    }
  },
}

Vielleicht hat einen Teil der Header hier ngrock gesetzt, aber interessante Daten gibt es trotzdem viele.

3. Signal Nr. 2: _meta["openai/userLocation"] — Geografie des Nutzers

Struktur und Bedeutung

_meta["openai/userLocation"] ist ein Objekt mit Geo‑Informationen: Land, Region, Stadt, Zeitzone und sogar Koordinaten. Ungefähr so:

{
  "city": "London",
  "region": "England",
  "country": "GB",
  "timezone": "Europe/London",
  "latitude": 51.5074,
  "longitude": -0.1278
}

Die wichtigsten Felder, die Sie in GiftGenius wirklich verwenden werden:

  • country — zweibuchstabiger ISO‑Ländercode, entscheidend für Sortiment und Währung;
  • timezone — nützlich für Datums-/Zeitformate und Erinnerungen.

Insight

Experimentell bestätigt — die Bestimmung von userLocation funktioniert sehr zuverlässig. Die Daten kommen bei jedem Aufruf des MCP‑Tools über den Parameter extra._meta["openai/userLocation"]. Sie können sich bei der Entwicklung Ihrer Anwendungen darauf verlassen.

Wie man userLocation in MCP‑Tools verwendet

Auf dem MCP‑Server liegt userLocation in _meta["openai/userLocation"] neben _meta["openai/locale"].

Erweitern wir das Beispiel unseres Tools:

server.registerTool(
  "suggest_gifts",
  { /* Schema wie oben */ },
  async ({ input }, extra) => {
    const meta = extra?._meta ?? {};
    const locale = (meta["openai/locale"] as string) || "en";
    const userLocation = meta["openai/userLocation"] as
      | { country?: string; city?: string }
      | undefined;

    const country = userLocation?.country || "US";

    const gifts = await loadGiftCatalog(locale, country);

    return {
      content: [
        {
          type: "text",
          text: `Found ${gifts.length} gifts for locale=${locale}, country=${country}`
        }
      ],
      structuredContent: { gifts }
    };
  }
);

Die Funktion loadGiftCatalog(locale, country) kann bereits:

  • die passende JSON‑Datei wählen: gift_catalog.en-US.json, gift_catalog.ru-RU.json,
  • Produkte herausfiltern, die in dieses Land nicht geliefert werden können,
  • die Basiswährung wählen.

Später in den Commerce‑Modulen wählen Sie auf Basis von country Steuerregeln und mappen auf die richtigen SKUs, aber architektonisch stützen Sie sich weiterhin auf dasselbe Signal — country.

Wie userLocation die Locale ergänzt

Klassisches Beispiel:

locale = "en", userLocation.country = "DE".

Die Logik kann so aussehen:

  • UI und Prompts — auf Englisch (respect locale);
  • Währungs- und Preisformat — Euro, weil der Nutzer physisch in Deutschland ist;
  • Geschenkliste — nur Artikel, die nach DE lieferbar sind.

In GiftGenius lässt sich das mit einer kleinen Helper‑Funktion ausdrücken:

export function deriveCurrency(locale: string, country?: string): string {
  if (country === "DE") return "EUR";
  if (country === "JP") return "JPY";   
  if (locale === "zh_CN") return "CNY"; 
  return "USD";
}

Und sowohl im Backend als auch im Frontend zur Preisformatierung verwenden:

const currency = deriveCurrency(locale, country);
const formatted = new Intl.NumberFormat(locale, {
  style: "currency",
  currency
}).format(price);

Im Backend haben wir bereits gelernt, locale und country zur Auswahl von Katalog und Währung zu verwenden. Wichtig ist als Nächstes, dieselben Signale sauber bis ins UI im Widget zu tragen, damit der Nutzer Texte und Preise im erwarteten Format sieht.

4. Wie man Locale und userLocation im GiftGenius‑Widget erhält

Wir haben bereits gesehen, wie locale und userLocation auf der MCP‑Seite leben und Kataloge und Währung beeinflussen. Jetzt schauen wir uns an, wie wir die locale sauber ins GiftGenius‑Widget holen und direkt im React‑UI verwenden.

Wichtig: Im Widget haben wir direkten Zugriff nur auf die locale (über window.openai und SDK‑Hooks). userLocation lebt in _meta und wird auf der MCP/Backend‑Seite verwendet — damit haben wir oben bereits gearbeitet.

Im Apps SDK gibt es neben dem „rohen“ window.openai Utilities in Form von React‑Hooks. In der Dokumentation werden Hooks wie useOpenAiGlobal("locale") beschrieben, die Werte des globalen ChatGPT‑Kontexts in React‑Komponenten ziehen.

Wir modellieren diesen Hook selbst, damit klar wird, was unter der Haube passiert.

Grundlegender Hook useOpenAiGlobal

Zuvor haben wir den spezialisierten useOpenAiLocale erstellt. In der Praxis ist es bequemer, einen universellen Hook für den Zugriff auf ChatGPT‑Globals zu haben — darauf lassen sich useOpenAiLocale und weitere Wrapper leicht aufbauen. Stellen wir uns so einen Hook vor:

// src/app/hooks/useOpenAiGlobal.ts
import { useEffect, useState } from "react";

type OpenAiGlobals = {
  locale?: string;
  // hier später z. B. theme, userAgent usw. ergänzen
};

export function useOpenAiGlobal<K extends keyof OpenAiGlobals>(
  key: K,
  fallback?: NonNullable<OpenAiGlobals[K]>
): NonNullable<OpenAiGlobals[K]> {
  const [value, setValue] = useState<NonNullable<OpenAiGlobals[K]>>(
    (fallback ?? "") as NonNullable<OpenAiGlobals[K]>
  );

  useEffect(() => {
    if (typeof window === "undefined") return;
    const globals = (window.openai || {}) as OpenAiGlobals;
    const next = globals[key] ?? fallback;
    if (next !== undefined) {
      setValue(next as NonNullable<OpenAiGlobals[K]>);
    }
  }, [key, fallback]);

  return value;
}

Jetzt liefert useOpenAiGlobal("locale", "en") den aktuellen Wert von locale mit dem Standardwert "en".

Einsatz im GiftGenius‑Widget

Erstellen wir eine kleine Komponente, die eine lokalisierte Begrüßung und die aktuelle Locale zu Debug‑Zwecken anzeigt:

// src/app/widgets/GiftWelcome.tsx
"use client";

import React from "react";
import { useOpenAiGlobal } from "../hooks/useOpenAiGlobal";

export function GiftWelcome() {
  const locale = useOpenAiGlobal("locale", "en");

  const greeting =
    locale.startsWith("ru") || locale.startsWith("uk")
      ? "Hallo! Ich helfe dir, ein tolles Geschenk zu finden."
      : "Hi! I’ll help you find a great gift.";

  return (
    <div>
      <p>{greeting}</p>
      <small style={{ opacity: 0.6 }}>Debug locale: {locale}</small>
    </div>
  );
}

Noch keine Wörterbücher und keine i18n‑Bibliotheken — das kommt später. Wichtig ist jetzt, dass wir die Sprache ehrlich aus ChatGPT nehmen können, statt aus zufälligen Annahmen.

5. Wann man den Nutzer explizit nach der Sprache fragen sollte

Wenn openai/locale und userLocation so gut sind, kann man den Nutzer dann überhaupt nie fragen, in welcher Sprache er arbeiten möchte? Leider muss man es manchmal doch tun.

Wann die Signale nicht ausreichen

Es gibt einige typische Situationen:

  • Der ChatGPT‑Account ist englischsprachig (locale = "en"), der Nutzer schreibt aber auf Russisch. Das Modell antwortet auf Russisch, aber Ihre UI ist auf Englisch.
  • Der Nutzer ist in Deutschland (userLocation.country = "DE"), locale = "en", und Sie können sowohl eine deutsche als auch eine englische Oberfläche anbieten.
  • Die Anwendung ist kritisch für die Kommunikationssprache: Psychotherapie, Rechtsberatung, Bildung. Dort ist die Genauigkeit des Verständnisses wichtiger als der Komfort des Autodeteks.

In solchen Fällen ist es angemessen, einmal zu Beginn kurz und höflich zu fragen und die Auswahl danach zu merken.

Wie man unaufdringlich nach der Sprache fragt

Formulieren Sie die Frage in der Regel so einfach und visuell wie möglich, zum Beispiel:

  • „Welche Sprache ist für Sie bequemer: Englisch oder Russisch?“
  • „Wir haben Ihre Sprache als Englisch erkannt. Möchten Sie zu einer anderen wechseln?“

In der ChatGPT‑App geht das auf zwei Arten:

  • Über die Widget‑UI: einen kleinen Sprachschalter oben rendern.
  • Über eine Follow‑up‑Nachricht im Chat im Namen der App: eine Text‑Follow‑up‑Frage senden und die Antwort verarbeiten.

Code: einfache Sprachauswahl in GiftGenius

Erstellen wir eine Schalter‑Komponente, die:

  • die Startsprache aus der locale nimmt,
  • dem Nutzer ru oder en zur Auswahl stellt,
  • die Auswahl im Zustand des Widgets speichert (vorerst im React‑State).
// src/app/widgets/LanguageSwitcher.tsx
"use client";

import React, { useState, useEffect } from "react";
import { useOpenAiGlobal } from "../hooks/useOpenAiGlobal";

type SupportedLocale = "en" | "ru";

export function LanguageSwitcher(props: {
  onChange?: (locale: SupportedLocale) => void;
}) {
  const initialLocale = useOpenAiGlobal("locale", "en");
  const [locale, setLocale] = useState<SupportedLocale>("en");

  useEffect(() => {
    const normalized: SupportedLocale = initialLocale.startsWith("ru")
      ? "ru"
      : "en";
    setLocale(normalized);
    props.onChange?.(normalized);
  }, [initialLocale, props]);

  const handleChange = (next: SupportedLocale) => {
    setLocale(next);
    props.onChange?.(next);
  };

  return (
    <div style={{ marginBottom: 8 }}>
      <span style={{ marginRight: 8 }}>
        {locale === "ru" ? "Sprache:" : "Language:"}
      </span>
      <button
        type="button"
        onClick={() => handleChange("en")}
        style={{ fontWeight: locale === "en" ? "bold" : "normal" }}
      >
        EN
      </button>
      <button
        type="button"
        onClick={() => handleChange("ru")}
        style={{ fontWeight: locale === "ru" ? "bold" : "normal", marginLeft: 4 }}
      >
        RU
      </button>
    </div>
  );
}

Und im Haupt‑Widget von GiftGenius können Sie Texte/Wörterbuch bereits nach selectedLocale auswählen, anstatt nach „rohen“ Daten von ChatGPT.

In zukünftigen Vorlesungen ersetzen Sie den lokalen State durch eine robustere Speicherung (zum Beispiel geben Sie die gewählte Sprache an MCP / Gateway über _meta["openai/subject"] weiter), aber das Muster bleibt das gleiche.

6. Wie man Locale und userLocation ans Backend übergibt und speichert

Die Signale kommen „von oben“ aus ChatGPT, aber damit ist die Arbeit nicht getan. Diese Daten müssen weiter an Ihre Tools und Services gegeben, unterwegs nicht verloren und das Modell nicht gezwungen werden, die Sprache erneut zu erraten.

Explizites Feld locale in den Tool‑Argumenten

Die zuverlässigste Methode ist, locale (und bei Bedarf country) als eigene Felder in das inputSchema des Tools aufzunehmen. Dann erhält das Modell ein klares Signal: „Dieses Feld ist auszufüllen.“

server.registerTool(
  "suggest_gifts",
  {
    title: "Gift suggestions",
    description: "Suggest gifts based on recipient and budget",
    inputSchema: {
      type: "object",
      properties: {
        recipient: { type: "string" },
        budget: { type: "number" },
        locale: {
          type: "string",
          description: "Current user UI locale, BCP-47 (e.g. en-US, fr-FR)"
        },
        country: {
          type: "string",
          description: "ISO country code (e.g. US, DE)"
        }
      },
      required: ["recipient", "budget"]
    }
  },
  async ({ input }, extra) => {
    // Falls das Modell locale/country nicht gesetzt hat, aus _meta absichern:
    const meta = extra?._meta ?? {};
    const locale = input.locale || (meta["openai/locale"] as string) || "en";
    const country =
      input.country ||
      (meta["openai/userLocation"] as any)?.country ||
      "US";

    // ...
  }
);

Das verringert die „Magie“ im Server: Er sieht klar die Argumente, die das Modell zu verwenden gedenkt.

Speichern der Locale auf Sitzungs-/Benutzerebene

In einer Architektur mit MCP Gateway (spätere Module) ist es üblich, „Client‑Zustand“ zu speichern: locale, currency, Präferenzen. Für uns ist wichtig: Einmal die Signale von ChatGPT gelesen — anschließend als Teil des Sitzungszustands verwenden, nicht jedes Mal neu bestimmen.

Ein fiktiver Pseudocode:

// gateway.ts
const sessionState = new Map<string, { locale: string; country?: string }>();

function onMcpRequest(request: any) {
  const subject = request._meta?.["openai/subject"]; // anonyme Benutzer-ID
  const locale = request._meta?.["openai/locale"] || "en";
  const country = request._meta?.["openai/userLocation"]?.country;

  if (subject) {
    sessionState.set(subject, { locale, country });
  }

  // anschließend locale/country an den konkreten MCP-Server weitergeben
}

Im Rahmen dieser Vorlesung müssen Sie kein Gateway implementieren; es genügt zu verstehen, dass locale und userLocation gute Kandidaten für solchen „Sitzungszustand“ sind.

Insight

Experimentelle Daten: request._meta?.["openai/locale"] zeigt die aktuell eingestellte Locale des Nutzers. Die Gesprächssprache kann als Tool‑Parameter über inputSchema erfasst werden.

Ich hatte auf meinem Rechner die EN‑Locale eingestellt, habe aber mit ChatGPT auf Deutsch (DE) kommuniziert. Ergebnis:

  • request._meta?.["openai/locale"] war EN
  • locale, als Tool‑Parameter über inputSchema erhalten, war DE

7. Locale vs. automatische Spracherkennung anhand des Textes

Entwickler sind manchmal versucht: „Wir erkennen einfach die Sprache aus dem Text, LLM kann doch alles.“ In der Praxis ist das fast immer schlechter, als sich auf openai/locale zu stützen.

Die Gründe sind recht bodenständig:

  • Nutzer können in einer Sprachmischung schreiben;
  • feine Unterschiede (uk‑UA vs. ru‑RU) lassen sich aus einer einzelnen Nachricht schlecht erkennen;
  • ChatGPT hat diese Arbeit bereits für Sie erledigt und die locale geliefert.

Autodetektion ist als Fallback nützlich, falls openai/locale in einer seltsamen Form kommt oder fehlt (was inzwischen selten ist), aber darauf die Hauptlogik aufzubauen, ist keine gute Idee. Grobe Regel:

  • zuerst betrachten wir openai/locale als „Quelle der Wahrheit“;
  • dann berücksichtigen wir userLocation (Währung, Sortiment);
  • und nur in ganz strittigen Fällen schauen wir zusätzlich auf die Sprache der letzten Nachricht.

8. Verschiedene Kombinationen von Locale und userLocation: Szenariotabelle

Zur Festigung schauen wir uns an, wie sich GiftGenius in unterschiedlichen Szenarien verhalten sollte.

Szenario locale userLocation.country UI‑Sprache Währung Katalog
1
en-US
US
EN
USD
US‑Artikel
2
uk-UA
UA
UKR/RU
UAH
UA‑Artikel
3
en
DE
EN
EUR
DE‑Artikel
4
ru-RU
DE
RU
EUR
DE‑Artikel
5
en
(keine Daten) EN
USD
Globaler Standard

Dieser Blick wird später beim Thema Commerce nützlich, aber schon jetzt sieht man, wie leicht sich das Verhalten ändern lässt, indem man einfach unterschiedliche locale und country einspeist.

9. Kleines Diagramm des Locale‑Signalflusses

Um die Gedanken zu ordnen, schauen wir uns ein vereinfachtes Schema an:

flowchart TD
  U[Nutzer<br/>schreibt eine Nachricht] --> C[ChatGPT]
  C -->|bestimmt| L[openai/locale<br/>+ userLocation]
  L -->|leitet weiter| W["Widget (Next.js)"]
  L -->|leitet über _meta weiter| S[MCP Server]

  W -->|locale| UI[GiftGenius UI<br/>Texte + Zahlenformatierung]
  S -->|locale + country| DATA[Kataloge, Preise, Filter]

  style L fill:#e0f7ff,stroke:#00a
  style W fill:#f7fff0,stroke:#4b4
  style S fill:#fdf0ff,stroke:#b4

Wichtig: In diesem Schema taucht nirgends ein modales Fenster „Sprache wählen“ auf. Es ist nur als zusätzliche Ebene nötig, wenn die Signale den Erwartungen des Nutzers widersprechen.

10. Praxis: Was Sie jetzt sofort in Ihrer App tun können

Damit die Vorlesung nicht reine Theorie bleibt, ein kurzer praktischer Check‑list für GiftGenius:

  • Im Widget: den Hook useOpenAiGlobal("locale") oder ein Pendant hinzufügen und mindestens an einer Stelle eine RU/EN‑Verzweigung für einen Text anlegen.
  • Im MCP‑Server: in einem bestehenden Tool (suggest_gifts) _meta["openai/locale"] und _meta["openai/userLocation"] auslesen, in den Log schreiben und für die Katalogauswahl verwenden.
  • Eine einfache Funktion deriveCurrency(locale, country) schreiben und sie an einer Stelle zur Preisformatierung einsetzen.

Bauen Sie nicht sofort eine komplette i18n‑Engine und 15 Sprachen — unser Ziel ist jetzt, die Signale der Plattform ehrlich zu nutzen.

11. Typische Fehler beim Umgang mit Locale und userLocation

Fehler Nr. 1: openai/locale komplett ignorieren und sich nur auf navigator.language verlassen.
So machen es diejenigen, die an gewöhnliche Web‑Apps gewöhnt sind. In ChatGPT muss der Nutzer ggf. gar nichts im Browser öffnen, und navigator.language auf Ihrer Seite ist die Sprache des Tunneling‑Servers oder von Vercel, nicht des Nutzers. Am Ende ist die UI „mysteriöserweise“ immer auf Englisch, obwohl ChatGPT Ihnen zuverlässig ru-RU schickt.

Fehler Nr. 2: den Nutzer jedes Mal fragen „Welche Sprache ist für Sie bequemer?“
Wenn in jedem Chat die erste Replik des Widgets eine Sprachabfrage ist, fühlen sich Nutzer wie am Flughafen, wo sie fünfmal hintereinander gefragt werden, ob sie ihr Gepäck nicht vergessen haben. Die Plattform kennt Sprache und Region bereits — es reicht, die openai/locale zu respektieren und nur bei einem offensichtlichen Konflikt zu fragen (z. B. Anfrage auf Russisch bei locale = "en").

Fehler Nr. 3: die gewählte Sprache nur in der UI speichern und nicht an MCP‑Tools übergeben.
Das Widget kann auf Deutsch sein, aber der Server liefert weiterhin einen englischen Katalog, weil er nichts von der Sprachumschaltung weiß. Denken Sie immer an den durchgängigen Pfad: Wenn es in der UI einen Schalter gibt, muss dessen Ergebnis ans Backend übermittelt werden — entweder in den Tool‑Argumenten oder über die Gateway‑Sitzung.

Fehler Nr. 4: die Sprache nur anhand der Nachrichten zu „erraten“ und openai/locale zu ignorieren.
Autodetektion kann ganz gut funktionieren … solange der Nutzer reines Englisch schreibt. Sobald Mischsprachen oder ähnliche Phrasen auftauchen, schwankt das Ergebnis. openai/locale ist eine bereits vorbereitete, ausreichend zuverlässige Einschätzung, die die Plattform bereitstellt. Sie sollte die Hauptquelle der Wahrheit sein, Textdetektion nur ein zusätzlicher Hinweis.

Fehler Nr. 5: Geschäftslogik und Lokalisierung überall im Stil if (locale === 'ru') { ... } vermischen.
In dieser Vorlesung machen wir es der Einfachheit halber stellenweise noch so, aber planen Sie frühzeitig, dass Strings, Formate und Kataloge von der Geschäftslogik getrennt sein sollten. Andernfalls finden Sie sich in Code wieder, in dem jede Funktion mit if (locale.startsWith("ru")) beginnt, und eine weitere Sprache hinzuzufügen, wird schmerzhaft. In Vorlesung 44 gehen wir genau dieses Problem an, im Wissen, dass wir die Quelle locale bereits haben und sie zu nutzen wissen.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION