Reflow localization (awaiting internal support)

Kind of follow-up of this thread where we talked about Reflow cart localization.

So, here is my hack to support French and English. We can’t talk about a stable or satisfying solution in the time (it’s fragile and highly dependent on eventual changes in the Reflow code itself); it’s the reason why I put it in “Tips & Tricks”.

Well! however, it’s there and it could inspire you for your own use cases. Note that in mine, I didn’t need shipping not taxes, so I masked any element related to these subjects and didn’t localized them. Also, the concerned shop doesn’t manage any product page (I mean with the component called “Product” in BSS). It uses all other components (Product List, Shopping Cart, Add To Cart and the badge called View Cart that I added as custom code before it appears in BSS – so, don’t know it’s exactly the same)

carlang.js (AS IS):

/* EN/FR localization for /shop/* (awaiting Reflow provides it) - elroot, 2022/04
   NB: specialized SwitchCartLang() has to be called from lang.js/SwitchLang() 
       and atc_proxy handler setted-up during shop.js/add_to_cart_in_product_list().
*/

const dict = {
  /* <key> as class or id,  <value> as <original_en>|<fr> */
  /* step #0 (about cart badge leading to cart in pop-up) */
  ".ref-product-remove": "Remove|Supprimer",
  ".ref-summary-footer .ref-button": "Checkout|Paiement",
  ".ref-summary-footer .ref-button .ref-close-button": "Close|Fermer",
  ".ref-notification-content .ref-notification-title": "Product added to cart|Produit ajouté au panier",
  /* step #1 */
  ".ref-message": "Your shopping cart is empty.|Votre panier est vide.",
  ".ref-th .ref-product-col": "Product|Produit",
  ".ref-th .ref-price-col": "Price|Prix",
  ".ref-th .ref-quantity-col": "Quantity|Quantité",
  ".ref-checkout-button": "Checkout|Paiement",
  ".ref-product-remove": "Remove|Supprimer",
  /* step #2 */
  ".ref-back": "← Back to Cart|← Retour au panier",
  ".ref-details label:nth-child(4) span": "Phone|Téléphone",
  ".ref-error-parent label:first-of-type() span": "Country|Pays",
  ".ref-checkout-summary .ref-heading": "Order Summary|Récapitulatif",
  ".ref-next": "Next|Suivant",
  ".ref-note-to-seller span": "Note to seller|Note au vendeur",
  "#ref-field-note-seller::placeholder": "If you have any specific instructions you want to give to the seller, write them here.|Si vous avez des instructions particulières à transmettre au vendeur, écrivez-les ici.",
  /* step #3 */
  ".ref-shipping-form .ref-heading-small": "Shipping Address|Adresse de livraison",
  ".ref-address-widget > label:first-of-type() span": "Name|Nom",  
  ".ref-address-widget > label:nth-child(2) span": "Address|Adresse",  
  ".ref-address-widget > label:nth-child(3) span": "City|Ville", 
  ".ref-standard .ref-row-region label:nth-child(2) span": "Postal Code|Code Postal",
  "div .ref-heading-small": "Payment|Paiement",
  ".ref-standard-payment-buttons div:nth-child(1)": "Credit Card|Carte Bancaire"
}

function InitCartBadgeLangHandler() 
{  // Allow to translate cart pop-up on fly when user clicks on the status badge
   // USE: has to be called on page load of /shop/index.html (where the badge seats)
   // NB: handler not set during SwitchCartLang() since it's called on page load of /shop/cart.html only
   $("#cart-status").on("click", function() {
      const lang = localStorage.getItem("currlang");
      SwitchCartLang(lang);
   });
}

const switch_delay = 500; /* ms */

function SwitchCartLang(lang)
{ // Localize Reflow elements before Stripe stage
  const idx = (lang == "fr") ? 1 : 0;

  setTimeout(function(){
     for (let key in dict) {
       const value = dict[key].split("|")[idx];
       if (key.includes("::placeholder")) {
          /* set placeholder */
          const sel = key.split("::")[0];
          if ($(sel).exists())
            $(sel).attr("placeholder", value);
       }
       else {
          /* set text */
          if ($(key).exists())
              $(key).html(value);
       }
     }
  }, switch_delay /* lets Reflow step renders */);

   // prepare handlers to renew lang adjustment when necessary
   setTimeout(function(){
      /* about single element per class */
      const evt_srcs = [".ref-checkout-button", ".ref-next", ".ref-back"];
      for (let i = 0; i < evt_srcs.length; i++) {
         const elts = $(evt_srcs[i]);
         if (elts.exists()) {
            elts.get(0).addEventListener("click", function() {
               SwitchCartLang(lang);
            });
         }      
      }
      /* about all elements in a class */
      const elts = $(".ref-product-remove");
      for (let j = 0; j < elts.length; j++) {
         elts[j].addEventListener("click", function() {
            SwitchCartLang(lang);
            if ($(".ref-product-remove").length === 1) {
               setTimeout(function(){
                  $(".ref-summary-footer .ref-button").html("Fermer");
               }, switch_delay + 50 /* ensures change comes after SwitchCartLang() ones */);
            }
         });
      }
  }, switch_delay /* lets Reflow step renders */);
}

Basically, you just add this code in a js file for the html pages about Reflow, and call SwitchCartLang on page load of these pages. It assumes you stored a persistent variable called currlang (for “current language”) in local storage. And, of course, you can experience bugs since it has been tested in the website for which I did it only…

1 Like