Query 库
Query 库多语言 WordPress 站点页面翻译(Classic editor)

多语言 WordPress 站点页面翻译(Classic editor)

此 GraphQL Query 有助于创建多语言站点,其中每个站点都是某种语言的翻译版本。内容基于 Classic editor,最适合与 WordPress 多站点网络配合使用。

此 Query 需要在端点上启用嵌套 Mutation

该 Query 必须在主站点(包含源内容的站点)上执行,且该站点必须已安装"Power Extensions"套件。网络中的所有其他站点可以使用免费的 Gato GraphQL 插件。

连接网络站点时使用 Application Password。请务必为可访问所有站点的用户提供 $username$appPassword 变量。

该 Query 获取主站点和外部站点的语言并进行比较:

  • 如果相同,则直接复制所有页面
  • 如果不同,则以翻译后的内容复制所有页面

(这样,如果主站点的语言为 en,而网络中另一个站点也为 en,所有页面仍会被复制。)

然后,它从主站点获取所有页面,并(如有需要)通过对 Google Translate API 发起单次调用,将所有页面批量翻译为目标站点的语言。

最后,将所有这些页面创建到外部站点上。

########################################################################
# 
# Variables:
#   - $username: The username to log into the external site
#   - $appPassword: The application password to log into the external site
#   - $externalSiteURL: The URL of the external site, where all pages will be (translated and) created
#   - (Optional) $pageIDs: Restrict translating/creating the pages with given IDs
#   - (Optional) $pageStatus: Fetch pages with given status
#   - (Optional) $externalSiteGraphQLEndpointPath: Path to the GraphQL endpoint on the external site
#
# *********************************************************************
#
# === Description ===
#
# This Persisted GraphQL query helps create a Multilingual site
# where every site is the translation for some language. The content
# is based on the Classic editor, and it is most suitable with a
# WordPress multisite network.
# 
# It must be executed on the master site, which must have the PRO plugin.
# All other sites in the network can have the free Gato GraphQL plugin.
#
# The query retrieves the language from the main site and from the external
# site, and compares them:
#
#   - If they are the same, simply replicate all pages
#   - If they are different, replicate all pages with translated content
#
#   (This way, if the main site has "en" language, and another site in
#   the network also has "en", all pages are still replicated.)
#
# Then it grabs all the pages from the master site, and (if required) it
# translates them all at once (in bulk) to the destination site's language,
# by executing a single call to the Google Translate API.
#
# Finally it creates all those pages in the external site.
#
########################################################################
 
query InitializeExternalSiteVariables
  @configureWarningsOnExportingDuplicateVariable(enabled: false)
{
  isGutenbergEditorEnabled
    @export(as: "isGutenbergEditorEnabled")
 
  emptyBool: _echo(value: false)
    @export(as: "hasMasterPages")
    @export(as: "executeTranslation")
    @remove
}
 
query ExportData(
  $username: String!
  $appPassword: String!
  $externalSiteURL: URL!
  $externalSiteGraphQLEndpointPath: String! = "/graphql/internal/"
  $pageIDs: [ID!]! = []
  $pageStatus: [CustomPostStatusEnum!]! = [publish]
)
  @depends(on: "InitializeExternalSiteVariables")
  @skip(if: $isGutenbergEditorEnabled)
{
  # Retrieve the language of the content
  siteLanguage
    @export(as: "fromLanguage")
 
  # Generate the authorization header to connect to the external site
  loginCredentials: _sprintf(
    string: "%s:%s",
    values: [$username, $appPassword]
  )
    @remove
  base64EncodedLoginCredentials: _strBase64Encode(
    string: $__loginCredentials
  )
    @remove
  authorizationHeaderValue: _sprintf(
    string: "Basic %s",
    values: [$__base64EncodedLoginCredentials]
  )
    @remove
    @export(as: "authorizationHeaderValue")
  
  # Generate the external site's GraphQL endpoint to connect to
  endpoint: _sprintf(
    string: "%s%s",
    values: [
      $externalSiteURL,
      $externalSiteGraphQLEndpointPath
    ]
  )
    @export(as: "endpoint")
    
  masterPages: pages(filter: { ids: $pageIDs, status: $pageStatus }) {
    id
    emptyArray: _echo(value: [])
      @export(
        as: "rawTitle"
        type: DICTIONARY
      )
      @export(
        as: "rawContent"
        type: DICTIONARY
      )
      @export(
        as: "rawExcerpt"
        type: DICTIONARY
      )
      @remove
  }
 
  hasMasterPages: _notEmpty(value: $__masterPages)
    @export(as: "hasMasterPages")
}
 
query RetrieveAndExportExternalSiteLanguage
  @depends(on: "ExportData")
  @include(if: $hasMasterPages)
{
  # Retrieve the language of the external site
  externalHTTPRequest: _sendGraphQLHTTPRequest(input:{
    endpoint: $endpoint,
    query: """
  
{
  me {
    name
  }
  siteLanguage
}
 
    """,
    options: {
      headers: [
        {
          name: "Authorization",
          value: $authorizationHeaderValue
        }
      ]
    }
  })
  externalSiteLanguage: _objectProperty(
    object: $__externalHTTPRequest,
    by: {
      path: "data.siteLanguage"
    }
  )
    @export(as: "toLanguage")
  
  # Indicate if connecting to the external site was successful
  hasRetrievedExternalSiteLanguage: _notEmpty(
    value: $__externalSiteLanguage
  )
 
  # Only translate the content if the master/destination sites languages are different
  areFromToLanguagesDifferent: _notEquals(
    value1: $fromLanguage
    value2: $__externalSiteLanguage
  )
 
  # Flag to indicate if to translate the content
  executeTranslation: _and(
    values: [
      $__hasRetrievedExternalSiteLanguage,
      $__areFromToLanguagesDifferent,
    ]
  )
    @export(as: "executeTranslation")
}
 
query FetchData(
  $pageIDs: [ID!]! = []
  $pageStatus: [CustomPostStatusEnum!]! = [publish]
)
  @depends(on: "RetrieveAndExportExternalSiteLanguage")
  @include(if: $hasMasterPages)
{
  fetchDataPages: pages(filter: { ids: $pageIDs, status: $pageStatus }) {
    id
 
 
    rawTitle
      @export(
        as: "rawTitle"
        type: DICTIONARY
      )
    rawContent
      @export(
        as: "rawContent"
        type: DICTIONARY
      )
    rawExcerpt
      @export(
        as: "rawExcerpt"
        type: DICTIONARY
      )
  }
}
 
query AdaptData
  @depends(on: "FetchData")
  @include(if: $hasMasterPages)
{
  adaptedToRawTitle: _echo(value: $rawTitle)
    @underEachJSONObjectProperty(
      passValueOnwardsAs: "value"
    )
      @applyField(
        name: "_echo"
        arguments: {
          value: [$value]
        }
        setResultInResponse: true
      )
    @export(as: "adaptedToRawTitle")
  adaptedFromTitle: _echo(value: $rawTitle)
    @underEachJSONObjectProperty
      @applyField(
        name: "_echo"
        arguments: {
          value: [""]
        }
        setResultInResponse: true
      )
    @export(as: "adaptedFromTitle")
 
  adaptedToRawContent: _echo(value: $rawContent)
    @underEachJSONObjectProperty(
      passValueOnwardsAs: "value"
    )
      @applyField(
        name: "_echo"
        arguments: {
          value: [$value]
        }
        setResultInResponse: true
      )
    @export(as: "adaptedToRawContent")
  adaptedFromRawContent: _echo(value: $rawContent)
    @underEachJSONObjectProperty
      @applyField(
        name: "_echo"
        arguments: {
          value: [""]
        }
        setResultInResponse: true
      )
    @export(as: "adaptedFromRawContent")
 
  adaptedToRawExcerpt: _echo(value: $rawExcerpt)
    @underEachJSONObjectProperty(
      passValueOnwardsAs: "value"
    )
      @applyField(
        name: "_echo"
        arguments: {
          value: [$value]
        }
        setResultInResponse: true
      )
    @export(as: "adaptedToRawExcerpt")
  adaptedFromRawExcerpt: _echo(value: $rawExcerpt)
    @underEachJSONObjectProperty
      @applyField(
        name: "_echo"
        arguments: {
          value: [""]
        }
        setResultInResponse: true
      )
    @export(as: "adaptedFromRawExcerpt")
}
 
query TransformData
  @depends(on: "AdaptData")
  @include(if: $hasMasterPages)
{
  transformations: _echo(value: {
    metaRawTitle: {
      from: $adaptedFromTitle,
      to: $adaptedToRawTitle,
    },
    metaRawContent: {
      from: $adaptedFromRawContent,
      to: $adaptedToRawContent,
    },
    metaRawExcerpt: {
      from: $adaptedFromRawExcerpt,
      to: $adaptedToRawExcerpt,
    }
  })
    @if(condition: $executeTranslation)
      @underEachJSONObjectProperty
        @underJSONObjectProperty(by: { key: "to" })
          @underEachJSONObjectProperty
            @underEachArrayItem
              @strTranslate(
                from: $fromLanguage,
                to: $toLanguage
              )
    @export(as: "transformations")
}
 
query PrepareMetaReplacements
  @depends(on: "TransformData")
  @include(if: $hasMasterPages)
{
  transformedMetaTitle: _echo(value: $rawTitle)
    @underEachJSONObjectProperty(
      passKeyOnwardsAs: "pageID"
      affectDirectivesUnderPos: [1, 2, 3]
    )
      @applyField(
        name: "_sprintf",
        arguments: {
          string: "metaRawTitle.to.%s",
          values: [$pageID]
        }
        passOnwardsAs: "titlePath"
      )
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $transformations
          by: { path: $titlePath }
        }
        passOnwardsAs: "transformedPostTitleAsArray"
      )
      @applyField(
        name: "_arrayItem",
        arguments: {
          array: $transformedPostTitleAsArray
          position: 0
        }
        setResultInResponse: true
      )
    @export(
      as: "transformedRawTitle"
    )
 
  transformedMetaRawContent: _echo(value: $rawContent)
    @underEachJSONObjectProperty(
      passKeyOnwardsAs: "pageID"
      affectDirectivesUnderPos: [1, 2, 3]
    )
      @applyField(
        name: "_sprintf",
        arguments: {
          string: "metaRawContent.to.%s",
          values: [$pageID]
        }
        passOnwardsAs: "rawContentPath"
      )
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $transformations
          by: { path: $rawContentPath }
        }
        passOnwardsAs: "transformedPostRawContentAsArray"
      )
      @applyField(
        name: "_arrayItem",
        arguments: {
          array: $transformedPostRawContentAsArray
          position: 0
        }
        setResultInResponse: true
      )
    @export(
      as: "transformedRawContent"
    )
 
  transformedMetaRawExcerpt: _echo(value: $rawExcerpt)
    @underEachJSONObjectProperty(
      passKeyOnwardsAs: "pageID"
      affectDirectivesUnderPos: [1, 2, 3]
    )
      @applyField(
        name: "_sprintf",
        arguments: {
          string: "metaRawExcerpt.to.%s",
          values: [$pageID]
        }
        passOnwardsAs: "rawExcerptPath"
      )
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $transformations
          by: { path: $rawExcerptPath }
        }
        passOnwardsAs: "transformedPostRawExcerptAsArray"
      )
      @applyField(
        name: "_arrayItem",
        arguments: {
          array: $transformedPostRawExcerptAsArray
          position: 0
        }
        setResultInResponse: true
      )
    @export(
      as: "transformedRawExcerpt"
    )
}
 
query ExportMutationInputs(
  $pageIDs: [ID!]! = []
  $pageStatus: [CustomPostStatusEnum!]! = [publish]
)
  @depends(on: "PrepareMetaReplacements")
  @include(if: $hasMasterPages)
{
  exportPages: pages(filter: { ids: $pageIDs, status: $pageStatus }) {
    id
    transformedRawContent: _objectProperty(
      object: $transformedRawContent,
      by: {
        key: $__id
      }
    )
    transformedRawTitle: _objectProperty(
      object: $transformedRawTitle,
      by: {
        key: $__id
      }
    )
    transformedSlug: _echo(value: $__transformedRawTitle)
    transformedRawExcerpt: _objectProperty(
      object: $transformedRawExcerpt,
      by: {
        key: $__id
      }
    )
    input: _echo(value: {
      status: draft,
      title: $__transformedRawTitle,
      slug: $__transformedSlug,
      excerpt: $__transformedRawExcerpt,
      contentAs: {
        html: $__transformedRawContent
      }
    })
      @export(
        as: "createPostMutationInputs"
        type: LIST
      )
  }
}
 
mutation CreatePagesWithTranslationOnExternalSite
  @depends(on: "ExportMutationInputs")
  @include(if: $hasMasterPages)
{
  createExternalSitePageHTTPRequests: _echo(value: $createPostMutationInputs)
    @underEachArrayItem(
      passValueOnwardsAs: "input"
    )
      @applyField(
        name: "_sendGraphQLHTTPRequest"
        arguments: {
          input: {
            endpoint: $endpoint,
            query: """
          
mutation CreatePageFromMasterSite($input: JSONObject!) {
  createPage(input: $input) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    page {
      id
      slug
      title
      content
      status
      url
      excerpt
    }
  }
}
 
            """,
            variables: [
              {
                name: "input",
                value: $input
              }
            ],
            options: {
              headers: [
                {
                  name: "Authorization",
                  value: $authorizationHeaderValue
                }
              ]
            }
          }
        },
        setResultInResponse: true
      )
}