# Localization

Hygraph boasts a flexible localization API that you can use to publish content for all or specific locales in your project.

Hygraph boasts a flexible localization API that you can use to publish content for all or specific locales in your project.

**Warning:**

**Locales are environment specific**. This means their configuration is applied per environment. Take this into consideration if you're working with a project using more than one environment.

Localized content can be managed through the Hygraph UI, or via GraphQL mutations.

**Pro Tip:**

You may need to adjust your permissions at the API level to be able to see all locales.

To find your Public Content API permissions navigate to **Project settings > Access > API Access > Public Content API** and click on the 3-dots context menu to edit your permissions.

![Locale permissions](https://hygraph.com/images/classic-docs/api-reference/content-api/locale-permissions.png)

## Localizing fields

When adding a field that can be localized inside the schema editor, such as a string, mark the field as can be localized, and you will be able to perform all of the localization queries, and mutations outlined below.

![Hygraph Localize Fields](https://hygraph.com/images/classic-docs/api-reference/content-api/localize-field.png)

The model will be updated to contain additional [localized system fields](https://hygraph.com/classic-docs/api-reference/schema/system-fields#localization-fields) that you can use to fetch localized content.

## Fetching localized content

Fetching localized content is done by [fetching content](https://hygraph.com/classic-docs/api-reference/content-api/queries) the same way you are used to. For example, a product model containing localized fields can be queried like so:

```graphql
{
  product(where: { id: "..." }) {
    name
  }
  products {
    name
  }
}
```

The above will return the default locale values for the fields requested.

### Default locale

As shown as above, queried content will always return the default locale, unless told otherwise.

You can set the default locale inside `Settings > Locales`.

![Hygraph default locale](https://hygraph.com/images/classic-docs/api-reference/content-api/default-locale.png)

### Fallback locale(s)

Locales will be returned in the order they are requested, from left to right.

In this example, we will request products with the locales `en`, and `de`.

  **Request**

```graphql
{
  products(locales: [en, de]) {
    id
    locale
    name
  }
}
```

  
  **Response**

```json
{
  "data": {
    "products": [
      {
        "id": "ck3ee0ltu3kfn0b73wbslopia",
        "locale": "en",
        "name": "Unisex Long Sleeve Tees"
      },
      {
        "id": "ck3itjds7hnwo0b66au5rkvm9",
        "locale": "en",
        "name": "Snapback"
      },
      {
        "id": "ck3oqti2stn5o0b20ogmpwxer",
        "locale": "en",
        "name": "Unisex Zip Hoodie"
      },
      {
        "id": "ck3shntzy1xxw0b324jfxcjtl",
        "locale": "en",
        "name": "Mug"
      }
    ]
  }
}
```


### HTTP header

You can pass the `gcms-locales` header when localized content with your required locales.

```js
const fetch = require('cross-fetch');

const headers = {
  'Content-Type': 'application/json',
  'gcms-locales': 'en',
};

const body = JSON.stringify({ query: '{ products { name } }' });

const { products } = await fetch('<your-hygraph-endpoint>', {
  method: 'POST',
  headers,
  body,
});
```

You can also pass an array of locales to `gcms-locales` to define your fallback preference.

### All localizations

Whether you're fetching a [single content entry](https://hygraph.com/classic-docs/api-reference/content-api/queries#fetching-a-single-entry), or [multiple](https://hygraph.com/classic-docs/api-reference/content-api/queries#fetching-multiple-entries), you can fetch all `localizations` of that entry.

  **Request**

```graphql
{
  products {
    id
    name
    localizations {
      id
      name
      locale
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "products": [
      {
        "id": "ck3ee0ltu3kfn0b73wbslopia",
        "name": "Unisex Long Sleeve Tees",
        "localizations": [
          {
            "id": "ck3ee0ltu3kfn0b73wbslopia",
            "name": "Unisex Longsleeve",
            "locale": "de"
          }
        ]
      },
      {
        "id": "ck3itjds7hnwo0b66au5rkvm9",
        "name": "Snapback",
        "localizations": [
          {
            "id": "ck3itjds7hnwo0b66au5rkvm9",
            "name": "Cap",
            "locale": "de"
          }
        ]
      },
      {
        "id": "ck3oqti2stn5o0b20ogmpwxer",
        "name": "Unisex Zip Hoodie",
        "localizations": [
          {
            "id": "ck3oqti2stn5o0b20ogmpwxer",
            "name": "Unisex Hoodie",
            "locale": "de"
          }
        ]
      },
      {
        "id": "ck3shntzy1xxw0b324jfxcjtl",
        "name": "Mug",
        "localizations": [
          {
            "id": "ck3shntzy1xxw0b324jfxcjtl",
            "name": "Tasse mit Print",
            "locale": "de"
          }
        ]
      }
    ]
  }
}
```


Since the root graphql type returns the default locale `en` values, you'll notice the `localizations` response above returns just the `de` content entries.

Pass `includeCurrent: true` inside the `localizations` query arguments to include the default `en` locale.

  **Request**

```graphql
{
  products {
    id
    name
    localizations(includeCurrent: true) {
      id
      name
      locale
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "products": [
      {
        "id": "ck3ee0ltu3kfn0b73wbslopia",
        "name": "Unisex Long Sleeve Tees",
        "localizations": [
          {
            "id": "ck3ee0ltu3kfn0b73wbslopia",
            "name": "Unisex Long Sleeve Tees",
            "locale": "en"
          },
          {
            "id": "ck3ee0ltu3kfn0b73wbslopia",
            "name": "Unisex Longsleeve",
            "locale": "de"
          }
        ]
      },
      {
        "id": "ck3itjds7hnwo0b66au5rkvm9",
        "name": "Snapback",
        "localizations": [
          {
            "id": "ck3itjds7hnwo0b66au5rkvm9",
            "name": "Snapback",
            "locale": "en"
          },
          {
            "id": "ck3itjds7hnwo0b66au5rkvm9",
            "name": "Cap",
            "locale": "de"
          }
        ]
      },
      {
        "id": "ck3oqti2stn5o0b20ogmpwxer",
        "name": "Unisex Zip Hoodie",
        "localizations": [
          {
            "id": "ck3oqti2stn5o0b20ogmpwxer",
            "name": "Unisex Zip Hoodie",
            "locale": "en"
          },
          {
            "id": "ck3oqti2stn5o0b20ogmpwxer",
            "name": "Unisex Hoodie",
            "locale": "de"
          }
        ]
      },
      {
        "id": "ck3shntzy1xxw0b324jfxcjtl",
        "name": "Mug",
        "localizations": [
          {
            "id": "ck3shntzy1xxw0b324jfxcjtl",
            "name": "Mug",
            "locale": "en"
          },
          {
            "id": "ck3shntzy1xxw0b324jfxcjtl",
            "name": "Tasse mit Print",
            "locale": "de"
          }
        ]
      }
    ]
  }
}
```


**Warning:**

This will return all locales where values present. If nothing is found, the default locale will be returned.

## Mutating localized content

Just like you can query localized content, you can also create, update, upsert, and delete localized content using the [Mutations API](https://hygraph.com/classic-docs/api-reference/content-api/mutations).

Let's continue with the products model in our examples below. We can use the [auto-generated mutations](https://hygraph.com/classic-docs/api-reference/content-api/mutations#auto-generated-mutations) for modifying the locales for each entry.

### Create a localization

```graphql
mutation {
  updateProduct(
    where: { id: "..." }
    data: {
      localizations: {
        create: { locale: de, data: { name: "Tasse mit Print" } }
      }
    }
  ) {
    id
  }
}
```

**Note:**

You'll notice above we are using the `update[Model]` mutation to "create" a locale. This is because the existing entry is the default locale, and you can create additional localized content for fields on that entry.

You can also pass an array of localizations for locales that aren't your projects default. For example, here we create localizations for both `de`, and `es`.

```graphql
mutation {
  updateProduct(
    where: { id: "..." }
    data: {
      localizations: {
        create: [
          { locale: de, data: { name: "Tasse mit Print" } }
          { locale: es, data: { name: "Taza con estampado" } }
        ]
      }
    }
  ) {
    id
  }
}
```

The examples here assume you already have a product that you can update. It is possible to create a new entry, with the base locale, and the localized content via `localizations` at the same time:

```graphql
mutation {
  createProduct(
    data: {
      name: "Mug"
      localizations: {
        create: [
          { locale: de, data: { name: "Tasse mit Print" } }
          { locale: es, data: { name: "Taza con estampado" } }
        ]
      }
    }
  ) {
    id
    localizations(includeCurrent: true) {
      title
    }
  }
}
```

### Update a localization

```graphql
mutation {
  updateProduct(
    where: { id: "..." }
    data: { localizations: { update: { locale: en, data: { name: "Mug" } } } }
  ) {
    id
  }
}
```

### Upsert a localization

Just like you can create, or update content entries by unique filters, you can either also upsert localizations. Simply pass the `locale` you want to update, or create if it does not exist.

```graphql
mutation {
  createProduct(
    where: { id: "..." }
    data: {
      localizations: {
        upsert: {
          locale: de
          create: { name: "Tasse mit Print" }
          update: { name: "Tasse mit Print" }
        }
      }
    }
  ) {
    id
  }
}
```

### Delete a localization

To delete a localization, you need to use an update mutation, like so:

```graphql
mutation {
  updatePost(
    where: {
      id: "..."
    }
    data: {
      localizations: {
        delete: [de]
      }
    }
  )
}
```

**Warning:**
It is not possible to delete the default localization.
