CodeGym /Kurslar /ChatGPT Apps /Locale haradan götürülür: openai/locale, _meta["openai/us...

Locale haradan götürülür: openai/locale, _meta["openai/userLocation"]

ChatGPT Apps
Səviyyə , Dərs
Mövcuddur

1. Niyə ümumiyyətlə locale‑u platformadan bilmək vacibdir və hər dəfə istifadəçidən soruşmamaq

Mövzuya lokalizasiya baxımından “köhnə üsulla” yanaşsaq, məntiq adətən belə olur: “Dili seçin” modalı göstərmək və nəticəni localStorage-da saxlamaq. ChatGPT Apps-də yanaşma fərqlidir: artıq ağıllı platformamız var və o dil və region barədə siqnalları səxavətlə ötürür. Onlardan istifadə etməyi öyrənmək və istifadəçini artıq suallarla yormamaq lazımdır.

ChatGPT sizin App‑ə hər sorğuda kontekstə aşağıdakıları əlavə edir:

  • istifadəçinin üstünlük verdiyi lokali (dil + region) — openai/locale / _meta["openai/locale"] sahəsində;
  • istifadəçinin geolokasiyası/regionu — _meta["openai/userLocation"] sahəsində.

Vidget (frontend) tərəfində locale-u window.openai və ya SDK hook‑u vasitəsilə alırsınız; MCP/backend tərəfində isə — MCP sorğusunda _meta vasitəsilə.

Nəticədə normal ssenari belə görünür: istifadəçi “Anaya 50 avro çərçivəsində hədiyyə seç” yazır. ChatGPT artıq onun locale-unu və userLocation-unu bilir, platforma bu siqnalları sizin App‑ə ötürür və siz:

  • UI‑ni anlaşılan dildə göstərirsiniz,
  • düzgün kataloq dilini yükləyirsiniz,
  • qiymətləri lazım olan valyuta və formatda formalaşdırırsınız.

Ayrı dialoq olmadan: “Yeri gəlmişkən, hansı dildə rahatdır?”

2. Siqnal №1: openai/locale — istifadəçinin dili və regionu

Bu sahə nədir və necə görünür

openai/locale — BCP‑47 formatında olan sətirdir, yəqin ki, görmüsünüz: "en", "en-US", "ru", "ru-RU", "uk-UA" və s.

Vacibdir ki, platforma:

  • yalnız dili göndərə bilər ("en", "ru"),
  • dil + region göndərə bilər ("en-US", "en-GB", "fr-CA").

BCP‑47 — brauzerdəki Intl API və əksər i18n kitabxanaları ilə əla işləyən standartdır. Yəni openai/locale-u demək olar ki, birbaşa Intl.NumberFormat-a, tərcümə mühərrikinə və sizin tools‑larınıza ötürmək olar.

Locale vidgetdə harada mövcuddur

ChatGPT daxilində render olunan xüsusi UI‑də Apps SDK locale olan qlobal window.openai obyektini təqdim edir.

Adətən bu belə görünür (TypeScript, Next.js 16, bizim GiftGenius vidceti):

// 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";
}

Real tətbiqdə ChatGPT qum qutusu və Storybook‑da işləyəcək bir hook yazmaq daha rahatdır:

// 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;
}

İndi istənilən komponentdə:

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

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

  return (
    <h2>
      {/* sonra burada t('titles.gift_search') olacaq */}
      {locale.startsWith("ru") ? "Hədiyyə seçimi" : "Gift search"}
    </h2>
  );
}

4‑cü mühazirədə bütün sətirləri lüğətlərə səliqə ilə çıxaracağıq, amma artıq indi UI‑ni random navigator.language-a deyil, platformadan gələn real siqnala bağladıq. Bu hook ixtisaslaşmışdır; real layihədə onu ChatGPT qloballarına çıxış üçün daha ümumi mexanizm üzərində qurmaq rahatdır — aşağıda ayrıca bölmədə buna qayıdacağıq.

Locale MCP/backend tərəfində harada mövcuddur

ChatGPT MCP‑alətini çağıranda, SDK JSON‑rpc sorğusunda _meta["openai/locale"]-ni ötürür. TypeScript serverində (bizim GiftGenius MCP) bu adətən alət handler‑inin ikinci arqumentində əlçatandır.

Nümunə:

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

const server = new McpServer();

server.registerTool(
  "suggest_gifts",
  {
    title: "Hədiyyələrin seçimi",
    description: "Seçimlərə əsasən hədiyyə siyahısı təklif edir",
    inputSchema: {
      type: "object",
      properties: {
        recipient: { type: "string" },
        budget: { type: "number" }
      },
      required: ["recipient", "budget"]
    }
  },
  async ({ input }, extra) => {
    const locale = extra?._meta?.["openai/locale"] || "en";
    // sonra düzgün kataloqu yükləmək olar
    const gifts = await loadGiftCatalog(locale);
    // ...
    return {
      content: [
        {
          type: "text",
          text: `Found ${gifts.length} gifts for locale ${locale}`
        }
      ],
      structuredContent: { gifts }
    };
  }
);

Beləliklə, locale bütün stack boyunca yaşayır: ChatGPT → Apps SDK → sizin MCP serveriniz.

İpucu

Hər bir mcp‑alətin serverdə extra parametri var, mcp‑server inputSchema-ya sığmayan bütün məlumatları ora qoyur. Belə bir obyektə nümunə:

{
  sessionId: undefined,			// həmişə undefined, aşağıda `openai/subject` istifadə edin
  _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',		// istifadəçinin kompüter lokali, söhbətdəki dillə uyğun gəlməyə bilər
    'openai/userLocation': {		// istifadəçinin kifayət qədər dəqiq yerləşməsi
      city: 'London',
      region: 'London City',
      country: 'GB',
      timezone: 'Europe/London',
      latitude: '5.45466',
      longitude: '-0.52380'
    },
    timezone_offset_minutes: -240,	// saat qurşağı ofseti
    'openai/subject': 'v1/sEtRuS92UEOPNdwzEUZORfeOKf7XSk2KZoIUGfAsb68BzZ8h5FAOgrH'	// bu sessionId‑dir
  },
  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',					// tətbiqin yerli domeni
      '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'
    }
  },
}

Bəlkə başlıqların bir hissəsini burada ngrock doldurub, amma maraqlı məlumatlar yenə də çoxdur.

3. Siqnal №2: _meta["openai/userLocation"] — istifadəçinin coğrafiyası

Struktur və məna

_meta["openai/userLocation"] — ölkə, region, şəhər, saat qurşağı və hətta koordinatları olan geo‑məlumat obyektidir. Təxminən belə:

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

GiftGenius‑də həqiqətən istifadə edəcəyiniz əsas sahələr:

  • country — ölkənin iki hərfli ISO kodu, assortiment və valyuta üçün kritikdir;
  • timezone — tarix/vaxt formatları və xatırlatmalar üçün faydalıdır.

İpucu

Eksperimental olaraq yoxlanılıbuserLocation təyini çox keyfiyyətli işləyir. Məlumatlar hər MCP‑tool çağırışında extra._meta["openai/userLocation"] parametri ilə gəlir. Öz tətbiqlərinizi hazırlayarkən onlara arxalana bilərsiniz.

userLocation‑dan MCP‑alətlərində necə istifadə etməli

MCP serverində userLocation _meta["openai/userLocation"] daxilində, _meta["openai/locale"] ilə yanaşı yaşayır.

Nümunə alətimizi genişləndirək:

server.registerTool(
  "suggest_gifts",
  { /* sxema yuxarıdakı kimidir */ },
  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 }
    };
  }
);

loadGiftCatalog(locale, country) funksiyası artıq bunları edə bilər:

  • lazımi JSON faylını seçmək: gift_catalog.en-US.json, gift_catalog.ru-RU.json,
  • bu ölkəyə çatdırılması mümkün olmayan malları süzmək,
  • baza valyutasını seçmək.

Bir az sonra commerce modullarında country əsasında vergi qaydalarını seçəcək və düzgün SKU‑lara map edəcəksiniz, amma arxitektura baxımından yenə də eyni siqnala — country-yə — söykənirsiniz.

userLocation locale‑u necə tamamlayır

Klassik nümunə:

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

Məntiq belə ola bilər:

  • UI və promptlar — ingilis dilində (locale‑a hörmət);
  • valyuta və qiymət formatı — avro, çünki istifadəçi fiziki olaraq Almaniyadadır;
  • hədiyyə siyahısı — yalnız DE‑yə çatdırılanlar.

GiftGenius‑də bunu kiçik bir köməkçi funksiyası ilə ifadə etmək olar:

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";
}

Və qiymət formatlaşdırması üçün backend / frontend‑də istifadə etmək:

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

Backenddə artıq localecountry-dən kataloq və valyuta seçimi üçün istifadə etməyi öyrəndik. Daha sonra həmin siqnalları vidcetdə UI‑yə düzgün ötürmək vacibdir ki, istifadəçi mətnləri və qiymətləri gözlənilən formatda görsün.

4. GiftGenius vidcetində locale və userLocation necə alınır

Artıq localeuserLocation-un MCP tərəfində necə yaşadığını və kataloqlara, valyutaya necə təsir etdiyini gördük. İndi locale-u GiftGenius vidcetinə necə səliqə ilə götürəcəyimizi və onu birbaşa React UI‑də necə istifadə edəcəyimizi araşdıraq.

Vacibdir: vidcetdə bizdə yalnız locale-a birbaşa çıxış var (window.openai və SDK hook‑ları vasitəsilə). userLocation _meta-da yaşayır və MCP/backend tərəfində istifadə olunur — yuxarıda bununla artıq işlədik.

Apps SDK‑da “xam” window.openai-dan əlavə React hook‑ları şəklində utilitlər var. Sənədlərdə useOpenAiGlobal("locale") kimi hook‑lar təsvir olunur; onlar ChatGPT‑nin qlobal kontekstinin dəyərlərini React komponentlərinə çıxarır.

Baş verənləri başa düşmək üçün belə bir hook‑u özümüz modelləşdirək.

Əsas hook: useOpenAiGlobal

Əvvəlcə ixtisaslaşmış useOpenAiLocale yazmışdıq. Praktikada ChatGPT qloballarına çıxış üçün bir universal hook‑a sahib olmaq daha rahatdır — onun əsasında həm useOpenAiLocale, həm də digər örtükləri asanlıqla yığmaq olar. Belə bir hook təsəvvür edək:

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

type OpenAiGlobals = {
  locale?: string;
  // bura sonra theme, userAgent və s. əlavə etmək olar
};

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;
}

İndi useOpenAiGlobal("locale", "en") bizə locale-un aktual dəyərini "en" defolt dəyəri ilə verir.

GiftGenius vidcetində tətbiqi

Lokalizə edilmiş salamı və debug üçün cari lokali göstərən kiçik bir komponent yazaq:

// 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")
      ? "Salam! Sizə hədiyyə seçməkdə kömək edəcəyəm."
      : "Hi! I’ll help you find a great gift.";

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

Hələlik nə lüğətlər, nə də i18n kitabxanaları var — bunlar sonra olacaq. İndi vacib olan odur ki, biz artıq dili təsadüfi fərziyyələrdən deyil, ChatGPT‑dən dürüst şəkildə götürməyi bacarırıq.

5. İstifadəçidən dili nə zaman açıq şəkildə soruşmaq lazımdır

Əgər openai/localeuserLocation bu qədər güclüdürsə, bəlkə heç vaxt istifadəçidən hansı dildə işləmək istədiyini soruşmayaq? Təəssüf ki, bəzən soruşmaq gərəkir.

Siqnallar nə vaxt kifayət etmir

Bir neçə tipik situasiya var:

  • ChatGPT hesabı ingiliscədir (locale = "en"), amma istifadəçi rus dilində yazır. Model rusca cavab verir, amma UI sizdə ingiliscədir.
  • İstifadəçi Almaniyadadır (userLocation.country = "DE"), locale = "en", siz isə həm alman, həm ingilis interfeysini verə bilirsiniz.
  • Tətbiq ünsiyyət dilinə qarşı həssasdır: psixoterapiya, hüquqi məsləhətlər, tədris. Burada anlama dəqiqliyi auto‑detektdən daha vacibdir.

Belə hallarda ssenarinin əvvəlində bir dəfə qısa və nəzakətli sual vermək, sonra isə seçimi yadda saxlamaq yerinə düşər.

Dil sualını necə gözə batmayan şəkildə verməli

Adətən formulyasiya maksimal sadə və vizual olur, məsələn:

  • “Hansə dildə rahatdır: English yoxsa Rus dili?”
  • “Diliniz English kimi müəyyən edildi. Başqa dilə keçmək istəyirsiniz?”

ChatGPT App‑də bunu iki üsulla etmək olar:

  • Vidget UI vasitəsilə: yuxarıda kiçik dil dəyişdirici çəkmək.
  • Tətbiqin adından chata follow‑up mesajı vasitəsilə: suallı mətn göndərmək və cavabı emal etmək.

Kod: GiftGenius‑də sadə dil seçimi

Switcher‑komponenti yazaq, o:

  • başlanğıc dili locale-dan götürür,
  • istifadəçiyə ru və ya en seçməyi təklif edir,
  • seçimi vidcet vəziyyətində saxlayır (hələlik sadəcə React state‑də).
// 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" ? "Dil:" : "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>
  );
}

Və əsas GiftGenius vidcetində artıq mətnləri/lüğəti ChatGPT‑dən gələn “xam” məlumatlara deyil, selectedLocale-a görə seçmək olar.

Gələcək mühazirələrdə lokal state‑i daha dayanıqlı saxlama ilə əvəz edəcəksiniz (məsələn, seçilmiş dili _meta["openai/subject"] vasitəsilə MCP / Gateway‑ə ötürməklə), amma pattern eyni qalacaq.

6. Locale və userLocation‑u backend‑ə necə ötürmək və saxlamaq

Siqnallar ChatGPT‑dən “yuxarıdan” gəlir, amma həyat bununla bitmir. Sonra bu məlumatları alətlərinizə və servislərinizə çatdırmaq, yolda itirməmək və modeli dili yenidən təxmin etməyə məcbur etməmək lazımdır.

Alət arqumentlərində ayrıca locale sahəsi

Ən etibarlı üsul — alətin inputSchema-sına ayrıca locale (və istəsəniz country) sahələrini əlavə etməkdir. Beləliklə, model açıq siqnal alır: “bu sahəni doldurmaq lazımdır”.

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) => {
    // Əgər model locale/country doldurmayıbsa, _meta-dan ehtiyat götürək:
    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";

    // ...
  }
);

Bu, server daxilində “sehr”i azaldır: modelin istifadə etmək istədiyi arqumentlər açıq görünür.

Locale‑un sessiya/istifadəçi səviyyəsində saxlanması

MCP Gateway (gələcək modullar) arxitekturasında “müştəri vəziyyəti” saxlamaq qəbul olunub: locale, currency, üstünlüklər. Bizim üçün indi vacib olan fikir budur: siqnalları ChatGPT‑dən bir dəfə oxuyuruq — sonra onları sessiya vəziyyətinin tərkib hissəsi kimi istifadə edirik, hər dəfə yenidən hesablamaq əvəzinə.

Şərti psevdokod:

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

function onMcpRequest(request: any) {
  const subject = request._meta?.["openai/subject"]; // anonim user id
  const locale = request._meta?.["openai/locale"] || "en";
  const country = request._meta?.["openai/userLocation"]?.country;

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

  // daha sonra locale/country konkret MCP serverinə ötürülür
}

Bu mühazirə çərçivəsində Gateway‑i reallaşdırmağınıza ehtiyac yoxdur, yalnız onu başa düşmək kifayətdir ki, localeuserLocation belə “sessiya vəziyyəti” üçün namizəddir.

İpucu

Eksperimental məlumatlar: request._meta?.["openai/locale"] istifadəçinin hazırda qurulmuş lokalını göstərir. Ünsiyyət dilini inputSchema vasitəsilə alət parametrində almaq olar.

Məndə kompüterdə EN lokalı qurulmuşdu, amma ChatGPT ilə alman dilində (DE) danışırdım. Nəticə belə oldu:

  • request._meta?.["openai/locale"] EN‑ə bərabər idi
  • inputSchema vasitəsilə alət parametri kimi alınan locale isə DE‑yə bərabər idi

7. Locale vs mətndən dilin avtomatik təyini

Bəzən tərtibatçılar belə bir fikrə meyl edir: “Gəlin istifadəçi mətnindən dili sadəcə detekt edək, axı LLM hər şeyi bacarır”. Praktikada bu demək olar ki, həmişə openai/locale-a əsaslanmaqdan daha pisdir.

Səbəblər kifayət qədər praqmatikdir:

  • istifadəçi dilləri qarışıq yaza bilər;
  • incə fərqlər (uk-UA vs ru-RU) tək mesajdan pis detekt olunur;
  • ChatGPT artıq sizin yerinizə bu işi görüb və locale göndərib.

Avtodetekt fallback kimi faydalıdır, əgər openai/locale qəribə formada gəlirsə və ya ümumiyyətlə gəlmirsə (bu, indi nadir hallarda olur), amma əsas məntiqi onun üzərində qurmaq lazım deyil. Kobud qayda:

  • ilk növbədə openai/locale-a “həqiqət” kimi baxırıq;
  • sonra userLocation-u nəzərə alırıq (valyuta, assortiment);
  • və yalnız çox mübahisəli hallarda son mesajın dilinə əlavəən baxmaq olar.

8. Müxtəlif locale və userLocation kombinasiyaları: ssenari cədvəli

Yekunlaşdırmaq üçün GiftGenius‑in müxtəlif ssenarilərdə necə davranmalı olduğunu baxaq.

Ssenari locale userLocation.country UI dili Valyuta Kataloq
1
en-US
US
EN
USD
US‑məhsullar
2
uk-UA
UA
UKR/RU
UAH
UA‑məhsullar
3
en
DE
EN
EUR
DE‑məhsullar
4
ru-RU
DE
RU
EUR
DE‑məhsullar
5
en
(məlumat yoxdur) EN
USD
Qlobal standart

Bu baxış sizə daha sonra commerce mövzularında kömək edəcək, amma artıq indi görünür ki, fərqli localecountry verərək davranışı necə asan dəyişmək olur.

9. Lokal siqnallarının axını üzrə kiçik diaqram

Düşüncələri toplamaq üçün sadələşdirilmiş sxemə baxaq:

flowchart TD
  U[İstifadəçi<br/>mesaj yazır] --> C[ChatGPT]
  C -->|müəyyən edir| L[openai/locale<br/>+ userLocation]
  L -->|ötürür| W["Widget (Next.js)"]
  L -->|_meta vasitəsilə ötürür| S[MCP Server]

  W -->|locale| UI[GiftGenius UI<br/>mətnlər + rəqəm formatı]
  S -->|locale + country| DATA[Kataloqlar, qiymətlər, filtrlər]

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

Vacib məqam: bu sxemdə heç yerdə “Dili seçin” modal pəncərəsi çəkilməyib. O, yalnız siqnallar istifadəçinin gözləntilərinə zidd olduqda əlavə qat kimi lazımdır.

10. Praktika: indi öz App‑inizdə nə edə bilərsiniz

Mühazirə nəzəriyyə olaraq qalmasın deyə, GiftGenius üzrə qısa praktik yoxlama siyahısı:

  • Vidgetdə: useOpenAiGlobal("locale") və ya onun analoqunu əlavə edin və ən azı bir yerdə mətn üçün RU/EN şaxələnməsi qurun.
  • MCP serverində: mövcud alətlərdən birində (suggest_gifts) _meta["openai/locale"]_meta["openai/userLocation"]-u götürün, log‑a yazın və kataloq seçimi üçün istifadə edin.
  • deriveCurrency(locale, country) sadə funksiyasını yazın və qiymət formatlaşdırmasında bir yerdə istifadə edin.

Dərhal tam i18n mühərriki və 15 dil qurmağa ehtiyac yoxdur — məqsədimiz indi platforma siqnallarından dürüst istifadə etməyi öyrənməkdir.

11. locale və userLocation ilə işləyərkən tipik səhvlər

Səhv №1: openai/locale‑u tam görməməzliyə vurmaq və yalnız navigator.language‑ə güvənmək.
Belə edənlər adətən sıravi veb‑tətbiqlərə öyrəşənlərdir. ChatGPT‑də istifadəçi ümumiyyətlə brauzerdə heç nə açmaya bilər, sizin tərəfdəki navigator.language isə istifadəçinin deyil, tunel serverinin və ya Vercel‑in dilidir. Nəticədə UI həmişə “sirli şəkildə” ingiliscə olur, halbuki ChatGPT sizə sabit şəkildə ru-RU göndərir.

Səhv №2: hər dəfə istifadəçidən “hansı dildə rahatdır?” sualını vermək.
Əgər hər chatda vidgetin ilk replikası dil sorğusudursa, istifadəçilər özlərini hava limanında hiss etməyə başlayırlar — onlardan üst‑üstə beş dəfə soruşurlar ki, bagaJı unutmayıblar ki? Platforma artıq dil və regionu bilir — openai/locale-a hörmət etmək və yalnız aşkar konflikt zamanı soruşmaq kifayətdir (məsələn, locale = "en" olduğu halda sorğu rus dilindədirsə).

Səhv №3: seçilmiş dili yalnız UI‑də saxlamaq və onu MCP alətlərinə ötürməmək.
Vidget rus dilində ola bilər, amma server dil dəyişikliyindən xəbəri olmadığı üçün hələ də ingiliscə kataloq qaytarar. Həmişə sonadək yol barədə düşünün: əgər UI‑də siviçer varsa, onun nəticəsi backend‑ə çatdırılmalıdır — ya alət arqumentlərində, ya da Gateway sessiyası vasitəsilə.

Səhv №4: openai/locale‑u görməzlikdən gələrək dili yalnız mesaj mətnindən “təhmin” etməyə çalışmaq.
Mətndən autodetekt pis işləməyə bilər… istifadəçi təmiz ingiliscə yazana qədər. Dillər qarışan kimi və ya oxşar ifadələr görünən kimi nəticə “üzməyə” başlayır. openai/locale — platforma tərəfindən təqdim edilən, artıq hazır və kifayət qədər etibarlı qiymətləndirmədir. Onu əsas həqiqət mənbəyi saymağa, mətndən detekti isə yalnız əlavə siqnal kimi qəbul etməyə dəyər.

Səhv №5: biznes məntiqini və lokalizasiyanı kodun hər yerində if (locale === 'ru') { ... } üslubunda qarışdırmaq.
Bu mühazirədə sadəlik naminə hələ bir az belə edirik, amma öncədən planlaşdırmaq vacibdir ki, sətirlər, formatlar və kataloqlar biznes məntiqindən ayrılmış olsun. Əks halda bir neçə aydan sonra kodun elə vəziyyətinə düşərsiniz ki, hər funksiya if (locale.startsWith("ru")) ilə başlayacaq və daha bir dil əlavə etmək ağrılı olacaq. 44‑cü mühazirədə məhz bu problemi müalicə edəcəyik, xatırlayaraq ki, locale mənbəyimiz artıq var və ondan istifadə etməyi bacarırıq.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION