# General Translation Integrations: Traduire les produits Shopify
URL: https://generaltranslation.com/fr/docs/integrations/shopify/guides/translating-products.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Comment traduire le contenu des produits Shopify avec General Translation, puis le stocker dans Shopify ou l’intégrer au bundle de votre vitrine.

Les titres, descriptions et options des produits proviennent de Shopify et non de votre code : `gt-react` et `gt-next` ne les traduisent donc pas. Traduisez-les une seule fois, puis servez-les depuis l’un des deux emplacements suivants.

## Que choisir et quand [#choosing]

* **Stockez les traductions dans Shopify** si les marchands modifient souvent le catalogue. Un script enregistre les traductions via l’Admin API, les vitrines les récupèrent avec `@inContext(language:)`, et les modifications du catalogue ne nécessitent pas de nouvelle compilation de la vitrine.
* **Intégrez les traductions au bundle de la vitrine** si vous n’avez pas accès à l’administration Shopify, ou si vous souhaitez que les traductions du catalogue soient relues et déployées avec votre code. La CLI traduit un fichier JSON exporté lors de la même exécution que vos textes. C’est l’approche retenue par la vitrine d’exemple.

*Remarque : le tableau de bord ne propose pas de connexion Shopify hébergée. Dans les deux cas, vous effectuez l’export vous-même avec vos propres informations d’authentification Shopify et General Translation.*

## a) Stocker les traductions dans Shopify [#store-in-shopify]

Shopify stocke une traduction par paramètre régional pour chaque champ d’une ressource. Un script exporte le texte source via l’Admin API, le traduit avec [`translateMany`](/docs/platform/core/reference/gt-class-methods/translation/translate-many), puis réenregistre les résultats dans Shopify.

### Avant de commencer

Il vous faut :

* Les langues cibles ajoutées et publiées dans l’administration Shopify, sous **Settings &gt; Languages**.
* Un jeton d’accès à l’Admin API de Shopify, issu d’une application installée sur la boutique et disposant des scopes `read_translations`, `write_translations` et `read_locales`. Un jeton de la Storefront API ne permet pas d’écrire des traductions.
* `generaltranslation` installé, ainsi qu’une clé API de projet disposant de l’autorisation **Traduction à l’exécution** (`project:translations:generate`). (Consultez le [Démarrage rapide](/docs/platform/core/quickstart) de la bibliothèque Core.)

Conservez le jeton Admin et la clé API dans l’environnement de votre script. Ne les ajoutez jamais à l’environnement de la vitrine ni aux bundles destinés au navigateur.

### Exporter le contenu source

Interrogez `translatableResources` pour chaque type de ressource que vous traduisez. Chaque champ renvoie sa `key`, sa `value` source et un `digest` qui identifie exactement ce texte source.

```graphql title="Admin API"
query CatalogExport($type: TranslatableResourceType!, $after: String) {
  translatableResources(first: 50, after: $after, resourceType: $type) {
    nodes {
      resourceId
      translatableContent { key value digest locale }
      translations(locale: "fr") { key value outdated }
    }
    pageInfo { hasNextPage endCursor }
  }
}
```

Utilisez des types de ressources tels que `PRODUCT`, `PRODUCT_OPTION` et `PRODUCT_OPTION_VALUE`, et paginez les résultats avec `endCursor`. Conservez les digests : vous en aurez besoin pour enregistrer les traductions.

### Traduire avec General Translation

Envoyez les champs en texte brut, comme les titres de produits, les types de produits, les titres et descriptions SEO, ainsi que les noms et valeurs d’options, à [`translateMany`](/docs/platform/core/reference/gt-class-methods/translation/translate-many). Ajoutez [`metadata.context`](/docs/platform/core/reference/types/entry-metadata#context) pour que les libellés courts soient correctement traduits.

```ts title="scripts/translate-catalog.ts"
import { GT } from 'generaltranslation';

const gt = new GT({
  apiKey: process.env.GT_API_KEY,
  projectId: process.env.GT_PROJECT_ID,
  sourceLocale: 'en',
});

const results = await gt.translateMany(
  fields.map((field) => ({
    source: field.value,
    metadata: {
      context: `Shopify ${field.resourceType} ${field.key}. Preserve product brand names, measurements, and model numbers.`,
    },
  })),
  { sourceLocale: 'en', targetLocale: 'fr' }
);
```

Les résultats sont renvoyés dans l&#39;ordre d&#39;entrée, et chacun indique individuellement s&#39;il a réussi ou échoué. Relancez les entrées en échec au lieu de les enregistrer.

Les champs de texte enrichi, comme le `body_html` d&#39;un produit, contiennent du HTML. La traduction adaptée au format via [`metadata.fileFormat`](/docs/platform/core/reference/types/entry-metadata#file-format) ne prend en charge que les documents Markdown et MDX : n&#39;envoyez donc pas de HTML brut à [`translateMany`](/docs/platform/core/reference/gt-class-methods/translation/translate-many) sans une étape qui en préserve le balisage.

### Enregistrer les traductions dans Shopify

Enregistrez chaque traduction à l&#39;aide de la mutation [`translationsRegister`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/translationsRegister) de l&#39;Admin API. Transmettez le digest de la source dans `translatableContentDigest` : Shopify rejettera ainsi toute traduction dont la source a été modifiée depuis l&#39;export.

```graphql title="Admin API"
mutation CatalogRegister($resourceId: ID!, $translations: [TranslationInput!]!) {
  translationsRegister(resourceId: $resourceId, translations: $translations) {
    translations { key locale value outdated }
    userErrors { field code }
  }
}
```

```json title="Variables"
{
  "resourceId": "gid://shopify/Product/123",
  "translations": [
    {
      "locale": "fr",
      "key": "title",
      "value": "Sweat à capuche en coton",
      "translatableContentDigest": "<digest from export>"
    }
  ]
}
```

Utilisez le code de langue de Shopify pour `locale`, qui peut différer de votre paramètre régional General Translation. (Voir [Codes de paramètres régionaux](/docs/integrations/shopify/reference/locale-handling#locale-codes)).

<Callout type="warn">
  `translationsRegister` remplace la traduction existante pour cette clé et ce paramètre régional, y compris les traductions saisies par un marchand dans l’interface d’administration ou écrites par une autre application. Avant toute écriture, comparez la traduction actuelle à la valeur enregistrée par votre script lors de sa dernière exécution, et ignorez les champs que vous n’avez pas écrits vous-même.
</Callout>

### Lire les traductions dans la vitrine

Ajoutez `@inContext(language: $language)` aux requêtes du catalogue et transmettez le `LanguageCode` Shopify correspondant au paramètre régional. Shopify renvoie la valeur traduite si elle existe, sinon la valeur source. Le client Storefront de Hydrogen renseigne `$language` à partir du contexte de la requête. (Voir [Localiser Shopify Hydrogen avec React Router](/docs/integrations/shopify/guides/localizing-react-router#storefront-language)).

Le contenu traduit du catalogue s&#39;affiche dès que les caches de Shopify et de la vitrine sont actualisés, sans qu&#39;un nouveau déploiement soit nécessaire.

### Maintenir les traductions à jour

Lorsqu&#39;un marchand modifie un produit, le digest de ses champs change et Shopify marque les traductions existantes comme `outdated`. Relancez l&#39;export, ne traduisez que les champs dont le digest a changé ou qui n&#39;ont pas encore de traduction, puis enregistrez les résultats.

## b) Intégrer les traductions au bundle de la vitrine [#bundle]

*Remarque : ces exemples proviennent de la vitrine d’exemple Next.js, qui reprend la configuration des paramètres régionaux du [guide Next.js](/docs/integrations/shopify/guides/localizing-nextjs).*

Exportez le texte du catalogue avec la Storefront API, en utilisant le texte source lui-même comme clé. Enregistrez les libellés courts (titres, noms et valeurs d’options, texte alternatif) et le texte enrichi (descriptions, corps de pages) dans des fichiers distincts, pour que seuls les libellés soient envoyés au navigateur. Nettoyez le texte enrichi exactement comme la vitrine le fait lors de l’affichage, afin que les clés correspondent :

```ts title="scripts/export-catalog.ts"
const labels = new Set<string>();
const content = new Set<string>();
for (const product of catalog.products.nodes) {
  labels.add(product.title).add(product.productType);
  content.add(product.description).add(sanitizeShopifyHtml(product.descriptionHtml));
  for (const image of product.images.nodes) if (image.altText) labels.add(image.altText);
  for (const option of product.options) {
    labels.add(option.name);
    for (const value of option.optionValues) labels.add(value.name);
  }
}

async function writeCatalog(file: string, texts: Set<string>): Promise<number> {
  const entries = [...texts].filter((text) => text.trim()).sort((a, b) => a.localeCompare(b, "en"));
  await writeFile(
    new URL(`../catalog/en/${file}`, import.meta.url),
    `${JSON.stringify(Object.fromEntries(entries.map((text) => [text, text])), null, 2)}\n`,
  );
  return entries.length;
}
```

Ajoutez les fichiers exportés sous `files.json` dans `gt.config.json`, à côté de votre entrée `files.gt` existante, afin que [`npx gt translate`](/docs/cli/reference/commands/translate) génère `catalog/<locale>/labels.json` et `catalog/<locale>/content.json` lors de la même exécution que vos textes :

```json title="gt.config.json"
{
  "files": {
    "json": { "include": ["catalog/[locale]/labels.json", "catalog/[locale]/content.json"] }
  }
}
```

Recherchez les traductions à partir du texte source en direct et utilisez-le comme valeur de repli : ainsi, tout contenu modifié dans Shopify après le dernier export affiche son texte actuel :

```ts title="lib/catalog/index.ts"
/** Recherche le texte du marchand à partir de sa source anglaise actuelle, et renvoie cette source lorsqu'aucune traduction n'existe. */
export function translateCatalogText(catalog: Catalog, text: string): string;
export function translateCatalogText(catalog: Catalog, text: string | undefined): string | undefined;
export function translateCatalogText(catalog: Catalog, text: string | undefined) {
  return (text && catalog[text]) || text;
}
```

```ts title="lib/catalog/server.ts"
/** Libellés courts (titres, noms et valeurs d'options, texte alternatif) pour les composants client tels que le panier. */
export function getCatalogLabels(locale: string): Catalog {
  return catalogs[locale]?.labels ?? {};
}

/** Renvoie une fonction de traduction des textes marchands Shopify dans le paramètre régional de la requête. */
export async function getCatalogText() {
  const catalog = catalogs[await getLocale()];
  const merged: Catalog = catalog ? { ...catalog.content, ...catalog.labels } : {};
  function ct(text: string): string;
  function ct(text: string | undefined): string | undefined;
  function ct(text: string | undefined) {
    return translateCatalogText(merged, text);
  }
  return ct;
}
```

* Transmettez le texte traduit à [`<T>`](/docs/react/reference/components/t) via [`<Var>`](/docs/react/reference/components/var), et non sous forme de texte source.
* Pour les composants client comme le panier et la recherche prédictive, transmettez `getCatalogLabels(locale)` à un fournisseur de contexte dans la mise en page. N&#39;envoyez au navigateur ni texte enrichi ni catalogues d&#39;autres paramètres régionaux.
* Conservez les valeurs d&#39;option dans leur langue source dès qu&#39;elles servent à sélectionner une variante, à construire une URL ou à communiquer avec Shopify. Ne traduisez que le libellé affiché.
* Pour orienter la traduction des noms de produits, par exemple pour conserver des termes de marque ou traduire un nom de vêtement, ajoutez des termes de glossaire et des instructions personnalisées au groupe de contexte du projet dans le tableau de bord.

## Next steps

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

## Sitemap

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