WPML

Query Content per Language From Your Front-End

Every WPGraphQL query gains a language argument. Filter posts, custom post types, taxonomy terms, menus, menu items, and comments by language in a single field – no post-query filtering on the front-end, no double the request volume, no language guessing.

query PostsES {
  posts(where: { language: "es" }) {
    nodes { slug uri title }
  }
}

When you filter a top-level node by language, connected items (categories, tags, custom taxonomies) automatically follow the same language. Results are consistent without extra arguments per nested field.

Want everything regardless of language for a sitemap or aggregate count? Pass language: "all".

Fetch Every Translation of a Node in One Query

The translations field on posts and taxonomy terms returns every other-language version of a node: slug, URI, language code, and any nested fields you ask for. One query, one round-trip, every language version of a page.

That’s the data you need for a language switcher rendered next to the page content itself, without making the front-end follow a chain of related queries.

Multilingual Menus, Taxonomies, Comments, and Language Data

Beyond posts, WPML GraphQL extends the same language argument and translation handling to:

  • Menus and menu items. menus(where: { language: "fr" }) and menuItems(where: { language: "fr" }) for per-language navigation.
  • Taxonomy terms. Categories, tags, and custom taxonomies follow their post’s language by default and can be queried per language directly.
  • Comments. Return comments associated with posts in a specific language.
  • languages and defaultLanguage queries. List every installed language on the site with code, locale, native name, country-flag URL, and home URL. The right data shape for a custom language switcher.

Query a Specific Post by ID or Slug, in Any Language

Two query shapes get a single translated post by its language-specific identifier:

query PostBySlug {
  post(id: "hola-mundo", idType: SLUG) {
    title slug uri
  }
}
query PostById {
  post(id: "2", idType: DATABASE_ID) {
    title slug uri
  }
}

Either form returns the translated post with its translated title, slug, and URI – without separate “is this a translation?” logic on the front-end.

Maintained Against the Current WPGraphQL Release

We tested WPML GraphQL 5.2.0 with WPGraphQL 2.24.1 and WPGraphQL for ACF 3.0.0. The team that maintains WPGraphQL works with us so the multilingual layer keeps moving with the schema. When WPGraphQL ships a new release, WPML GraphQL is right behind it.

Works With ACF When You Add ACFML and WPGraphQL for ACF

Many headless sites build their content model in Advanced Custom Fields and expose it through WPGraphQL. Add ACFML and WPGraphQL for ACF, and your ACF data follows the same language rules as the rest of the schema.

Query an ACF Options Page in Any Language

Options pages sit outside any post, so they take a language argument of their own. Sub-fields inside repeaters and flexible content come back in that language too. The query below reads the offices repeater and the promos flexible content field. Since WPGraphQL for ACF 3.0.0, an options page is in the schema only when you turn on show_in_graphql for it.

query StoreSettingsES {
  storeSettings(language: "es") {
    storeContact {
      heading
      offices { city openingHours }
      promos {
        ... on StoreContactPromosBannerLayout { bannerText }
      }
    }
  }
}

Relationship Fields Return the Translated Post

ACF fields on posts and custom post types do not take a language argument of their own. They follow the language of the request. In the query below, where: { language: "es" } sets that language for the whole query.

A relationship field set to Copy already holds translated IDs. When WPML copies the field to the translation, ACFML swaps each ID for its translation. It keeps the original ID when the translation does not exist yet. You set this preference per field in the ACF field group editor, under Translation preferences. See Relational Fields in our guide to translating ACF custom fields.

query BlendsES {
  posts(where: { language: "es" }) {
    nodes {
      title
      postExtras {
        relatedGuide {
          nodes { ... on Post { title languageCode } }
        }
      }
    }
  }
}

The Spanish post returns the Spanish guide.

Set the language on every request. A query that reads one post by ID or slug carries no language filter. It then runs in the default language, and the related posts come back in the default language too.

How you set the language depends on your WPML URL format. With a domain per language, call that language’s endpoint: https://es.example.com/graphql. With the language parameter, add it to the endpoint: /graphql?lang=es. The directory format has no per-language endpoint, so filter by language inside the query.

When a Translation Is Missing

WPML does not fall back to the default language. If a related post has no translation in the language of the request, it drops out of the result:

{
  "data": {
    "posts": {
      "nodes": [
        {
          "title": "Nuestras mezclas de la casa",
          "postExtras": {
            "relatedGuide": {
              "nodes": [
                { "title": "Guía de compra de espresso", "languageCode": "es" }
              ]
            }
          }
        }
      ]
    }
  }
}

The field points at two guides. Only one of them is translated into Spanish, so the Spanish query returns one. Your front-end gets a shorter list, never a mix of languages. Translate the missing post and it appears in the same query.

The list stays in one language when the post type is translatable. If you set the post type to Display as translated, WPML returns the untranslated guide in the default language. The list then mixes languages.

WPML GraphQL Is Included With WPML

WPML GraphQL ships with Multilingual CMS and WPML Agency. No separate purchase, no per-site fee. Buy WPML once and your headless multilingual stack has its language layer. If you already have WPML, activate WPML GraphQL from your WPML downloads page.