# General Translation Integrations: Localizzare uno storefront Shopify con Next.js
URL: https://generaltranslation.com/it/docs/integrations/shopify/guides/localizing-nextjs.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Come localizzare uno storefront Vercel Shop con gt-next, route con prefisso di impostazione regionale e Cache Components.

[Vercel Shop](https://github.com/vercel/shop) è un template per Next.js App Router basato su Hydrogen, l&#39;SDK per storefront di Shopify indipendente dal framework. Con `gt-next`, l&#39;impostazione locale predefinita viene servita senza prefisso, le altre impostazioni regionali si trovano sotto un prefisso come `/fr/...` e ogni pagina rimane prerenderizzabile una volta per ciascuna impostazione regionale. Tutte le lingue vendono nello stesso mercato Shopify; per assegnare a ogni lingua un mercato e una valuta propri, segui poi la guida [Vendere in più mercati](/docs/integrations/shopify/guides/selling-in-markets).

*Nota: questa guida si basa sul template con Next.js 16, `cacheComponents: true`, `@shopify/hydrogen` 2026.10 e `gt-next` 11.4, ovvero le versioni utilizzate dallo [storefront di esempio](https://gt-shopify-vercel.vercel.app), già online in inglese, francese, giapponese, coreano e indonesiano.*

## Prima di iniziare [#before-start]

Installa `gt-next` e la CLI `gt` come dipendenza di sviluppo, come descritto nell&#39;[Avvio rapido di Next.js](/docs/react/nextjs-quickstart). In questa guida, il middleware dell&#39;Avvio rapido viene sostituito dal file `proxy.ts` già presente nel template.

## Configurare gt-next [#configure]

### 1. Aggiungi il plugin di configurazione

Aggiungi [`withGTConfig`](/docs/react/nextjs/config) all&#39;elenco dei plugin che il template passa a `withShopConfig`:

```ts title="next.config.ts"
import { withGTConfig } from "gt-next/config";

export default withShopConfig(nextConfig, [
  (config: NextConfig) => withGTConfig(config), // [!code ++]
  shopConfig.botid.isEnabled && withBotId,
  shopConfig.agent.isEnabled && withEve,
]);
```

### 2. Aggiungi le funzioni di richiesta

Con Cache Components, l&#39;impostazione regionale deve provenire dal parametro radice `[locale]`, non dalle intestazioni o dai cookie. Crea i file [`getLocale`](/docs/react/nextjs/reference/functions/get-locale) e [`getRegion`](/docs/react/nextjs/reference/functions/get-region) nella radice del progetto: `withGTConfig` li rileva automaticamente. (Vedi [Utilizzo di Cache Components](/docs/react/nextjs/cache-components#request-values)).

```ts title="getLocale.ts"
import { locale } from "next/root-params";

import { defaultLocale } from "@/lib/i18n";

// Il root param `[locale]` fa parte della chiave di cache statica, quindi leggerlo consente di mantenere le pagine prerenderizzabili.
export default async function getLocale(): Promise<string> {
  return (await locale()) ?? defaultLocale;
}
```

```ts title="getRegion.ts"
import { locale } from "next/root-params";

import { defaultLocale, getCommerceLocale } from "@/lib/i18n";

// La regione è il paese del mercato Shopify in cui vende la pagina con la sua impostazione regionale.
export default async function getRegion(): Promise<string> {
  return getCommerceLocale((await locale()) ?? defaultLocale).country;
}
```

`getCommerceLocale` associa un&#39;impostazione regionale al paese e alla lingua corrispondenti su Shopify. (Vedi [Eseguire query su Shopify in ogni lingua](#shopify-language)).

### 3. Generare e caricare le traduzioni in locale

Cache Components richiede una funzione [`loadTranslations`](/docs/react/reference/functions/load-translations) personalizzata, perché il caricamento remoto non è sicuro durante il prerendering. Scrivi le traduzioni nel tuo codice sorgente tramite la CLI e importale dal bundle. (Vedi [Archiviare le traduzioni in locale](/docs/react/guides/storing-translations)).

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["fr", "ja", "ko", "id"],
  "src": ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}"],
  "files": {
    "gt": { "output": "public/_gt/[locale].json" }
  }
}
```

* `src` aggiunge `lib/`. Per impostazione predefinita, la CLI analizza solo `src/`, `app/`, `pages/` e `components/`, mentre il template tiene i metadati e le etichette in `lib/`.

```ts title="loadTranslations.ts"
// `pnpm translate` genera questi file prima della build; includerli nel bundle consente di prerenderizzare le pagine.
const translations: Record<string, () => Promise<{ default: object }>> = {
  fr: () => import("./public/_gt/fr.json"),
  ja: () => import("./public/_gt/ja.json"),
  ko: () => import("./public/_gt/ko.json"),
  id: () => import("./public/_gt/id.json"),
};

export default async function loadTranslations(locale: string): Promise<object> {
  const loaded = await translations[locale]?.();
  return loaded?.default ?? {};
}
```

Esegui [`npx gt translate`](/docs/cli/reference/commands/translate) dopo aver modificato i testi ed esegui il commit dei file generati, oppure lancialo prima di `next build`. Con i file già nel repository, la build dello storefront funziona anche senza una chiave API di General Translation.

## Instradare le richieste in base all&#39;impostazione regionale [#routing]

### Spostare le route sotto `[locale]`

1. Sposta tutte le route dello storefront in `app/[locale]/` ed elimina `app/layout.tsx`, in modo che `[locale]` diventi un parametro radice. Lascia `api/`, `md/`, `agent/`, `sitemap*`, `robots.ts`, `manifest.ts`, `llms.txt`, `global-error.tsx` e le icone statiche direttamente sotto `app/`.

2. Aggiorna gli argomenti di tipo di `PageProps<"/...">` e `LayoutProps<"/...">` in `"/[locale]/..."`.

3. In `app/[locale]/layout.tsx`, restituisci tutte le impostazioni regionali da `generateStaticParams`, rifiuta quelle non supportate, imposta `<html lang>` e racchiudi il body in [`GTProvider`](/docs/react/reference/components/gt-provider):

   ```tsx title="app/[locale]/layout.tsx"
   import { GTProvider } from "gt-next";
   import { getLocale } from "gt-next/server";
   import { notFound } from "next/navigation";

   import { isSupportedLocale, locales } from "@/lib/i18n";

   export const ensureStatic = "prefetch";

   export function generateStaticParams() {
     return locales.map((locale) => ({ locale }));
   }

   export default async function RootLayout({ children }: LayoutProps<"/[locale]">) {
     const locale = await getLocale();
     if (!isSupportedLocale(locale)) notFound();
     return (
       <html lang={locale}>
         <body>
           <GTProvider>{/* skip link, provider del carrello, nav, main, footer */}{children}</GTProvider>
         </body>
       </html>
     );
   }
   ```

4. Aggiungi una route catch-all che chiami `notFound()`, così i percorsi senza corrispondenza renderizzano `app/[locale]/not-found.tsx` all&#39;interno del layout localizzato anziché la pagina 404 predefinita di Next.js:

   ```tsx title="app/[locale]/[...rest]/page.tsx"
   import { notFound } from "next/navigation";

   import { PLACEHOLDER_HANDLE } from "@/lib/static-params";

   export function generateStaticParams() {
     return [{ rest: [PLACEHOLDER_HANDLE] }];
   }

   export default function CatchAllPage(): never {
     notFound();
   }
   ```

<Callout type="warn">
  **Attenzione:** in `gt-next` 11.4, [`GTProvider`](/docs/react/reference/components/gt-provider) legge `usePathname()` sul client. Di conseguenza, con Cache Components, il prerendering di una route dinamica senza parametri statici non va a buon fine. Nelle route che non hanno parametri statici, come la route catch-all e `account/orders/[id]`, restituisci un segnaposto da `generateStaticParams`.
</Callout>

### Instradare le richieste nel proxy

Leggi una sola volta l&#39;elenco delle impostazioni regionali da `gt.config.json` e separa il prefisso da ciascun percorso:

```ts title="lib/i18n/index.ts"
import gtConfig from "@/gt.config.json";

export const defaultLocale = gtConfig.defaultLocale;
export const locales = [gtConfig.defaultLocale, ...gtConfig.locales];

export function isSupportedLocale(value: string | undefined): value is string {
  return value !== undefined && locales.includes(value);
}

/** Divide `/fr/products/x` in `fr` e `/products/x`; i percorsi senza prefisso corrispondono all'impostazione locale predefinita. */
export function splitLocalePath(pathname: string): { locale: string; pathname: string } {
  const [, segment, ...rest] = pathname.split("/");
  if (segment !== defaultLocale && isSupportedLocale(segment)) {
    return { locale: segment, pathname: `/${rest.join("/")}` };
  }
  return { locale: defaultLocale, pathname };
}

/** L'impostazione locale predefinita resta senza prefisso, così ogni pagina ha un unico URL canonical. */
export function localizePath(pathname: string, locale: string): string {
  if (locale === defaultLocale) return pathname;
  return pathname === "/" ? `/${locale}` : `/${locale}${pathname}`;
}
```

In `proxy.ts`, mantieni invariato il dispatch `handleShopifyRoutes` del template, così che Shopify gestisca per primo le richieste relative al carrello, alla ricerca predittiva e all&#39;account cliente. Poi riscrivi tutte le altre richieste di pagina verso la rispettiva route `/[locale]`. Non modificare i percorsi API e gli altri percorsi che non corrispondono a pagine:

```ts title="proxy.ts"
// Il dispatch del template, invariato: con gli account cliente abilitati, il branch
// che gestisce la sessione aggiunge i gestori degli account e un manager di sessione.
const shopifyRoute = customerSession
  ? handleShopifyRoutes({
      ...routeOptions,
      handlers: customerHandlers(customerSession, isAuthPath),
      sessionManager: createCustomerSessionManager(request),
    })
  : handleShopifyRoutes({ ...routeOptions, handlers: [cartHandlers, predictiveSearchHandlers] });
if (shopifyRoute) return shopifyRoute;

const { locale, pathname: unprefixedPathname } = splitLocalePath(pathname);
const refinedPath = getRefinedCollectionPath(unprefixedPathname, request.nextUrl.search);
const localizedPath = isUnlocalizedPath(pathname)
  ? null
  : `/${locale}${refinedPath ?? (unprefixedPathname === "/" ? "" : unprefixedPathname)}`;
// Le pagine si trovano in app/[locale]; l'impostazione locale predefinita viene servita senza prefisso e riscritta internamente.
const rewritePath =
  getMarkdownRewritePath(request) ?? (localizedPath === pathname ? null : localizedPath);
```

```ts title="proxy.ts"
const UNLOCALIZED_PATH = /^\/(?:api|md|agent|eve|_eve_internal|\.well-known|__shopify)(?:\/|$)/;

function isUnlocalizedPath(pathname: string): boolean {
  return UNLOCALIZED_PATH.test(pathname);
}

// Pagine dello storefront, a differenza delle route API e degli endpoint di Shopify con estensione, come `/cart.js`.
function isPagePath(pathname: string): boolean {
  return !isUnlocalizedPath(pathname) && !/\.[a-z]+$/i.test(pathname);
}
```

Poiché `splitLocalePath` non considera mai l&#39;impostazione locale predefinita come prefisso, `/en/products/x` viene riscritto in `/en/en/products/x` e restituisce un errore 404. In questo modo ogni pagina ha un solo URL canonical.

### Localizza i link

Passa gli href di tipo stringa a [`useLocalizeHref`](/docs/react/nextjs/reference/hooks/use-localize-href) all&#39;interno del componente `Link` del template, così che i link interni mantengano l&#39;impostazione regionale corrente. Fai lo stesso per `router.push`, `router.replace` e la navigazione della ricerca.

```tsx title="components/ui/link.tsx"
import { useLocalizeHref } from "gt-next/link";

// Mantiene la navigazione nel locale attivo; l'impostazione locale predefinita resta senza prefisso.
const localizeHref = useLocalizeHref();
const localizedHref = typeof href === "string" ? localizeHref(href) : href;
```

Per il selettore della lingua, sostituisci il prefisso dell&#39;URL corrente e mostra il nome di ogni lingua nella lingua stessa:

```tsx title="components/nav/language-switcher.tsx"
"use client";

import { T, useLocale, useLocales } from "gt-next";
import { useId } from "react";

import { localizePath, splitLocalePath } from "@/lib/i18n";

/** Mostra il nome di ogni lingua nella lingua stessa ("Français", "日本語"), così gli acquirenti riconoscono subito la propria. */
function getEndonym(locale: string): string {
  const name = new Intl.DisplayNames([locale], { type: "language" }).of(locale) ?? locale;
  return name.charAt(0).toLocaleUpperCase(locale) + name.slice(1);
}

export function LanguageSwitcher() {
  const id = useId();
  const locale = useLocale();
  const locales = useLocales();
  return (
    <>
      <label htmlFor={id} className="sr-only">
        <T>Language</T>
      </label>
      <select
        id={id}
        value={locale}
        onChange={(event) => {
          // Il cambio di impostazione regionale modifica il layout radice, quindi naviga con un ricaricamento completo della pagina.
          const { pathname } = splitLocalePath(window.location.pathname);
          window.location.assign(
            `${localizePath(pathname, event.target.value)}${window.location.search}`,
          );
        }}
      >
        {locales.map((option) => (
          <option key={option} lang={option} value={option}>
            {getEndonym(option)}
          </option>
        ))}
      </select>
    </>
  );
}
```

### Aggiungi i metadati SEO

Assegna a ogni pagina un URL canonical nella relativa impostazione regionale e un&#39;alternativa `hreflang` per ciascuna impostazione regionale. Le funzioni `buildAlternates` e `buildOpenGraph` del template in `lib/seo/index.ts` sono sincrone e non possono leggere l&#39;impostazione regionale, quindi spostale in `lib/seo/server.ts` come funzioni asincrone:

1. In `lib/seo/index.ts`, esporta `buildCanonicalPath` ed elimina `buildAlternates` e `buildOpenGraph`.
2. Aggiungi le versioni asincrone a `lib/seo/server.ts`:

   ```ts title="lib/seo/server.ts"
   import { getLocale } from "gt-next/server";
   import type { Metadata } from "next";

   import { localizePath, locales } from "@/lib/i18n";
   import { buildCanonicalPath } from "@/lib/seo";
   import type { SearchParamsInput } from "@/lib/seo/types";

   /** URL canonical per l'impostazione regionale della richiesta, più le alternative hreflang per ogni impostazione regionale. */
   export async function buildAlternates({
     pathname,
     searchParams,
   }: {
     pathname: string;
     searchParams?: SearchParamsInput;
   }): Promise<Metadata["alternates"]> {
     const canonicalPath = buildCanonicalPath(pathname, searchParams);
     const locale = await getLocale();
     return {
       canonical: localizePath(canonicalPath, locale),
       languages: {
         ...Object.fromEntries(locales.map((code) => [code, localizePath(canonicalPath, code)])),
         "x-default": canonicalPath,
       },
     };
   }
   ```

   Rendi asincrona anche `buildOpenGraph` allo stesso modo e localizzane l&#39;URL e le impostazioni regionali. Open Graph richiede valori nel formato `language_TERRITORY`, come `fr_FR`, quindi converti l&#39;impostazione regionale in quel punto e mantieni il tag semplice per `hreflang` e `<html lang>`:

   ```ts title="lib/seo/server.ts"
   /** Le impostazioni regionali di Open Graph usano il formato language_TERRITORY, come fr_FR; "fr" diventa il territorio più probabile. */
   function toOpenGraphLocale(locale: string): string {
     const { language, region } = new Intl.Locale(locale).maximize();
     return `${language}_${region}`;
   }

   // In buildOpenGraph, insieme ai campi esistenti:
   const locale = await getLocale();
   return {
     url: localizePath(url, locale),
     locale: toOpenGraphLocale(locale),
     alternateLocale: locales.filter((code) => code !== locale).map(toOpenGraphLocale),
   };
   ```

   `maximize()` sceglie il territorio più probabile, come `fr_FR` per `fr` e `zh_TW` per `zh-Hant`. Se per un&#39;impostazione regionale il territorio più probabile non corrisponde a quello a cui ti rivolgi, sostituisci la conversione con una mappatura esplicita.
3. Nella funzione `generateMetadata` di ogni pagina, importa entrambi gli helper da `@/lib/seo/server` e usa `await` per attenderli:

   ```tsx title="app/[locale]/page.tsx"
   import { buildAlternates, buildOpenGraph } from "@/lib/seo/server"; // [!code highlight]

   export async function generateMetadata(): Promise<Metadata> {
     const gt = await getGT();
     const title = gt("Home");
     const description = gt("Explore featured products, curated collections, and seasonal campaigns.");
     return {
       title: `${title} | ${shopConfig.site.name}`,
       description,
       alternates: await buildAlternates({ pathname: "/" }), // [!code highlight]
       openGraph: await buildOpenGraph({ title, description, url: "/", type: "website" }), // [!code highlight]
     };
   }
   ```

   Dopo l&#39;eliminazione dei vecchi helper, le pagine che importano ancora da `@/lib/seo` non superano il controllo dei tipi: in questo modo individui tutti i punti di chiamata che ti sono sfuggiti.

Elenca anche nella mappa del sito l&#39;URL di ogni impostazione regionale, ciascuno con voci `<xhtml:link rel="alternate" hreflang="...">` per tutte le impostazioni regionali.

## Eseguire query su Shopify in ogni lingua [#shopify-language]

Associa ogni impostazione regionale al paese e alla lingua Shopify accettati dalle chiamate alla Storefront API del template. Tutte le impostazioni regionali condividono l&#39;unico mercato dello store, quindi cambia solo la lingua:

```ts title="lib/i18n/index.ts"
import type { CommerceLocale } from "@/lib/config/types";

// Il mercato in cui si vende in ogni lingua. La Currency proviene sempre dalla risposta di Shopify.
const STORE_COUNTRY: CommerceLocale["country"] = "US";

// La lingua della Storefront API per ogni impostazione regionale in gt.config.json.
const SHOPIFY_LANGUAGES: Record<string, CommerceLocale["language"]> = {
  en: "EN",
  fr: "FR",
  ja: "JA",
  ko: "KO",
  id: "ID",
};

export function getCommerceLocale(locale: string): CommerceLocale {
  const language = SHOPIFY_LANGUAGES[locale];
  if (!language) throw new Error(`No Shopify language for locale: ${locale}`);
  return { country: STORE_COUNTRY, language };
}

/** Il proxy memorizza in questo cookie l'impostazione regionale della pagina, così le chiamate ai gestori Hydrogen (`/api/cart`) usano la stessa lingua. */
export const LOCALE_COOKIE_NAME = "shop_locale";
/** Il proxy inoltra in questa intestazione della richiesta l'impostazione regionale risolta alle server action e al seed del carrello. */
export const LOCALE_HEADER_NAME = "x-shop-locale";
```

Ogni lingua deve essere un `LanguageCode` valido della Storefront API (vedi [Codici locale](/docs/integrations/shopify/reference/locale-handling#locale-codes)). Se [memorizzi le traduzioni del catalogo in Shopify](/docs/integrations/shopify/guides/translating-products#store-in-shopify), pubblica anche ogni lingua nel negozio: per una lingua non pubblicata, Shopify restituisce il testo di origine. Le traduzioni incluse nel bundle dello storefront non richiedono la pubblicazione delle lingue.

### Passare la lingua alle letture del catalogo

I getter del catalogo del template accettano già un&#39;opzione `locale` di tipo `CommerceLocale` e la passano a `@inContext`. Passa il valore dell&#39;impostazione regionale da ogni pagina e componente. I getter che usano `"use cache"` lo ricevono come argomento, in modo che ogni lingua abbia una propria voce di cache.

```ts title="lib/i18n/server.ts"
import { getLocale } from "gt-next/server";
import { headers } from "next/headers";

import type { CommerceLocale } from "@/lib/config/types";
import { defaultLocale, getCommerceLocale, isSupportedLocale, LOCALE_HEADER_NAME } from "@/lib/i18n";

/** Paese e lingua Shopify per il `[locale]` della pagina; passali a ogni lettura del catalogo. */
export async function getRequestCommerceLocale(): Promise<CommerceLocale> {
  return getCommerceLocale(await getLocale());
}

/** Lo stesso valore, ricavato dall'intestazione del proxy, per il codice dinamico privo di parametri di routing (server action, seed del carrello). */
export async function getForwardedCommerceLocale(): Promise<CommerceLocale> {
  const locale = (await headers()).get(LOCALE_HEADER_NAME) ?? undefined;
  return getCommerceLocale(isSupportedLocale(locale) ? locale : defaultLocale);
}
```

```tsx title="app/[locale]/products/[handle]/page.tsx"
const product = await getProduct({
  handle,
  locale: await getRequestCommerceLocale(),
});
```

Le server action, come l&#39;acquisto rapido e **Load more**, non possono leggere i parametri di routing. In questi casi, leggi il valore con `getForwardedCommerceLocale()`.

### Eseguire i gestori di Hydrogen nella stessa lingua

I gestori del carrello e della ricerca predittiva di Hydrogen ricavano la lingua e il paese dall&#39;oggetto `i18n` del contesto della richiesta. Le richieste come `/api/cart` non hanno un prefisso del locale, perciò il proxy memorizza l&#39;impostazione regionale della pagina in un cookie e la inoltra ai componenti server e alle server action tramite un&#39;intestazione:

```ts title="proxy.ts"
import {
  defaultLocale,
  getCommerceLocale,
  isSupportedLocale,
  LOCALE_COOKIE_NAME,
  LOCALE_HEADER_NAME,
  splitLocalePath,
} from "@/lib/i18n";

const rememberedLocale = request.cookies.get(LOCALE_COOKIE_NAME)?.value;
const requestLocale = resolveRequestLocale(request);
// I prefetch speculativi non devono modificare il carrello del cliente né la lingua memorizzata.
const isPageNavigation =
  request.method === "GET" &&
  isPagePath(pathname) &&
  !request.headers.has("next-router-prefetch") &&
  request.headers.get("purpose") !== "prefetch" &&
  !request.headers.get("sec-purpose")?.includes("prefetch");

// I gestori del carrello e della ricerca di Hydrogen vengono eseguiti nella lingua del cliente.
const requestContext = createCustomerRequestContext(
  request,
  getCommerceLocale(requestLocale),
  requestLocale,
);

// Dopo che handleShopifyRoutes ha rifiutato la richiesta:
const headers = forwardCustomerRefreshAttempt(
  request.nextUrl,
  requestContext.getForwardedRequestHeaders(),
);
headers.set(LOCALE_HEADER_NAME, requestLocale);

const response = rewritePath
  ? NextResponse.rewrite(new URL(`${rewritePath}${request.nextUrl.search}`, request.url), {
      request: { headers },
    })
  : NextResponse.next({ request: { headers } });

// Nella risposta:
if (isPageNavigation && rememberedLocale !== locale) {
  response.cookies.set(LOCALE_COOKIE_NAME, locale, { path: "/", sameSite: "lax" });
}

/** L'impostazione regionale dell'URL per le pagine; l'impostazione regionale memorizzata della pagina per gli endpoint Shopify senza prefisso, come `/api/cart`. */
function resolveRequestLocale(request: NextRequest): string {
  const { pathname } = request.nextUrl;
  const { locale } = splitLocalePath(pathname);
  if (locale !== defaultLocale || isPagePath(pathname)) return locale;
  const remembered = request.cookies.get(LOCALE_COOKIE_NAME)?.value;
  return isSupportedLocale(remembered) ? remembered : defaultLocale;
}
```

Mantieni l&#39;import `forwardCustomerRefreshAttempt` del template da `@/lib/auth/request`. Applicalo prima di scegliere tra `NextResponse.rewrite` e `NextResponse.next`, così anche le pagine dell&#39;account riscritte ricevono l&#39;intestazione del tentativo di refresh e non possono ritentare all&#39;infinito un refresh del token non riuscito.

In `createCustomerRequestContext`, accetta sia l&#39;impostazione regionale di Shopify sia quella della pagina, e passa il prefisso URL dell&#39;impostazione regionale come `i18n.pathPrefix`: `/fr` per gli URL in francese e una stringa vuota per l&#39;impostazione locale predefinita. Senza questo prefisso, Hydrogen non riconosce `/fr/products/hoodie?variant=123` come URL di un prodotto e salta il reindirizzamento alla variante, quindi la pagina potrebbe mostrare la variante predefinita anziché quella indicata nel link:

```ts title="lib/auth/request.ts"
import { defaultLocale } from "@/lib/i18n";

export function createCustomerRequestContext(
  request: Request,
  i18n: CommerceLocale = shopConfig.localization,
  locale: string = defaultLocale,
): ShopifyRequestContext {
  return createShopifyRequestContext({
    i18n: {
      country: i18n.country,
      language: i18n.language,
      // Hydrogen riconosce e reindirizza gli URL dei prodotti che hanno questo prefisso.
      pathPrefix: locale === defaultLocale ? "" : `/${locale}`,
    },
    request,
  });
}
```

I valori predefiniti garantiscono che gli altri chiamanti del template continuino a funzionare. Passa `getCommerceLocale` anche al seed del carrello lato server (`lib/cart/server.ts`), anziché leggere `shopConfig.localization`.

## Tradurre i testi [#copy]

Mantieni i testi inline in ciascun componente, come avviene nel template:

* Racchiudi il JSX in [`<T>`](/docs/react/reference/components/t). Racchiudi i valori dinamici in [`<Var>`](/docs/react/reference/components/var), [`<Num>`](/docs/react/reference/components/num), [`<Currency>`](/docs/react/reference/components/currency) o [`<DateTime>`](/docs/react/reference/components/datetime) e i conteggi in [`<Plural>`](/docs/react/reference/components/plural). [`<T>`](/docs/react/reference/components/t) funziona sia nei Componenti Server sia nei Componenti Client.
* Traduci le stringhe, come i valori di `aria-label`, i metadati e le props, con [`getGT`](/docs/react/nextjs/reference/functions/get-gt) nei Componenti Server e con [`useGT`](/docs/react/reference/hooks/use-gt) nei Componenti Client.
* Contrassegna con [`msg`](/docs/react/reference/functions/msg) le etichette definite al di fuori di un componente, come le opzioni di ordinamento. Risolvile nel punto in cui vengono renderizzate con [`getMessages`](/docs/react/nextjs/reference/functions/get-messages) o [`useMessages`](/docs/react/reference/hooks/use-messages).

```tsx title="app/[locale]/page.tsx"
import { T } from "gt-next";
import { getGT } from "gt-next/server";

export async function generateMetadata(): Promise<Metadata> {
  const gt = await getGT();
  return { title: gt("Home") };
}

export default async function HomePage() {
  const gt = await getGT();
  return (
    <>
      <h1>
        <T>A storefront localized with General Translation</T>
      </h1>
      <ProductsGrid title={gt("Products")} />
    </>
  );
}
```

```tsx title="app/[locale]/search/page.tsx"
<T>
  <Plural
    n={total}
    one={<><Num>{total}</Num> result</>}
    other={<><Num>{total}</Num> results</>}
  />
</T>
```

<Callout type="warn">
  **Attenzione:** la CLI individua le stringhe di `gt()` tracciando la variabile assegnata da [`getGT()`](/docs/react/nextjs/reference/functions/get-gt) o [`useGT()`](/docs/react/reference/hooks/use-gt). Assegnala su una riga dedicata, ad esempio `const gt = await getGT()`. Le stringhe lette dal risultato destrutturato di un `Promise.all` non vengono estratte e vengono renderizzate nella lingua di origine.
</Callout>

Formatta i prezzi di Shopify usando l&#39;impostazione regionale e il codice valuta restituiti da Shopify. La funzione `formatPrice(money, locale)` del template usa `formatMoney` di Hydrogen, quindi 36.95 EUR viene renderizzato come `36,95 €` in francese.

## Tradurre i contenuti del catalogo [#catalog]

Titoli, descrizioni e opzioni dei prodotti provengono da Shopify. Puoi salvarne le traduzioni in Shopify e leggerle con `@inContext(language:)`, che `getCommerceLocale` passa già, oppure includerle nel bundle dello storefront tramite la CLI, come avviene nello storefront di esempio. (Vedi [Tradurre i prodotti Shopify](/docs/integrations/shopify/guides/translating-products)).

## Next steps

- /docs/integrations/shopify/guides/localizing-react-router
- /docs/integrations/shopify/guides/translating-products
- /docs/integrations/shopify/guides/selling-in-markets

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
