Shopify / js-buy-sdk

The JS Buy SDK is a lightweight library that allows you to build ecommerce into any website. It is based on Shopify's API and provides the ability to retrieve products and collections from your shop, add products to a cart, and checkout.
https://shopify.github.io/js-buy-sdk
MIT License
984 stars 259 forks source link

React-Shopify Translations | How to get products in a second language from Shopify #789

Open a5okol opened 3 years ago

a5okol commented 3 years ago

Hello everyone. I'm trying to get products in the second language from Shopify store.

The Storefront API states that the HTTP request header must contain Accept-Language: de, in my case (in React), the settings should look like this: https://shopify.dev/tutorials/manage-app-translations-with-admin-api#storefront-api-translation-header

const clientWithTranslatedContent = Client.buildClient({
  domain: 'your-shop-name.myshopify.com',
  storefrontAccessToken: 'your-storefront-access-token',
  language: 'de' // Accept-Language
});

How it have to work you can find here: https://github.com/Shopify/js-buy-sdk/blob/update-language-setting/src/client.js

I'm using Shopify Webhook API version 2020-07 (Latest). Here https://github.com/gatsbyjs/gatsby/issues/24173#issuecomment-646820211 I found information that in version 2020-04 Accept-Language header supports translations, but it doesn't work in my case.

In building an application, I always receive goods with default translation (EN).

a5okol commented 3 years ago

The problem was caused by the "gatsby-source-shopify" plugin that generates pages in gatsby-node.js. It doesn't take into account Accept-Language in the header of HTTP requests. To solve the problem, my team has finalized this plugin.

Here's a link: https://github.com/alex-borodin-vtlabs/gatsby-source-shopify-translated

pinktonio commented 3 years ago

@a5okol thanks for the plugin. I can now query products with different languages. However initializing the client with the js-buy-sdk and specifying a language property does not list my lineItems in checkout in that specified language. It still only retrieves them in the primary language set in shopify.

mattia85 commented 3 years ago

Hi, I'm still having the same problem, lineItems elements inside the checkout object are not translated, shopify buy sdk sends the right header accept-language: es-es but this doesn't take any effect. Do you have any updates about this issue?

Thank you

arobbins commented 3 years ago

Would love to know more about this as well...

mattia85 commented 3 years ago

Would love to know more about this as well...

Sure, these are the steps to reproduce the problem.

  1. Add a second language to your Shopify (under Settings > Store Languages).
  2. Translate some product fields using langify application or using the Shopify api.
  3. Inside you frontend create the shopify-buy client passing the language code (no the default one).
    const shopifyBuyClient = Client.buildClient({
    domain: 'your-shop-name.myshopify.com',
    storefrontAccessToken: 'your-storefront-access-token',
    language: 'it-IT'
    });
  4. Add the translated product inside the cart using shopifyBuyClient
  5. Take a look to the checkout object returned from the addLineItems call, the products fields inside lineItems array are not translated.

I hope it's clear now. Thank you.

nadinagray commented 1 year ago

we're also facing this issue, would love any updates-- specifically would love to use the storefront api / shopify-buy sdk, and not have to involve another integration w/ shopify admin api (which i understand may included translate & adapt access)

DerBasler commented 9 months ago

I have the same issue now. According to: https://shopify.github.io/buy-button-js/customization/#:~:text=No%20configurable%20text. It is not possible to configure the Text which makes sense but you have to bool option of: title which I put on true. If I check the graphQl requests: First request (checkout request): fragment VariantFragment on ProductVariant { id,title,price { amount,currencyCode },priceV2: price { amount,currencyCode },weight,available: availableForSale,sku,compareAtPrice { amount,currencyCode },compareAtPriceV2: compareAtPrice { amount,currencyCode },image { id,src: url,altText,width,height },selectedOptions { name,value },unitPrice { amount,currencyCode },unitPriceMeasurement { measuredType,quantityUnit,quantityValue,referenceUnit,referenceValue } },fragment DiscountApplicationFragment on DiscountApplication { __typename,targetSelection,allocationMethod,targetType,value { ... on MoneyV2 { amount,currencyCode },... on PricingPercentageValue { percentage } },... on ManualDiscountApplication { title,description },... on DiscountCodeApplication { code,applicable },... on ScriptDiscountApplication { title },... on AutomaticDiscountApplication { title } },fragment AppliedGiftCardFragment on AppliedGiftCard { amountUsed { amount,currencyCode },amountUsedV2: amountUsed { amount,currencyCode },balance { amount,currencyCode },balanceV2: balance { amount,currencyCode },presentmentAmountUsed { amount,currencyCode },id,lastCharacters },fragment VariantWithProductFragment on ProductVariant { ...VariantFragment,product { id,handle } },fragment MailingAddressFragment on MailingAddress { id,address1,address2,city,company,country,firstName,formatted,lastName,latitude,longitude,phone,province,zip,name,countryCode: countryCodeV2,provinceCode },fragment CheckoutFragment on Checkout { id,ready,requiresShipping,note,paymentDue { amount,currencyCode },paymentDueV2: paymentDue { amount,currencyCode },webUrl,orderStatusUrl,taxExempt,taxesIncluded,currencyCode,totalTax { amount,currencyCode },totalTaxV2: totalTax { amount,currencyCode },lineItemsSubtotalPrice { amount,currencyCode },subtotalPrice { amount,currencyCode },subtotalPriceV2: subtotalPrice { amount,currencyCode },totalPrice { amount,currencyCode },totalPriceV2: totalPrice { amount,currencyCode },completedAt,createdAt,updatedAt,email,discountApplications (first: 10) { pageInfo { hasNextPage,hasPreviousPage },edges { node { __typename,...DiscountApplicationFragment } } },appliedGiftCards { ...AppliedGiftCardFragment },shippingAddress { ...MailingAddressFragment },shippingLine { handle,price { amount,currencyCode },priceV2: price { amount,currencyCode },title },customAttributes { key,value },order { id,processedAt,orderNumber,subtotalPrice { amount,currencyCode },subtotalPriceV2: subtotalPrice { amount,currencyCode },totalShippingPrice { amount,currencyCode },totalShippingPriceV2: totalShippingPrice { amount,currencyCode },totalTax { amount,currencyCode },totalTaxV2: totalTax { amount,currencyCode },totalPrice { amount,currencyCode },totalPriceV2: totalPrice { amount,currencyCode },currencyCode,totalRefunded { amount,currencyCode },totalRefundedV2: totalRefunded { amount,currencyCode },customerUrl,shippingAddress { ...MailingAddressFragment },lineItems (first: 250) { pageInfo { hasNextPage,hasPreviousPage },edges { cursor,node { title,variant { ...VariantWithProductFragment },quantity,customAttributes { key,value } } } } },lineItems (first: 250) { pageInfo { hasNextPage,hasPreviousPage },edges { cursor,node { id,title,variant { ...VariantWithProductFragment },quantity,customAttributes { key,value },discountAllocations { allocatedAmount { amount,currencyCode },discountApplication { __typename,...DiscountApplicationFragment } } } } } },query ($id:ID!) { node (id: $id) { __typename,...CheckoutFragment } }

Return me: data -> node -> lineItems -> edges[0] -> node -> title -> not translated title

And the second request: fragment VariantFragment on ProductVariant { id,title,price { amount,currencyCode },priceV2: price { amount,currencyCode },weight,available: availableForSale,sku,compareAtPrice { amount,currencyCode },compareAtPriceV2: compareAtPrice { amount,currencyCode },image { id,src: url,altText,width,height },selectedOptions { name,value },unitPrice { amount,currencyCode },unitPriceMeasurement { measuredType,quantityUnit,quantityValue,referenceUnit,referenceValue } },fragment ProductFragment on Product { id,availableForSale,createdAt,updatedAt,descriptionHtml,description,handle,productType,title,vendor,publishedAt,onlineStoreUrl,options { id,name,values },images (first: 250) { pageInfo { hasNextPage,hasPreviousPage },edges { cursor,node { id,src: url,altText,width,height } } },variants (first: 250) { pageInfo { hasNextPage,hasPreviousPage },edges { cursor,node { ...VariantFragment } } } },query ($id:ID!) { node (id: $id) { __typename,...ProductFragment } }

Returns me: data -> node -> title -> translated title

The main difference is that request which gets the checkout gets the product like that: fragment VariantWithProductFragment on ProductVariant { ...VariantFragment product { id handle } }

While the second request gets it like: fragment ProductFragment on Product { id availableForSale createdAt updatedAt descriptionHtml description handle productType title vendor publishedAt onlineStoreUrl options { id name values } images(first: 250) { pageInfo { hasNextPage hasPreviousPage } edges { cursor node { id src: url altText width height } } } variants(first: 250) { pageInfo { hasNextPage hasPreviousPage } edges { cursor node { ...VariantFragment } } } } The title from the first request the "checkout request" is used which is not translated.

So if anyone finds anything else please let me know I will post my progress if I find something.