[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"footer-homepage":3,"footer-settings":84,"footer-integrations":220,"main-navigation":1197,"blog-post-nav-nav":1814,"blog-post-nav-[USE LATEST FEATURED]":1836,"blog-test-alerts-using-stomp-over-websocket-in-cypress-e2e-tests":1856},{"status":4,"header_badges":5,"footer_badges":27,"footer_secured_badges":34,"slider_badges":48},"published",[6,15,21],{"id":7,"status":4,"sort":8,"link":9,"title":10,"badgeType":11,"badgeName":12,"metadata":8,"image":13},1,null,"https:\u002F\u002Fwww.g2.com\u002Fproducts\u002Flocalazy\u002Freviews","Best meets requirements","Other","G2-winter-24-best-meets-requirments",{"id":14},"8d5dd6fd-6995-4c92-8219-a6ed5ba6acdc",{"id":16,"status":4,"sort":8,"link":9,"title":17,"badgeType":11,"badgeName":18,"metadata":8,"image":19},2,"Best support","G2-winter-24-best-support",{"id":20},"e59dd465-84d9-45c7-987d-dd4048fd6992",{"id":22,"status":4,"sort":8,"link":9,"title":23,"badgeType":11,"badgeName":24,"metadata":8,"image":25},3,"Easiest admin","G2-winter-24-easiest-admin",{"id":26},"5f12c4c8-bec0-47cf-87b4-a4502e9f1bd2",[28],{"id":29,"status":4,"sort":8,"link":9,"title":30,"badgeType":11,"badgeName":31,"metadata":8,"image":32},12,"Users love us","Users love us 25",{"id":33},"232416a5-86ba-4be6-85a5-b88802003d53",[35,42],{"id":36,"status":4,"sort":8,"link":37,"title":38,"badgeType":11,"badgeName":39,"metadata":8,"image":40},11,"https:\u002F\u002Fsprinto.com\u002Fget-iso-27001\u002F","Sprinto ISO 27001","Sprinto ISO 27001 certificate",{"id":41},"c1c6c06c-6caf-4b78-8a7e-9606c395eb61",{"id":43,"status":4,"sort":8,"link":44,"title":45,"badgeType":11,"badgeName":45,"metadata":8,"image":46},13,"https:\u002F\u002Fwww.aicpa.org\u002Fsoc4so","SOC certificate",{"id":47},"4f4bc0a6-09a0-41df-8295-8f990d96d941",[49,56,61,66,71,76,82],{"id":50,"status":4,"sort":8,"link":9,"title":51,"badgeType":11,"badgeName":52,"metadata":53,"image":54},5,"Most likely to recommend","a","",{"id":55},"da055731-3f11-4fc7-96f2-c11c0b84c831",{"id":57,"status":4,"sort":8,"link":9,"title":58,"badgeType":11,"badgeName":8,"metadata":8,"image":59},6,"EMEA High Performer",{"id":60},"586fb488-81f2-41db-a4e8-ef309e50c0e6",{"id":62,"status":4,"sort":8,"link":9,"title":63,"badgeType":11,"badgeName":8,"metadata":8,"image":64},7,"Ease of Doing Business With",{"id":65},"bfa26865-430e-463d-9886-cb56a8a8ecf6",{"id":67,"status":4,"sort":8,"link":9,"title":68,"badgeType":11,"badgeName":8,"metadata":8,"image":69},8,"High Performer",{"id":70},"2cc1ba0f-c23a-4c97-ad4a-a655c97466fe",{"id":72,"status":4,"sort":8,"link":9,"title":73,"badgeType":11,"badgeName":8,"metadata":8,"image":74},9,"Fastest Implementation",{"id":75},"6f297758-1c95-45f4-a6e9-528319897132",{"id":77,"status":4,"sort":8,"link":78,"title":79,"badgeType":11,"badgeName":8,"metadata":8,"image":80},10,"https:\u002F\u002Fwww.intercert.com\u002Fservices\u002Fgovernance-risk-compliance\u002Fiso-iec-27001","Intercert ISO 27001",{"id":81},"0521a5f1-e1f2-4da6-a2bc-dc92773f2a7b",{"id":36,"status":4,"sort":8,"link":37,"title":38,"badgeType":11,"badgeName":39,"metadata":8,"image":83},{"id":41},{"id":7,"status":4,"security_section_title":85,"loved_section_title":86,"columns":87,"social_links":180,"policy_links":210},"Secured & trusted","Loved by users",[88,102,119,141,145],{"id":7,"status":4,"sort":8,"title":89,"column_key":90,"links":91},"Localazy","connect",[92,95,98],{"id":36,"status":4,"sort":7,"title":93,"url":94},"Book a demo","___LOCALAZY_MEETING_URL___",{"id":29,"status":4,"sort":16,"title":96,"url":97},"Contact","\u002Fcontact",{"id":99,"status":4,"sort":22,"title":100,"url":101},21,"About us","\u002Fabout-us",{"id":16,"status":4,"sort":8,"title":103,"column_key":104,"links":105},"Programs","programs",[106,110,113,116],{"id":7,"status":4,"sort":107,"title":108,"url":109},4,"Partner Program","\u002Fpartnership",{"id":16,"status":4,"sort":50,"title":111,"url":112},"Ambassador Program","\u002Fambassador",{"id":22,"status":4,"sort":57,"title":114,"url":115},"Startup Program","\u002Ffor\u002Fstartups",{"id":107,"status":4,"sort":62,"title":117,"url":118},"Nonprofits","\u002Ffor\u002Fnonprofit",{"id":22,"status":4,"sort":8,"title":120,"column_key":121,"links":122},"Use Cases","use_cases",[123,126,129,132,135,138],{"id":50,"status":4,"sort":67,"title":124,"url":125},"Software Localization","\u002Fterm\u002Fsoftware-localization",{"id":57,"status":4,"sort":72,"title":127,"url":128},"Machine Translation Services","\u002Ffeatures\u002Fmachine-translation",{"id":62,"status":4,"sort":77,"title":130,"url":131},"Translation API","\u002Ffeatures\u002Ftranslation-api",{"id":67,"status":4,"sort":36,"title":133,"url":134},"Crowdsourced Translations","\u002Ffeatures\u002Fshare-tm",{"id":72,"status":4,"sort":29,"title":136,"url":137},"Figma i18n & localization","\u002Ffeatures\u002Ffigma-localization-plugin",{"id":77,"status":4,"sort":43,"title":139,"url":140},"Translation as a Service","\u002Fterm\u002Ftranslation-service",{"id":107,"status":4,"sort":8,"title":142,"column_key":143,"links":144},"Integrations","integrations",[],{"id":50,"status":4,"sort":8,"title":146,"column_key":147,"links":148},"Resources","resources",[149,153,157,161,165,169,173,177],{"id":43,"status":4,"sort":150,"title":151,"url":152},14,"Documentation","\u002Fdocs",{"id":150,"status":4,"sort":154,"title":155,"url":156},15,"Dictionary","\u002Fdictionary",{"id":154,"status":4,"sort":158,"title":159,"url":160},16,"Case Studies","\u002Fcase-study",{"id":158,"status":4,"sort":162,"title":163,"url":164},17,"Discussion forum","___DISCUSS_URL___",{"id":162,"status":4,"sort":166,"title":167,"url":168},18,"Localization Blog","\u002Fblog",{"id":166,"status":4,"sort":170,"title":171,"url":172},19,"FAQ","\u002Ffaq",{"id":170,"status":4,"sort":174,"title":175,"url":176},20,"Pricing","\u002Fpricing",{"id":174,"status":4,"sort":99,"title":178,"url":179},"Brand assets","https:\u002F\u002Fdrive.google.com\u002Fdrive\u002Fu\u002F1\u002Ffolders\u002F1tZqsZHBlGelz7A2FwTsiwrs4j3sd9HTk",[181,186,191,196,201,206],{"id":7,"status":4,"sort":8,"platform":182,"icon":183,"url":184,"label":185},"feed","rss","\u002Ffeed.xml","Localazy RSS Feed",{"id":16,"status":4,"sort":8,"platform":187,"icon":188,"url":189,"label":190},"facebook","fb-logo","https:\u002F\u002Fwww.facebook.com\u002Flocalazy\u002F","Localazy facebook",{"id":22,"status":4,"sort":8,"platform":192,"icon":193,"url":194,"label":195},"github","github-logo","https:\u002F\u002Fgithub.com\u002Flocalazy","Localazy GitHub",{"id":107,"status":4,"sort":8,"platform":197,"icon":198,"url":199,"label":200},"x","x-twitter","https:\u002F\u002Fx.com\u002Flocalazy","Localazy X",{"id":50,"status":4,"sort":8,"platform":202,"icon":203,"url":204,"label":205},"linkedin","linkedin-logo","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002F37836599\u002F","Localazy LinkedIn",{"id":57,"status":4,"sort":8,"platform":207,"icon":208,"url":164,"label":209},"discourse","discourse-logo","Localazy Discourse",[211,214,217],{"id":7,"status":4,"sort":8,"title":212,"url":213,"action":8},"Privacy policy","\u002Fprivacy-policy",{"id":16,"status":4,"sort":8,"title":215,"url":216,"action":8},"Terms & Conditions","\u002Fterms-and-conditions",{"id":22,"status":4,"sort":8,"title":218,"url":8,"action":219},"Cookies","cookie-consent",[221,387,468,579,671,755,847,940,1029,1136],{"id":222,"status":4,"created_on":223,"modified_on":224,"name":225,"slug":226,"description":227,"docs_link":228,"priority":8,"has_sdk":229,"sort":22,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":231,"show_in_spa":230,"is_file_format":229,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":232,"tile_subtitle":233,"tile_description":234,"is_enterprise":229,"is_popular":229,"primary_use_case":8,"hierarchy_handling":8,"best_for":8,"file_extension":8,"format_code_example":8,"format_to_extension":235,"upload_features":237,"icon":238,"meta_image":240,"primary_tag":242,"tags":261,"integration_methods":281,"recommended_methods":371,"default_integration_method":372,"faq_categories":379,"translations":385,"platforms_id":222},33,"2022-03-18T08:09:24.000Z","2025-02-26T13:36:08.000Z","React","react","Manage your React app translations with Localazy, a continuous localization tool. React i18n done right. ","\u002Fdocs\u002Fcli\u002Fjson-format",false,true,"JSON format support","CLI support","react-i18next and more","Use Localazy to translate your React projects with your favorite i18n library.",{"json":236},"json",[],{"id":239},"26757a90-88a3-4a94-b587-9f38614ed3bd",{"id":241},"a97492ec-ee8d-429c-bf66-d0fe59b6e5c9",{"id":50,"status":4,"sort":16,"created_on":243,"label":244,"hidden":229,"icon":245,"translations":247},"2022-03-17T12:23:44.000Z","Web apps",{"id":246},"c9e70e4f-8136-432a-8d82-53c3501a9eb4",[248,250,254,258],{"id":50,"languages_code":249,"label":244},"xxa",{"id":251,"languages_code":252,"label":253},45,"es","Aplicaciones web",{"id":255,"languages_code":256,"label":257},50,"cs","Webové aplikace",{"id":259,"languages_code":260,"label":244},59,"en",[262,269],{"id":50,"status":4,"sort":16,"label":244,"hidden":229,"created_on":243,"icon":263,"translations":264},{"id":246},[265,266,267,268],{"id":50,"languages_code":249,"label":244},{"id":251,"languages_code":252,"label":253},{"id":255,"languages_code":256,"label":257},{"id":259,"languages_code":260,"label":244},{"id":67,"status":4,"sort":72,"label":270,"hidden":229,"created_on":271,"icon":8,"translations":272},"Framework","2022-03-17T12:23:45.000Z",[273,274,277,279],{"id":67,"languages_code":249,"label":270},{"id":275,"languages_code":252,"label":276},53,"Marco",{"id":278,"languages_code":256,"label":270},60,{"id":280,"languages_code":260,"label":270},67,[282,296,326,349],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":287},"API","api","Translate strings directly or upload them into your Localazy project.","\u002Fdocs\u002Fapi\u002Fintroduction",[288,289,292,294],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},40,"Utilice la API para exportar traducciones e importar contenido de\u002Fa Localazy mediante programación.",{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},"Choose between translating strings directly or uploading them into Localazy.",{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},"Pomocí rozhraní API můžete programovaně exportovat překlady a importovat obsah z\u002Fdo Localazy.",{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":302},"Create source keys online","add-keys-manually","Add source keys via the web interface online and sync them into your project later.","\u002Fdocs\u002Fgeneral\u002Fimporting-localization-files#add-new-keys-in-ui","vpn-key-outline",[303,304,308,310,313,317,319,321],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},39,"Cree claves fuente en línea","Añada claves fuente a través de la interfaz web en línea y sincronícelas posteriormente en su proyecto.",{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},51,{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},"Vytvářejte zdrojové klíče online","Přidejte zdrojové klíče přes webové rozhraní online a synchronizujte je do svého projektu později.",{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},64,"Cree claves de origen en línea","Añada claves de origen a través de la interfaz web en línea y sincronícelas posteriormente en su proyecto.",{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},65,{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},66,{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},88,"de","Erstellen Sie Quellschlüssel online","Fügen Sie Quellschlüssel über die Weboberfläche online hinzu und synchronisieren Sie sie später mit Ihrem Projekt.",{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":333},"Direct file upload","File upload","web-upload","Upload your texts and existing translations in any format directly to start quickly.","\u002Fdocs\u002Fgeneral\u002Fimporting-localization-files","file-upload",[334,335,339,341,345],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},38,"Carga directa de archivos","Cargue sus textos y traducciones existentes en cualquier formato directamente para empezar rápidamente.",{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},47,{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},56,"Přímé nahrávání souborů","Nahrajte přímo své texty a stávající překlady v libovolném formátu a začněte pracovat ihned.",{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},85,"Direkter Datei-Upload","Laden Sie Ihre Texte und vorhandenen Übersetzungen in einem beliebigen Format direkt hoch, um schnell loszulegen.",{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":355},"Command Line Interface","CLI","cli","The best option for developers that want to make localization an automated part of their workflow.","\u002Fdocs\u002Fcli\u002Fthe-basics",[356,357,361,363,367],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},37,"Interfaz de Línea de Comandos","La mejor opción para los desarrolladores que deseen hacer de la localización una parte automatizada de su flujo de trabajo.",{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},46,{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},55,"Rozhraní Příkazového Řádku","Nejlepší volba pro vývojáře, kteří chtějí, aby se lokalizace stala automatizovanou součástí jejich pracovních postupů.",{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},87,"Befehlszeilenschnittstelle","Die beste Option für Entwickler, die die Lokalisierung zu einem automatisierten Teil ihres Arbeitsablaufs machen möchten.",[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":373},[374,375,376,377,378],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[380],{"id":381,"status":4,"created_on":382,"sort":8,"slug":383,"label":384,"on_faq_index":8},76,"2025-02-26T12:44:29.000Z","front-end-common","Front-end Common",[386],{"languages_code":249,"name":225,"slug":226,"description":227,"support_type":231,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":233,"tile_description":234,"id":222,"platforms_id":222,"docs_link":228},{"id":170,"status":4,"created_on":223,"modified_on":388,"name":389,"slug":390,"description":391,"docs_link":228,"priority":8,"has_sdk":229,"sort":107,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":231,"show_in_spa":230,"is_file_format":229,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":232,"tile_subtitle":392,"tile_description":393,"is_enterprise":229,"is_popular":229,"primary_use_case":8,"hierarchy_handling":8,"best_for":8,"file_extension":8,"format_code_example":8,"format_to_extension":394,"upload_features":395,"icon":396,"meta_image":398,"primary_tag":400,"tags":407,"integration_methods":421,"recommended_methods":452,"default_integration_method":453,"faq_categories":460,"translations":466,"platforms_id":170},"2025-02-26T13:35:41.000Z","Vue.js","vuejs","Online Vue.js project localization tool for your translation management. Enjoy true continuous localization with Localazy & translate your JSON files automatically.","Vue.js & JSON","Enjoy true continuous localization with Localazy & translate your Vue projects automatically.",{"json":236},[],{"id":397},"6180b41f-3249-47d3-adcd-50fe1cf11bf1",{"id":399},"8171b836-d6b8-4354-8db3-34ccd384970d",{"id":50,"status":4,"sort":16,"created_on":243,"label":244,"hidden":229,"icon":401,"translations":402},{"id":246},[403,404,405,406],{"id":50,"languages_code":249,"label":244},{"id":251,"languages_code":252,"label":253},{"id":255,"languages_code":256,"label":257},{"id":259,"languages_code":260,"label":244},[408,415],{"id":50,"status":4,"sort":16,"label":244,"hidden":229,"created_on":243,"icon":409,"translations":410},{"id":246},[411,412,413,414],{"id":50,"languages_code":249,"label":244},{"id":251,"languages_code":252,"label":253},{"id":255,"languages_code":256,"label":257},{"id":259,"languages_code":260,"label":244},{"id":67,"status":4,"sort":72,"label":270,"hidden":229,"created_on":271,"icon":8,"translations":416},[417,418,419,420],{"id":67,"languages_code":249,"label":270},{"id":275,"languages_code":252,"label":276},{"id":278,"languages_code":256,"label":270},{"id":280,"languages_code":260,"label":270},[422,428,438,445],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":423},[424,425,426,427],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":429},[430,431,432,433,434,435,436,437],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":439},[440,441,442,443,444],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":446},[447,448,449,450,451],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":454},[455,456,457,458,459],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[461,465],{"id":342,"status":4,"created_on":462,"sort":8,"slug":463,"label":464,"on_faq_index":8},"2023-03-01T11:21:41.000Z","vue-localization","Vue.js Localization",{"id":381,"status":4,"created_on":382,"sort":8,"slug":383,"label":384,"on_faq_index":8},[467],{"languages_code":249,"name":389,"slug":390,"description":391,"support_type":231,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":392,"tile_description":393,"id":170,"platforms_id":170,"docs_link":228},{"id":7,"status":4,"created_on":223,"modified_on":469,"name":470,"slug":471,"description":472,"docs_link":473,"priority":8,"has_sdk":229,"sort":57,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":474,"show_in_spa":230,"is_file_format":229,"meta_title":8,"meta_description":8,"featured_on_web":229,"marketing_subtitle":232,"tile_subtitle":474,"tile_description":475,"is_enterprise":229,"is_popular":229,"primary_use_case":476,"hierarchy_handling":477,"best_for":478,"file_extension":479,"format_code_example":480,"format_to_extension":481,"upload_features":483,"icon":484,"meta_image":486,"primary_tag":488,"tags":499,"integration_methods":537,"recommended_methods":568,"default_integration_method":569,"faq_categories":576,"translations":577,"platforms_id":7},"2025-07-03T14:21:42.000Z","Flutter","flutter","Learn how to use Localazy CLI for localization of Flutter app. Flutter’s ARB format is fully supported including arrays, plurals, and selected context information. No extra configuration is necessary, but you can enable certain features if you want to.","\u002Fdocs\u002Fcli\u002Fflutter-format","ARB format support","Use the Localazy CLI for localization of Flutter projects. Flutter’s ARB format is fully supported.","Supports metadata like placeholders","JSON-like key-value","Flutter apps",".arb","```\n{\n  \"localazy_message\": \"Go international, today. With Localazy.\"\n}\n```",{"arb":482},"arb",[],{"id":485},"b9f13a11-9328-4a03-86cf-b20de0685606",{"id":487},"c2674666-4371-4aa4-9a65-438c7363fafe",{"id":57,"status":4,"sort":67,"created_on":271,"label":489,"hidden":229,"icon":490,"translations":492},"Mobile apps",{"id":491},"c9c7e1f5-8b59-4016-ae0c-6fba9469cd55",[493,494,496,498],{"id":57,"languages_code":249,"label":489},{"id":362,"languages_code":252,"label":495},"Aplicaciones móviles",{"id":364,"languages_code":256,"label":497},"Mobilní aplikace",{"id":318,"languages_code":260,"label":489},[500,511,518,525],{"id":62,"status":4,"sort":170,"label":501,"hidden":229,"created_on":271,"icon":502,"translations":504},"Desktop & Games",{"id":503},"65b04533-5b4c-430c-b8a4-ecce84754200",[505,506,508,510],{"id":62,"languages_code":249,"label":501},{"id":340,"languages_code":252,"label":507},"Escritorio y Juegos",{"id":342,"languages_code":256,"label":509},"Stolní počítače & Hry",{"id":320,"languages_code":260,"label":501},{"id":50,"status":4,"sort":16,"label":244,"hidden":229,"created_on":243,"icon":512,"translations":513},{"id":246},[514,515,516,517],{"id":50,"languages_code":249,"label":244},{"id":251,"languages_code":252,"label":253},{"id":255,"languages_code":256,"label":257},{"id":259,"languages_code":260,"label":244},{"id":57,"status":4,"sort":67,"label":489,"hidden":229,"created_on":271,"icon":519,"translations":520},{"id":491},[521,522,523,524],{"id":57,"languages_code":249,"label":489},{"id":362,"languages_code":252,"label":495},{"id":364,"languages_code":256,"label":497},{"id":318,"languages_code":260,"label":489},{"id":526,"status":4,"sort":527,"label":528,"hidden":230,"created_on":271,"icon":8,"translations":529},30,32,"ARB",[530,531,533,535],{"id":526,"languages_code":249,"label":528},{"id":532,"languages_code":252,"label":528},120,{"id":534,"languages_code":256,"label":528},125,{"id":536,"languages_code":260,"label":528},130,[538,544,554,561],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":539},[540,541,542,543],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":545},[546,547,548,549,550,551,552,553],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":555},[556,557,558,559,560],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":562},[563,564,565,566,567],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":570},[571,572,573,574,575],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],[578],{"languages_code":249,"name":470,"slug":471,"description":472,"support_type":474,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":474,"tile_description":475,"id":7,"platforms_id":7,"docs_link":473},{"id":580,"status":4,"created_on":581,"modified_on":582,"name":583,"slug":584,"description":585,"docs_link":586,"priority":8,"has_sdk":229,"sort":29,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":587,"show_in_spa":230,"is_file_format":229,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":232,"tile_subtitle":587,"tile_description":588,"is_enterprise":229,"is_popular":229,"primary_use_case":8,"hierarchy_handling":8,"best_for":8,"file_extension":8,"format_code_example":8,"format_to_extension":589,"upload_features":591,"icon":592,"meta_image":594,"primary_tag":596,"tags":610,"integration_methods":625,"recommended_methods":656,"default_integration_method":657,"faq_categories":664,"translations":669,"platforms_id":580},31,"2022-03-18T08:09:25.000Z","2024-07-17T07:43:22.000Z","JavaScript","javascript","Localize your app with JavaScript localizations and Localazy CLI.\nUpload JavaScript files with strings to Localazy and manage your translations easily. Download translated files back.","\u002Fdocs\u002Fcli\u002Fjavascript-format","JS file support","Translating JS files is easy as a pie with Localazy!",{"js":590},"js",[],{"id":593},"4218d0c9-7e6b-494d-9663-37ceaf93ee8c",{"id":595},"2c6699eb-1d80-4772-8268-5597dbcead8c",{"id":77,"status":4,"sort":77,"created_on":271,"label":597,"hidden":229,"icon":598,"translations":600},"Programming Languages",{"id":599},"8c5836bb-1fbe-49c5-9330-8f931838c457",[601,602,605,608],{"id":77,"languages_code":249,"label":597},{"id":603,"languages_code":252,"label":604},63,"Lenguajes de Programación",{"id":606,"languages_code":256,"label":607},68,"Programovací Jazyky",{"id":609,"languages_code":260,"label":597},70,[611,618],{"id":50,"status":4,"sort":16,"label":244,"hidden":229,"created_on":243,"icon":612,"translations":613},{"id":246},[614,615,616,617],{"id":50,"languages_code":249,"label":244},{"id":251,"languages_code":252,"label":253},{"id":255,"languages_code":256,"label":257},{"id":259,"languages_code":260,"label":244},{"id":77,"status":4,"sort":77,"label":597,"hidden":229,"created_on":271,"icon":619,"translations":620},{"id":599},[621,622,623,624],{"id":77,"languages_code":249,"label":597},{"id":603,"languages_code":252,"label":604},{"id":606,"languages_code":256,"label":607},{"id":609,"languages_code":260,"label":597},[626,632,642,649],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":627},[628,629,630,631],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":633},[634,635,636,637,638,639,640,641],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":643},[644,645,646,647,648],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":650},[651,652,653,654,655],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":658},[659,660,661,662,663],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[665],{"id":666,"status":4,"created_on":667,"sort":8,"slug":668,"label":583,"on_faq_index":229},35,"2022-06-10T09:49:33.000Z","javascript-i18n-localization",[670],{"languages_code":249,"name":583,"slug":584,"description":585,"support_type":587,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":587,"tile_description":588,"id":580,"platforms_id":580,"docs_link":586},{"id":29,"status":4,"created_on":581,"modified_on":672,"name":673,"slug":236,"description":674,"docs_link":228,"priority":8,"has_sdk":229,"sort":174,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":675,"show_in_spa":230,"is_file_format":230,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":232,"tile_subtitle":676,"tile_description":677,"is_enterprise":229,"is_popular":230,"primary_use_case":678,"hierarchy_handling":679,"best_for":680,"file_extension":681,"format_code_example":682,"format_to_extension":683,"upload_features":684,"icon":685,"meta_image":687,"primary_tag":689,"tags":702,"integration_methods":710,"recommended_methods":741,"default_integration_method":742,"faq_categories":749,"translations":753,"platforms_id":29},"2025-10-14T11:22:29.000Z","JSON","Online JSON translator you will love. Comfortable JSON language files editor with powerful CLI under your fingers for continuous localization.","Advanced format support","{Objectively the best}","Translate any JSON files with Localazy, with the best in class plural and array support.","Used for structured data storage and APIs","Uses key-value pairs","Web & mobile apps, APIs",".json","```\n{\n  \"parent\": {\n    \"child\": {\n      \"another_nested_level\": \"All is supported.\"\n    }\n  }\n}\n```",{"json":236},[],{"id":686},"99ac3b7c-dba5-4693-a4f4-1f27a6d7782d",{"id":688},"8d614c20-667e-4bee-a64d-7d7ce9c0ee0a",{"id":107,"status":4,"sort":50,"created_on":271,"label":690,"hidden":229,"icon":691,"translations":693},"File formats",{"id":692},"ab7c8f89-dcce-45ab-9e21-8605aef289c3",[694,695,698,700],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},44,"Formatos de archivo",{"id":309,"languages_code":256,"label":699},"Formáty souborů",{"id":701,"languages_code":260,"label":690},62,[703],{"id":107,"status":4,"sort":50,"label":690,"hidden":229,"created_on":271,"icon":704,"translations":705},{"id":692},[706,707,708,709],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},[711,717,727,734],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":712},[713,714,715,716],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":718},[719,720,721,722,723,724,725,726],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":728},[729,730,731,732,733],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":735},[736,737,738,739,740],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":743},[744,745,746,747,748],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[750],{"id":751,"status":4,"created_on":752,"sort":8,"slug":236,"label":673,"on_faq_index":229},36,"2022-06-10T10:49:07.000Z",[754],{"languages_code":249,"name":673,"slug":236,"description":674,"support_type":675,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":676,"tile_description":677,"id":29,"platforms_id":29,"docs_link":228},{"id":99,"status":4,"created_on":581,"modified_on":756,"name":757,"slug":758,"description":759,"docs_link":760,"priority":8,"has_sdk":229,"sort":99,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":761,"show_in_spa":229,"is_file_format":230,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":232,"tile_subtitle":762,"tile_description":763,"is_enterprise":229,"is_popular":230,"primary_use_case":764,"hierarchy_handling":765,"best_for":766,"file_extension":767,"format_code_example":768,"format_to_extension":769,"upload_features":771,"icon":772,"meta_image":774,"primary_tag":776,"tags":783,"integration_methods":805,"recommended_methods":836,"default_integration_method":837,"faq_categories":844,"translations":845,"platforms_id":99},"2025-07-03T14:28:31.000Z","XLIFF","xliff","XLIFF is meant for localization. Enjoy Localazy - an online XLIFF editor for your translation management. Integrate your XLIFF files with Localazy to achieve true continuous localization and translate XLIFF files on autopilot.","\u002Fdocs\u002Fcli\u002Fxliff-12-format","File format support","Meant for localization","XLIFF stands for XML Localization Interchange File Format - and Localazy is the best way to manage XLIFF files.","Used in translation pipelines","XML-based exchange format","Translation & software",".xliff","```\n\u003Ctrans-unit id=\"localazy_message\">\n    \u003Csource>Go international, today. With Localazy.\u003C\u002Fsource>\n\u003C\u002Ftrans-unit>\n```",{"xliff":770},"xlf",[],{"id":773},"ca424cc8-e8a7-4aef-8dca-ef4a4d1334fc",{"id":775},"889970a6-cce8-4055-b96a-9c3f292aa67f",{"id":107,"status":4,"sort":50,"created_on":271,"label":690,"hidden":229,"icon":777,"translations":778},{"id":692},[779,780,781,782],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},[784,791,798],{"id":107,"status":4,"sort":50,"label":690,"hidden":229,"created_on":271,"icon":785,"translations":786},{"id":692},[787,788,789,790],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},{"id":107,"status":4,"sort":50,"label":690,"hidden":229,"created_on":271,"icon":792,"translations":793},{"id":692},[794,795,796,797],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},{"id":107,"status":4,"sort":50,"label":690,"hidden":229,"created_on":271,"icon":799,"translations":800},{"id":692},[801,802,803,804],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},[806,812,822,829],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":807},[808,809,810,811],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":813},[814,815,816,817,818,819,820,821],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":823},[824,825,826,827,828],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":830},[831,832,833,834,835],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":838},[839,840,841,842,843],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],[846],{"languages_code":249,"name":757,"slug":758,"description":759,"support_type":761,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":762,"tile_description":763,"id":99,"platforms_id":99,"docs_link":760},{"id":174,"status":4,"created_on":848,"modified_on":848,"name":849,"slug":850,"description":851,"docs_link":852,"priority":8,"has_sdk":229,"sort":853,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":761,"show_in_spa":230,"is_file_format":230,"meta_title":8,"meta_description":8,"featured_on_web":229,"marketing_subtitle":232,"tile_subtitle":854,"tile_description":855,"is_enterprise":229,"is_popular":230,"primary_use_case":8,"hierarchy_handling":8,"best_for":8,"file_extension":8,"format_code_example":8,"format_to_extension":856,"upload_features":857,"icon":858,"meta_image":860,"primary_tag":862,"tags":869,"integration_methods":898,"recommended_methods":929,"default_integration_method":930,"faq_categories":937,"translations":938,"platforms_id":174},"2026-05-21T20:49:09.000Z","PO","po","Edit .po and .pot files with your team, automate translation with AI, and ship faster.","\u002Fdocs\u002Fcli\u002Fpo-format",24,"Seamless integration","Upload, edit and translate PO files with Localazy.",{"po":850},[],{"id":859},"25f317fe-0c10-4f0b-92cd-f80d1f3c6a67",{"id":861},"490022f9-d91a-4e1a-9e79-db374ec997c2",{"id":107,"status":4,"sort":50,"created_on":271,"label":690,"hidden":229,"icon":863,"translations":864},{"id":692},[865,866,867,868],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},[870,877,888],{"id":107,"status":4,"sort":50,"label":690,"hidden":229,"created_on":271,"icon":871,"translations":872},{"id":692},[873,874,875,876],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},{"id":878,"status":4,"sort":878,"label":879,"hidden":230,"created_on":271,"icon":8,"translations":880},34,"C++",[881,882,884,886],{"id":878,"languages_code":249,"label":879},{"id":883,"languages_code":252,"label":879},135,{"id":885,"languages_code":256,"label":879},140,{"id":887,"languages_code":260,"label":879},144,{"id":99,"status":4,"sort":853,"label":889,"hidden":230,"created_on":271,"icon":8,"translations":890},"Gettext",[891,892,894,896],{"id":99,"languages_code":249,"label":889},{"id":893,"languages_code":252,"label":889},101,{"id":895,"languages_code":256,"label":889},106,{"id":897,"languages_code":260,"label":889},111,[899,905,915,922],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":900},[901,902,903,904],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":906},[907,908,909,910,911,912,913,914],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":916},[917,918,919,920,921],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":923},[924,925,926,927,928],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":931},[932,933,934,935,936],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],[939],{"languages_code":249,"name":849,"slug":850,"description":851,"support_type":761,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":854,"tile_description":855,"id":174,"platforms_id":174,"docs_link":852},{"id":941,"status":4,"created_on":581,"modified_on":942,"name":943,"slug":944,"description":945,"docs_link":946,"priority":8,"has_sdk":229,"sort":947,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":761,"show_in_spa":230,"is_file_format":230,"meta_title":8,"meta_description":8,"featured_on_web":229,"marketing_subtitle":232,"tile_subtitle":948,"tile_description":949,"is_enterprise":229,"is_popular":229,"primary_use_case":950,"hierarchy_handling":951,"best_for":952,"file_extension":953,"format_code_example":954,"format_to_extension":955,"upload_features":956,"icon":957,"meta_image":958,"primary_tag":960,"tags":967,"integration_methods":985,"recommended_methods":1016,"default_integration_method":1017,"faq_categories":1024,"translations":1027,"platforms_id":941},26,"2025-10-02T08:32:44.000Z","RESX","resx","Quickly translate and manage your RESX files with Localazy or integrate Localazy with your .NET project and enjoy a fully automated localization process. ","\u002Fdocs\u002Fcli\u002Fresx-format",27,".NET localization","Translate .NET projects using RESX files and Localazy.","Standard format for Windows\u002F.NET localization","Flat key-value structure",".NET applications",".resx","```\n\u003C?xml version=\"1.0\" encoding=\"utf-8\"?>\n\u003Croot>\n  \u003Cdata name=\"localazy_message\" xml:space=\"preserve\">\n    \u003Cvalue>Go international, today. With Localazy.\u003C\u002Fvalue>\n  \u003C\u002Fdata>\n\u003C\u002Froot>\n```",{"resx":944},[],{"id":859},{"id":959},"1f07bf83-9363-47d6-b21b-a5121c0efaf6",{"id":107,"status":4,"sort":50,"created_on":271,"label":690,"hidden":229,"icon":961,"translations":962},{"id":692},[963,964,965,966],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},[968,975],{"id":107,"status":4,"sort":50,"label":690,"hidden":229,"created_on":271,"icon":969,"translations":970},{"id":692},[971,972,973,974],{"id":107,"languages_code":249,"label":690},{"id":696,"languages_code":252,"label":697},{"id":309,"languages_code":256,"label":699},{"id":701,"languages_code":260,"label":690},{"id":853,"status":4,"sort":941,"label":976,"hidden":230,"created_on":271,"icon":8,"translations":977},"C#",[978,979,981,983],{"id":853,"languages_code":249,"label":976},{"id":980,"languages_code":252,"label":976},103,{"id":982,"languages_code":256,"label":976},108,{"id":984,"languages_code":260,"label":976},113,[986,992,1002,1009],{"id":107,"status":4,"sort":57,"label":283,"alternative_label":8,"slug":284,"description":285,"documentation_link":286,"loc_icon":284,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":987},[988,989,990,991],{"id":107,"languages_code":249,"label":283,"description":285,"slug":284},{"id":290,"languages_code":252,"label":283,"description":291,"slug":284},{"id":255,"languages_code":260,"label":283,"description":293,"slug":284},{"id":259,"languages_code":256,"label":283,"description":295,"slug":284},{"id":22,"status":4,"sort":50,"label":297,"alternative_label":8,"slug":298,"description":299,"documentation_link":300,"loc_icon":301,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":993},[994,995,996,997,998,999,1000,1001],{"id":22,"languages_code":249,"label":297,"description":299,"slug":298},{"id":305,"languages_code":252,"label":306,"description":307,"slug":8},{"id":309,"languages_code":260,"label":297,"description":299,"slug":298},{"id":278,"languages_code":256,"label":311,"description":312,"slug":8},{"id":314,"languages_code":252,"label":315,"description":316,"slug":298},{"id":318,"languages_code":260,"label":297,"description":299,"slug":298},{"id":320,"languages_code":256,"label":311,"description":312,"slug":298},{"id":322,"languages_code":323,"label":324,"description":325,"slug":8},{"id":16,"status":4,"sort":107,"label":327,"alternative_label":328,"slug":329,"description":330,"documentation_link":331,"loc_icon":332,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1003},[1004,1005,1006,1007,1008],{"id":16,"languages_code":249,"label":327,"description":330,"slug":329},{"id":336,"languages_code":252,"label":337,"description":338,"slug":8},{"id":340,"languages_code":260,"label":327,"description":330,"slug":329},{"id":342,"languages_code":256,"label":343,"description":344,"slug":8},{"id":346,"languages_code":323,"label":347,"description":348,"slug":8},{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1010},[1011,1012,1013,1014,1015],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[],{"id":7,"status":4,"sort":22,"label":350,"alternative_label":351,"slug":352,"description":353,"documentation_link":354,"loc_icon":352,"is_official_plugin":229,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1018},[1019,1020,1021,1022,1023],{"id":7,"languages_code":249,"label":350,"description":353,"slug":352},{"id":358,"languages_code":252,"label":359,"description":360,"slug":352},{"id":362,"languages_code":260,"label":350,"description":353,"slug":352},{"id":364,"languages_code":256,"label":365,"description":366,"slug":352},{"id":368,"languages_code":323,"label":369,"description":370,"slug":8},[1025],{"id":696,"status":4,"created_on":1026,"sort":8,"slug":944,"label":943,"on_faq_index":8},"2022-08-01T16:44:06.000Z",[1028],{"languages_code":249,"name":943,"slug":944,"description":945,"support_type":761,"meta_title":8,"meta_description":8,"marketing_subtitle":232,"tile_subtitle":948,"tile_description":949,"id":941,"platforms_id":941,"docs_link":946},{"id":1030,"status":4,"created_on":1031,"modified_on":1032,"name":1033,"slug":1034,"description":1035,"docs_link":1036,"priority":8,"has_sdk":8,"sort":1037,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":1038,"show_in_spa":230,"is_file_format":8,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":1038,"tile_subtitle":1038,"tile_description":1039,"is_enterprise":229,"is_popular":230,"primary_use_case":8,"hierarchy_handling":8,"best_for":8,"file_extension":8,"format_code_example":8,"format_to_extension":8,"upload_features":8,"icon":1040,"meta_image":1042,"primary_tag":1044,"tags":1056,"integration_methods":1103,"recommended_methods":1123,"default_integration_method":1124,"faq_categories":1131,"translations":1134,"platforms_id":1030},72,"2022-06-16T09:08:11.000Z","2026-04-27T18:16:54.000Z","Strapi","strapi","Enjoy seamless integration of Strapi & Localazy and translate your website efficiently. Download the official Localazy plugin in the Strapi Marketplace to get started!","\u002Fdocs\u002Fstrapi\u002Fstrapi-plugin-introduction",54,"Localization Plugin","Localize your Strapi website with our official localization plugin. Easy setup and installation.",{"id":1041},"cde7f1d0-f2e0-4243-929e-a3f8f9146e69",{"id":1043},"5995b721-a2ea-487e-ad4b-298a489bbd24",{"id":29,"status":4,"sort":36,"created_on":271,"label":1045,"hidden":229,"icon":1046,"translations":1048},"CMS",{"id":1047},"1172a655-928c-4594-9263-d8afdfd9cd79",[1049,1050,1052,1054],{"id":29,"languages_code":249,"label":1045},{"id":1051,"languages_code":252,"label":1045},73,{"id":1053,"languages_code":256,"label":1045},81,{"id":1055,"languages_code":260,"label":1045},84,[1057,1069,1082,1089],{"id":166,"status":4,"sort":162,"label":1058,"hidden":229,"created_on":271,"icon":8,"translations":1059},"Multilingual SEO",[1060,1061,1064,1067],{"id":166,"languages_code":249,"label":1058},{"id":1062,"languages_code":252,"label":1063},89,"SEO multilingüe",{"id":1065,"languages_code":256,"label":1066},94,"Vícejazyčné SEO",{"id":1068,"languages_code":260,"label":1058},99,{"id":222,"status":4,"sort":222,"label":1070,"hidden":229,"created_on":271,"icon":1071,"translations":1073},"E-commerce",{"id":1072},"e782ed3f-d954-45ca-8b17-5bf5fe95f30a",[1074,1075,1078,1080],{"id":222,"languages_code":249,"label":1070},{"id":1076,"languages_code":252,"label":1077},132,"Comercio electrónico",{"id":1079,"languages_code":256,"label":1070},137,{"id":1081,"languages_code":260,"label":1070},142,{"id":29,"status":4,"sort":36,"label":1045,"hidden":229,"created_on":271,"icon":1083,"translations":1084},{"id":1047},[1085,1086,1087,1088],{"id":29,"languages_code":249,"label":1045},{"id":1051,"languages_code":252,"label":1045},{"id":1053,"languages_code":256,"label":1045},{"id":1055,"languages_code":260,"label":1045},{"id":16,"status":4,"sort":57,"label":1090,"hidden":229,"created_on":271,"icon":1091,"translations":1093},"Marketing tools",{"id":1092},"098fe6a4-dd2e-42d8-937e-2d8121e6e266",[1094,1095,1098,1101],{"id":16,"languages_code":249,"label":1090},{"id":1096,"languages_code":252,"label":1097},43,"Herramientas de marketing",{"id":1099,"languages_code":256,"label":1100},48,"Marketingové nástroje",{"id":1102,"languages_code":260,"label":1090},58,[1104],{"id":67,"status":4,"sort":8,"label":1105,"alternative_label":1106,"slug":1107,"description":1108,"documentation_link":1109,"loc_icon":1110,"is_official_plugin":230,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1111},"Official Strapi Plugin","Official Plugin","official-strapi-plugin","Our developers maintain an official Strapi localization plugin. Start in a few clicks!","\u002Fdocs\u002Fstrapi","localazy-box",[1112,1113,1116,1117,1120],{"id":67,"languages_code":249,"label":1105,"description":1108,"slug":1107},{"id":1096,"languages_code":252,"label":1114,"description":1115,"slug":8},"Complemento Oficial de Strapi","Nuestros desarrolladores mantienen un complemento oficial de localización de Strapi. ¡Empiece en unos pocos clics!",{"id":275,"languages_code":260,"label":1105,"description":1108,"slug":1107},{"id":701,"languages_code":256,"label":1118,"description":1119,"slug":8},"Oficiál Plugin Strapi","Naši vývojáři udržují a neustále vylepšují oficiální lokalizační plugin Strapi. Začněte několika kliknutími!",{"id":1062,"languages_code":323,"label":1121,"description":1122,"slug":8},"Offizielles Strapi-Plugin","Unsere Entwickler pflegen ein offizielles Strapi-Lokalisierungs-Plugin. Starten Sie mit ein paar Klicks!",[],{"id":67,"status":4,"sort":8,"label":1105,"alternative_label":1106,"slug":1107,"description":1108,"documentation_link":1109,"loc_icon":1110,"is_official_plugin":230,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1125},[1126,1127,1128,1129,1130],{"id":67,"languages_code":249,"label":1105,"description":1108,"slug":1107},{"id":1096,"languages_code":252,"label":1114,"description":1115,"slug":8},{"id":275,"languages_code":260,"label":1105,"description":1108,"slug":1107},{"id":701,"languages_code":256,"label":1118,"description":1119,"slug":8},{"id":1062,"languages_code":323,"label":1121,"description":1122,"slug":8},[1132],{"id":358,"status":4,"created_on":1133,"sort":8,"slug":1034,"label":1033,"on_faq_index":8},"2022-06-16T09:24:13.000Z",[1135],{"languages_code":249,"name":1033,"slug":1034,"description":1035,"support_type":1038,"meta_title":8,"meta_description":8,"marketing_subtitle":1038,"tile_subtitle":1038,"tile_description":1039,"id":1030,"platforms_id":1030,"docs_link":1036},{"id":278,"status":4,"created_on":581,"modified_on":1137,"name":1138,"slug":1139,"description":8,"docs_link":1140,"priority":8,"has_sdk":229,"sort":364,"highlighted":229,"in_menu":230,"changefreq":8,"support_type":1141,"show_in_spa":230,"is_file_format":229,"meta_title":8,"meta_description":8,"featured_on_web":230,"marketing_subtitle":1142,"tile_subtitle":1143,"tile_description":1144,"is_enterprise":229,"is_popular":230,"primary_use_case":8,"hierarchy_handling":8,"best_for":8,"file_extension":8,"format_code_example":8,"format_to_extension":8,"upload_features":1145,"icon":1146,"meta_image":1148,"primary_tag":1150,"tags":1164,"integration_methods":1172,"recommended_methods":1187,"default_integration_method":1188,"faq_categories":1194,"translations":1195,"platforms_id":278},"2024-12-20T15:00:22.000Z","Figma","figma","\u002Fdocs\u002Fintegrations\u002Fquick-start-figma","plugin","Figma plugin","Localization plugin","Quickly translate your Figma designs and seamlessly reuse the translations during the development of your project.",[],{"id":1147},"813745a4-a77d-4735-93b7-e0dd731b2304",{"id":1149},"7573fed6-8817-4cb4-84d2-be327e6c4891",{"id":22,"status":4,"sort":62,"created_on":271,"label":1151,"hidden":229,"icon":1152,"translations":1154},"Design tools",{"id":1153},"1053d863-b690-4fbd-aadf-dbf2ba282768",[1155,1156,1159,1162],{"id":22,"languages_code":249,"label":1151},{"id":1157,"languages_code":252,"label":1158},42,"Herramientas de diseño",{"id":1160,"languages_code":256,"label":1161},49,"Nástroje pro návrh",{"id":1163,"languages_code":260,"label":1151},57,[1165],{"id":22,"status":4,"sort":62,"label":1151,"hidden":229,"created_on":271,"icon":1166,"translations":1167},{"id":1153},[1168,1169,1170,1171],{"id":22,"languages_code":249,"label":1151},{"id":1157,"languages_code":252,"label":1158},{"id":1160,"languages_code":256,"label":1161},{"id":1163,"languages_code":260,"label":1151},[1173],{"id":62,"status":4,"sort":8,"label":1106,"alternative_label":1106,"slug":1174,"description":1175,"documentation_link":152,"loc_icon":1110,"is_official_plugin":230,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1176},"official-plugin","Our developers maintain an official plugin for this integration. Start in a few clicks!",[1177,1178,1182,1184],{"id":62,"languages_code":249,"label":1106,"description":1175,"slug":1174},{"id":1179,"languages_code":252,"label":1180,"description":1181,"slug":8},23,"Plugin Oficial","Nuestros desarrolladores mantienen un plugin oficial para esta integración. ¡Empiece con unos pocos clics!",{"id":1183,"languages_code":260,"label":1106,"description":1175,"slug":1174},29,{"id":666,"languages_code":256,"label":1185,"description":1186,"slug":8},"Oficiální Plugin","Naši vývojáři udržují a neustále vylepšují oficiální plugin pro tuto integraci. Začněte několika kliknutími!",[],{"id":62,"status":4,"sort":8,"label":1106,"alternative_label":1106,"slug":1174,"description":1175,"documentation_link":152,"loc_icon":1110,"is_official_plugin":230,"is_universal_plugin":229,"universal_plugin_vendor":8,"translations":1189},[1190,1191,1192,1193],{"id":62,"languages_code":249,"label":1106,"description":1175,"slug":1174},{"id":1179,"languages_code":252,"label":1180,"description":1181,"slug":8},{"id":1183,"languages_code":260,"label":1106,"description":1175,"slug":1174},{"id":666,"languages_code":256,"label":1185,"description":1186,"slug":8},[],[1196],{"languages_code":249,"name":1138,"slug":1139,"description":8,"support_type":1141,"meta_title":8,"meta_description":8,"marketing_subtitle":1142,"tile_subtitle":1143,"tile_description":1144,"id":278,"platforms_id":278,"docs_link":1140},[1198,1379,1589,1690,1809,1811],{"id":16,"name":1199,"url":8,"url_text":8,"status":4,"groups":1200},"Solutions",[1201,1210,1277,1309],{"navigation_items_group_id":1202},{"id":22,"sort":50,"status":4,"name":1203,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":230,"show_all_url":8,"represent_as_tile":229,"items":1205},"Featured Article","top",[1206],{"collection":1207,"item":1208},"blog_post_navigation_item_type",{"id":107,"status":4,"sort":8,"show_author_img":230,"blog_post_tag":1209,"description":8},"nav",{"navigation_items_group_id":1211},{"id":50,"sort":7,"status":4,"name":1212,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":1213,"represent_as_tile":230,"items":1214},"Your Role","\u002Froles",[1215,1227,1237,1247,1257,1267],{"collection":1216,"item":1217},"relation_navigation_item_type",{"id":7,"status":4,"sort":8,"name":1218,"item":1219},"CMO",[1220],{"collection":1221,"item":1222},"personas",{"id":7,"status":4,"sort":8,"slug":1223,"icon":1224},"chief-marketing-officers",{"id":1225,"title":1226},"526097d8-176f-48e5-83d3-2fc4d77061f9","La Mail Bulk",{"collection":1216,"item":1228},{"id":22,"status":4,"sort":8,"name":1229,"item":1230},"CTO",[1231],{"collection":1221,"item":1232},{"id":107,"status":4,"sort":8,"slug":1233,"icon":1234},"chief-technical-officers",{"id":1235,"title":1236},"f808fdf0-c78b-4294-ba59-fe25f46fe825","La Mechanic",{"collection":1216,"item":1238},{"id":174,"status":4,"sort":8,"name":1239,"item":1240},"Product Manager",[1241],{"collection":1221,"item":1242},{"id":166,"status":4,"sort":8,"slug":1243,"icon":1244},"product-managers",{"id":1245,"title":1246},"ea39586a-21fc-4b34-ba87-496028e5198f","La Worker",{"collection":1216,"item":1248},{"id":358,"status":4,"sort":8,"name":1249,"item":1250},"Translator",[1251],{"collection":1221,"item":1252},{"id":174,"status":4,"sort":8,"slug":1253,"icon":1254},"professional-translators",{"id":1255,"title":1256},"07945171-d51d-4ca8-96c0-21cde9db258f","La Chat",{"collection":1216,"item":1258},{"id":336,"status":4,"sort":8,"name":1259,"item":1260},"Developer",[1261],{"collection":1221,"item":1262},{"id":526,"status":4,"sort":8,"slug":1263,"icon":1264},"software-developers",{"id":1265,"title":1266},"1806e46d-c551-4845-bf42-4407344d229e","La Terminal",{"collection":1216,"item":1268},{"id":947,"status":4,"sort":8,"name":1269,"item":1270},"Localization Manager",[1271],{"collection":1221,"item":1272},{"id":57,"status":4,"sort":8,"slug":1273,"icon":1274},"localization-managers",{"id":1275,"title":1276},"dac69bd1-bf5d-41d0-87d4-dd13e314698a","La Language",{"navigation_items_group_id":1278},{"id":72,"sort":22,"status":4,"name":1279,"render_show_all_url":229,"show_all_url_position":1280,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1281},"Use cases","bottom",[1282,1287,1291,1296,1300,1305],{"collection":1283,"item":1284},"simple_link_navigation_item_type",{"id":853,"status":4,"sort":8,"url":1285,"url_text":1286,"show_favorite_icon":229},"https:\u002F\u002Flocalazy.com\u002Fuse-cases\u002Fsoftware-localization","Software localization",{"collection":1283,"item":1288},{"id":941,"status":4,"sort":8,"url":1289,"url_text":1290,"show_favorite_icon":229},"https:\u002F\u002Flocalazy.com\u002Fuse-cases\u002Fmobile-app-localization","Mobile app localization",{"collection":1283,"item":1292},{"id":1293,"status":4,"sort":8,"url":1294,"url_text":1295,"show_favorite_icon":229},25,"https:\u002F\u002Flocalazy.com\u002Fuse-cases\u002Fwebsite-localization","Website localization",{"collection":1283,"item":1297},{"id":947,"status":4,"sort":8,"url":1298,"url_text":1299,"show_favorite_icon":229},"https:\u002F\u002Flocalazy.com\u002Fuse-cases\u002Fdesign-localization","Design localization",{"collection":1283,"item":1301},{"id":1302,"status":4,"sort":8,"url":1303,"url_text":1304,"show_favorite_icon":229},28,"https:\u002F\u002Flocalazy.com\u002Fuse-cases\u002Fgame-localization","Game localization",{"collection":1283,"item":1306},{"id":1183,"status":4,"sort":8,"url":1307,"url_text":1308,"show_favorite_icon":229},"https:\u002F\u002Flocalazy.com\u002Fuse-cases\u002Fhelp-and-docs-localization","Help & docs localization",{"navigation_items_group_id":1310},{"id":67,"sort":16,"status":4,"name":1311,"render_show_all_url":229,"show_all_url_position":1280,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1312},"Industry",[1313,1323,1333,1342,1352,1361,1372],{"collection":1216,"item":1314},{"id":1179,"status":4,"sort":8,"name":1315,"item":1316},"Digital Agencies",[1317],{"collection":1221,"item":1318},{"id":62,"status":4,"sort":8,"slug":1319,"icon":1320},"digital-agencies",{"id":1321,"title":1322},"547f5619-b21d-4b29-86f1-8b2200313cde","La Digi Agency",{"collection":1216,"item":1324},{"id":305,"status":4,"sort":8,"name":1325,"item":1326},"Startups & SaaS",[1327],{"collection":1221,"item":1328},{"id":16,"status":4,"sort":8,"slug":1329,"icon":1330},"startups",{"id":1331,"title":1332},"da1516e2-4afc-40a2-bcbf-a8161e2d610d","La Saa S",{"collection":1216,"item":1334},{"id":16,"status":4,"sort":8,"name":1070,"item":1335},[1336],{"collection":1221,"item":1337},{"id":50,"status":4,"sort":8,"slug":1338,"icon":1339},"e-commerce",{"id":1340,"title":1341},"a3d09cd2-054f-4bb5-a0a2-d3d207db65df","La Ecommerce",{"collection":1216,"item":1343},{"id":170,"status":4,"sort":8,"name":1344,"item":1345},"FinTech Platforms",[1346],{"collection":1221,"item":1347},{"id":947,"status":4,"sort":8,"slug":1348,"icon":1349},"fintech",{"id":1350,"title":1351},"147339ba-07d1-4e5e-baad-23d27e60c919","La Money",{"collection":1216,"item":1353},{"id":853,"status":4,"sort":8,"name":1354,"item":1355},"Translation Agencies",[1356],{"collection":1221,"item":1357},{"id":853,"status":4,"sort":8,"slug":1358,"icon":1359},"translation-agencies",{"id":1360,"title":1276},"15d6fe33-2af8-4d6e-933d-5caa64394511",{"collection":1216,"item":1362},{"id":1363,"status":4,"sort":8,"name":1364,"item":1365},22,"Travel & Tourism",[1366],{"collection":1221,"item":1367},{"id":22,"status":4,"sort":8,"slug":1368,"icon":1369},"tourism",{"id":1370,"title":1371},"23a785e8-0ae5-4c4b-8452-aab1b58182a6","La Travel",{"collection":1216,"item":1373},{"id":1293,"status":4,"sort":8,"name":1374,"item":1375},"Nonprofit Causes",[1376],{"collection":1221,"item":1377},{"id":1302,"status":4,"sort":8,"slug":1378,"icon":8},"nonprofit",{"id":50,"name":1380,"url":8,"url_text":8,"status":4,"groups":1381},"Features",[1382,1441,1492,1538],{"navigation_items_group_id":1383},{"id":36,"sort":57,"status":4,"name":1384,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1385},"Localization",[1386,1394,1402,1409,1416,1420,1427,1434],{"collection":1216,"item":1387},{"id":696,"status":4,"sort":8,"name":1388,"item":1389},"Localization services",[1390],{"collection":1391,"item":1392},"products",{"id":72,"status":4,"slug":1393},"continuous-localization-team",{"collection":1216,"item":1395},{"id":251,"status":4,"sort":8,"name":1396,"item":1397},"Translation management",[1398],{"collection":1399,"item":1400},"term_landing_page",{"id":1183,"status":4,"slug":1401},"translation-management-system",{"collection":1216,"item":1403},{"id":362,"status":4,"sort":8,"name":1404,"item":1405},"Context Screenshots",[1406],{"collection":1391,"item":1407},{"id":43,"status":4,"slug":1408},"context-screenshots-ocr",{"collection":1216,"item":1410},{"id":340,"status":4,"sort":8,"name":1411,"item":1412},"Translation Glossary",[1413],{"collection":1391,"item":1414},{"id":162,"status":4,"slug":1415},"glossary",{"collection":1283,"item":1417},{"id":107,"status":4,"sort":8,"url":1418,"url_text":1419,"show_favorite_icon":229},"\u002Fdocs\u002Fgeneral\u002Freviewing-translations","Quality control",{"collection":1216,"item":1421},{"id":878,"status":4,"sort":8,"name":1422,"item":1423},"Connected Projects",[1424],{"collection":1391,"item":1425},{"id":7,"status":4,"slug":1426},"connected-projects",{"collection":1216,"item":1428},{"id":314,"status":4,"sort":8,"name":1429,"item":1430},"Plural handling",[1431],{"collection":1391,"item":1432},{"id":527,"status":4,"slug":1433},"plurals",{"collection":1216,"item":1435},{"id":318,"status":4,"sort":8,"name":1436,"item":1437},"Style guides",[1438],{"collection":1391,"item":1439},{"id":336,"status":4,"slug":1440},"style-guide",{"navigation_items_group_id":1442},{"id":29,"sort":62,"status":4,"name":1443,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1444},"Translation",[1445,1452,1459,1463,1470,1477,1485],{"collection":1216,"item":1446},{"id":751,"status":4,"sort":8,"name":1447,"item":1448},"Professional translations",[1449],{"collection":1399,"item":1450},{"id":526,"status":4,"slug":1451},"professional-translation-services",{"collection":1216,"item":1453},{"id":1099,"status":4,"sort":8,"name":1454,"item":1455},"Crowdsourced translations",[1456],{"collection":1391,"item":1457},{"id":67,"status":4,"slug":1458},"share-tm",{"collection":1283,"item":1460},{"id":50,"status":4,"sort":8,"url":1461,"url_text":1462,"show_favorite_icon":229},"\u002Fdocs\u002Fgeneral\u002Ftranslating-strings","Translation interface",{"collection":1216,"item":1464},{"id":364,"status":4,"sort":8,"name":1465,"item":1466},"Machine translations",[1467],{"collection":1391,"item":1468},{"id":50,"status":4,"slug":1469},"machine-translation",{"collection":1216,"item":1471},{"id":278,"status":4,"sort":8,"name":1472,"item":1473},"Localazy AI translation",[1474],{"collection":1391,"item":1475},{"id":1183,"status":4,"slug":1476},"localazy-ai",{"collection":1216,"item":1478},{"id":1479,"status":4,"sort":8,"name":1480,"item":1481},61,"Translation Memory",[1482],{"collection":1391,"item":1483},{"id":666,"status":4,"slug":1484},"translation-memory",{"collection":1216,"item":1486},{"id":603,"status":4,"sort":8,"name":1487,"item":1488},"Code & placeholders",[1489],{"collection":1391,"item":1490},{"id":526,"status":4,"slug":1491},"code-and-placeholders",{"navigation_items_group_id":1493},{"id":43,"sort":67,"status":4,"name":1494,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1495},"Management",[1496,1500,1507,1515,1523,1530,1534],{"collection":1283,"item":1497},{"id":67,"status":4,"sort":8,"url":1498,"url_text":1499,"show_favorite_icon":229},"\u002Fdocs\u002Fgeneral\u002Fdefining-user-roles","User roles",{"collection":1216,"item":1501},{"id":309,"status":4,"sort":8,"name":1502,"item":1503},"Duplicity Linking",[1504],{"collection":1391,"item":1505},{"id":170,"status":4,"slug":1506},"duplicity-linking",{"collection":1216,"item":1508},{"id":1509,"status":4,"sort":8,"name":1510,"item":1511},52,"Language Permissions",[1512],{"collection":1391,"item":1513},{"id":99,"status":4,"slug":1514},"language-permissions",{"collection":1216,"item":1516},{"id":275,"status":1517,"sort":8,"name":1518,"item":1519},"draft","Automations",[1520],{"collection":1391,"item":1521},{"id":174,"status":4,"slug":1522},"automations",{"collection":1216,"item":1524},{"id":1102,"status":4,"sort":8,"name":1525,"item":1526},"Branching",[1527],{"collection":1391,"item":1528},{"id":947,"status":4,"slug":1529},"branching",{"collection":1283,"item":1531},{"id":99,"status":1517,"sort":8,"url":1532,"url_text":1533,"show_favorite_icon":229},"https:\u002F\u002Flocalazy.com\u002Fdocs\u002Fgeneral\u002Fsso-configuration","SSO",{"collection":1283,"item":1535},{"id":1363,"status":1517,"sort":8,"url":1536,"url_text":1537,"show_favorite_icon":229},"https:\u002F\u002Flocalazy.com\u002Fdocs\u002Fgeneral\u002Flanguage-statistics","Reporting",{"navigation_items_group_id":1539},{"id":150,"sort":72,"status":4,"name":1540,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1541},"Development",[1542,1548,1554,1561,1568,1575,1582],{"collection":1216,"item":1543},{"id":1183,"status":4,"sort":8,"name":130,"item":1544},[1545],{"collection":1391,"item":1546},{"id":36,"status":4,"slug":1547},"translation-api",{"collection":1216,"item":1549},{"id":222,"status":4,"sort":8,"name":1550,"item":1551},"Localazy CLI",[1552],{"collection":1391,"item":1553},{"id":62,"status":4,"slug":352},{"collection":1216,"item":1555},{"id":527,"status":4,"sort":8,"name":1556,"item":1557},"Language CDN",[1558],{"collection":1391,"item":1559},{"id":107,"status":4,"slug":1560},"language-cdn",{"collection":1216,"item":1562},{"id":1302,"status":4,"sort":8,"name":1563,"item":1564},"Releases",[1565],{"collection":1391,"item":1566},{"id":57,"status":4,"slug":1567},"releases",{"collection":1216,"item":1569},{"id":1163,"status":1517,"sort":8,"name":1570,"item":1571},"Format Conversions",[1572],{"collection":1391,"item":1573},{"id":16,"status":4,"slug":1574},"format-conversions",{"collection":1216,"item":1576},{"id":259,"status":4,"sort":8,"name":1577,"item":1578},"Webhooks",[1579],{"collection":1391,"item":1580},{"id":580,"status":4,"slug":1581},"webhooks",{"collection":1216,"item":1583},{"id":701,"status":4,"sort":8,"name":1584,"item":1585},"Export Aliases",[1586],{"collection":1391,"item":1587},{"id":222,"status":4,"slug":1588},"export-aliases",{"id":107,"name":142,"url":8,"url_text":8,"status":4,"groups":1590},[1591,1680],{"navigation_items_group_id":1592},{"id":62,"sort":77,"status":4,"name":1593,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1594},"Most popular",[1595],{"collection":1216,"item":1596},{"id":29,"status":4,"sort":8,"name":142,"item":1597},[1598,1606,1613,1617,1621,1627,1631,1638,1642,1646,1650,1654,1658,1665,1672],{"collection":1599,"item":1600},"platforms",{"id":57,"status":4,"sort":7,"slug":1601,"name":1602,"icon":1603},"android","Android",{"id":1604,"title":1605},"ff965add-53b0-44ad-b27c-ea4ef641d384","Ic Outline Android",{"collection":1599,"item":1607},{"id":62,"status":4,"sort":16,"slug":1608,"name":1609,"icon":1610},"ios","iOS",{"id":1611,"title":1612},"886285d7-816a-4430-b5a5-edfe307b238e","Ios",{"collection":1599,"item":1614},{"id":222,"status":4,"sort":22,"slug":226,"name":225,"icon":1615},{"id":239,"title":1616},"Logos React",{"collection":1599,"item":1618},{"id":170,"status":4,"sort":107,"slug":390,"name":389,"icon":1619},{"id":397,"title":1620},"Vue",{"collection":1599,"item":1622},{"id":158,"status":4,"sort":50,"slug":1623,"name":1624,"icon":1625},"angular","Angular",{"id":1626,"title":1624},"2a31a97a-48c5-4531-aa36-41c9dd0bdbef",{"collection":1599,"item":1628},{"id":7,"status":4,"sort":57,"slug":471,"name":470,"icon":1629},{"id":485,"title":1630},"Logos Flutter",{"collection":1599,"item":1632},{"id":22,"status":4,"sort":36,"slug":1633,"name":1634,"icon":1635},"typescript","TypeScript",{"id":1636,"title":1637},"8d1319b5-8a96-4199-8407-00add3418b1f","Logos Typescript Icon",{"collection":1599,"item":1639},{"id":580,"status":4,"sort":29,"slug":584,"name":583,"icon":1640},{"id":593,"title":1641},"Logos Javascript",{"collection":1599,"item":1643},{"id":29,"status":4,"sort":174,"slug":236,"name":673,"icon":1644},{"id":686,"title":1645},"Logos Json",{"collection":1599,"item":1647},{"id":99,"status":4,"sort":99,"slug":758,"name":757,"icon":1648},{"id":773,"title":1649},"Format",{"collection":1599,"item":1651},{"id":1030,"status":4,"sort":1037,"slug":1034,"name":1033,"icon":1652},{"id":1041,"title":1653},"Strapi Logo Purple",{"collection":1599,"item":1655},{"id":278,"status":4,"sort":364,"slug":1139,"name":1138,"icon":1656},{"id":1147,"title":1657},"Figma Icon",{"collection":1599,"item":1659},{"id":309,"status":4,"sort":340,"slug":1660,"name":1661,"icon":1662},"microsoft-excel","Microsoft Excel",{"id":1663,"title":1664},"7a175955-7b96-4561-939f-a0e1924faa40","Excel",{"collection":1599,"item":1666},{"id":320,"status":4,"sort":1479,"slug":1667,"name":1668,"icon":1669},"github-actions","GitHub Actions",{"id":1670,"title":1671},"da17554f-ac6d-443d-9bac-1f29645ec1c6","Github Icon",{"collection":1599,"item":1673},{"id":1674,"status":4,"sort":1675,"slug":1676,"name":1677,"icon":1678},97,999,"webflow","Webflow",{"id":1679,"title":1677},"ff43a386-52f8-499f-b77c-ab9a30f4a77e",{"navigation_items_group_id":1681},{"id":107,"sort":36,"status":4,"name":1682,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1683},"Explore more",[1684],{"collection":1685,"item":1686},"text_link_navigation_item_type",{"id":7,"status":4,"sort":8,"text":1687,"url":1688,"url_text":1689},"Localazy is a technology-agnostic platform supporting 50+ frameworks, file formats & popular tools.","\u002Fintegrations","See all integrations",{"id":7,"name":146,"url":8,"url_text":8,"status":4,"groups":1691},[1692,1716,1722],{"navigation_items_group_id":1693},{"id":7,"sort":29,"status":4,"name":1694,"render_show_all_url":229,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":8,"represent_as_tile":229,"items":1695},"Helpful Links",[1696,1699,1701,1705,1707,1710,1712],{"collection":1283,"item":1697},{"id":43,"status":4,"sort":8,"url":168,"url_text":1698,"show_favorite_icon":230},"Localazy Blog",{"collection":1283,"item":1700},{"id":150,"status":4,"sort":8,"url":152,"url_text":151,"show_favorite_icon":230},{"collection":1283,"item":1702},{"id":7,"status":4,"sort":8,"url":1703,"url_text":1704,"show_favorite_icon":229},"https:\u002F\u002Fdiscuss.localazy.com\u002F","Discussion Forum",{"collection":1283,"item":1706},{"id":29,"status":4,"sort":8,"url":160,"url_text":159,"show_favorite_icon":229},{"collection":1283,"item":1708},{"id":22,"status":4,"sort":8,"url":109,"url_text":1709,"show_favorite_icon":229},"Become a Partner",{"collection":1283,"item":1711},{"id":154,"status":4,"sort":8,"url":172,"url_text":171,"show_favorite_icon":229},{"collection":1283,"item":1713},{"id":162,"status":4,"sort":8,"url":1714,"url_text":1715,"show_favorite_icon":229},"\u002Ftags\u002Frelease-update","Release Updates",{"navigation_items_group_id":1717},{"id":16,"sort":150,"status":4,"name":1698,"render_show_all_url":230,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":168,"represent_as_tile":229,"items":1718},[1719],{"collection":1207,"item":1720},{"id":22,"status":4,"sort":8,"show_author_img":229,"blog_post_tag":1721,"description":8},"[USE LATEST FEATURED]",{"navigation_items_group_id":1723},{"id":57,"sort":43,"status":4,"name":151,"render_show_all_url":230,"show_all_url_position":1204,"show_favorite_icon":229,"show_all_url":152,"represent_as_tile":229,"items":1724},[1725,1739,1750,1759,1770,1780,1791,1799],{"collection":1216,"item":1726},{"id":107,"status":4,"sort":8,"name":1727,"item":1728},"General",[1729],{"collection":1730,"item":1731},"docs_section",{"id":16,"status":4,"sort":7,"slug":1732,"name":1727,"icon":1733,"featured_icon":1736},"general",{"id":1734,"title":1735},"423101f1-308c-42f1-8dfe-53272019e7cb","Global",{"id":1737,"title":1738},"0f7ca4cb-dc3b-4f62-b476-132ed5c4931f","General Doc",{"collection":1216,"item":1740},{"id":50,"status":4,"sort":8,"name":351,"item":1741},[1742],{"collection":1730,"item":1743},{"id":22,"status":4,"sort":16,"slug":352,"name":351,"icon":1744,"featured_icon":1747},{"id":1745,"title":1746},"2f7a4573-8265-4d76-8d55-ce0cc79b8983","Cli",{"id":1748,"title":1749},"3f76ff7b-0e74-4046-bb03-4ca99c3b66d5","Doc Cat Cli",{"collection":1216,"item":1751},{"id":67,"status":4,"sort":8,"name":283,"item":1752},[1753],{"collection":1730,"item":1754},{"id":174,"status":4,"sort":22,"slug":284,"name":283,"icon":1755,"featured_icon":1756},{"id":1745,"title":1746},{"id":1757,"title":1758},"20866781-e69b-4e01-9456-05437487b75c","API Doc",{"collection":1216,"item":1760},{"id":255,"status":4,"sort":8,"name":1761,"item":1762},"CDN",[1763],{"collection":1730,"item":1764},{"id":941,"status":4,"sort":107,"slug":1765,"name":1761,"icon":1766,"featured_icon":1767},"cdn",{"id":1734,"title":1735},{"id":1768,"title":1769},"a8ee9cb7-4e02-41f0-b595-eb518c3085b6","Doc Cat Cdn",{"collection":1216,"item":1771},{"id":57,"status":4,"sort":8,"name":1602,"item":1772},[1773],{"collection":1730,"item":1774},{"id":7,"status":4,"sort":50,"slug":1601,"name":1602,"icon":1775,"featured_icon":1777},{"id":1776,"title":1602},"fb8329ae-0c0c-4fbc-bcdc-83f2eeda1039",{"id":1778,"title":1779},"f7c0dec8-5b42-4943-ab3a-e3665723ad6f","Doc Cat Android",{"collection":1216,"item":1781},{"id":62,"status":4,"sort":8,"name":1609,"item":1782},[1783],{"collection":1730,"item":1784},{"id":107,"status":4,"sort":57,"slug":1608,"name":1609,"icon":1785,"featured_icon":1788},{"id":1786,"title":1787},"289e136c-55df-4d51-847b-1782a2308ee4","Ios Blue",{"id":1789,"title":1790},"2968d3f0-14b5-4427-82e7-f1ea2de17846","Doc Cat Ios",{"collection":1216,"item":1792},{"id":72,"status":4,"sort":8,"name":1138,"item":1793},[1794],{"collection":1730,"item":1795},{"id":99,"status":4,"sort":62,"slug":1139,"name":1138,"icon":1796,"featured_icon":1797},{"id":1745,"title":1746},{"id":1798,"title":1138},"f5e66b5b-a439-47f6-af4a-6ad261de2e87",{"collection":1216,"item":1800},{"id":77,"status":4,"sort":8,"name":1033,"item":1801},[1802],{"collection":1730,"item":1803},{"id":1179,"status":4,"sort":67,"slug":1034,"name":1033,"icon":1804,"featured_icon":1806},{"id":1805,"title":1033},"3b4b03c7-e131-49e6-a014-c8c2c8a2751e",{"id":1807,"title":1808},"1dd05c76-e517-4aea-a3d8-49cfddb40056","Strapi Doc",{"id":22,"name":175,"url":176,"url_text":175,"status":4,"groups":1810},[],{"id":57,"name":93,"url":1812,"url_text":93,"status":4,"groups":1813},"\u002Fbook-demo",[],{"id":1815,"owner":1816,"created_by":8,"sort":8,"title":1821,"slug":1822,"modified_on":53,"created_on":1823,"pinned":229,"badge":8,"priority":1824,"main_image":1825,"status":4,"tags":1826,"dictionary":1834,"reading_time":1835,"excerpt":-1,"og_title":53,"og_description":53,"og_image":53},"69d78a237ab1270001eddabf",{"id":1817,"first_name":1818,"last_name":53,"slug":1819,"avatar":1820},"606c233dcf7b6a0001d1da93","Petr Hodný","petr-hodny","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F12\u002Fpetr.png","Translation API: Translate your content on the fly with Localazy AI!","translation-api-translate-your-content-on-the-fly-with-localazy-ai","2026-04-24T09:27:26.000+02:00","0.7","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2026\u002F04\u002FLocalazy-AI-translation-api.png",[1827,1829,1832],{"id":278,"created_on":1828,"status":4,"label":283,"slug":284,"on_index_page":229},"2026-06-06 04:29:34",{"id":314,"created_on":1828,"status":4,"label":1830,"slug":1831,"on_index_page":230},"AI","ai",{"id":278,"created_on":1828,"status":4,"label":1384,"slug":1833,"on_index_page":230},"localization",[],0,{"id":1837,"owner":1838,"created_by":8,"sort":8,"title":1843,"slug":1844,"modified_on":53,"created_on":1845,"pinned":229,"badge":8,"priority":1824,"main_image":1846,"status":4,"tags":1847,"dictionary":1855,"reading_time":1835,"excerpt":-1,"og_title":53,"og_description":53,"og_image":53},"6a145e3f8550a300014081e4",{"id":1839,"first_name":1840,"last_name":53,"slug":1841,"avatar":1842},"65647a510470910001942876","Dorota Pawlak","dorota-pawlak","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2024\u002F07\u002Fdorota.png","The great LLM translation war, pt. 2: Context beats model choice in 2026","the-great-llm-translation-war-pt-2-2026","2026-06-05T14:56:58.000+02:00","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2026\u002F06\u002Flocalazy-AI-series-11.png",[1848,1849,1852],{"id":314,"created_on":1828,"status":4,"label":1830,"slug":1831,"on_index_page":230},{"id":314,"created_on":1828,"status":4,"label":1850,"slug":1851,"on_index_page":229},"ChatGPT","chatgpt",{"id":278,"created_on":1828,"status":4,"label":1853,"slug":1854,"on_index_page":229},"Translations","translations",[],{"post":1857,"relatedPosts":1961,"banner":2020},{"id":1858,"owner":1859,"created_by":8,"sort":8,"title":1864,"slug":1865,"modified_on":1866,"created_on":1867,"pinned":230,"badge":8,"priority":1824,"main_image":1868,"status":4,"tags":1869,"dictionary":1879,"reading_time":77,"excerpt":1905,"og_title":53,"og_description":53,"og_image":53,"content":1906,"meta_title":53,"meta_description":53,"canonical":53,"cta":1907,"fullGhostPost":1915},"64144f06047091000193ad2f",{"id":1860,"first_name":1861,"last_name":53,"slug":1862,"avatar":1863},"6092822ecf7b6a0001d1dab3","David Václavek","david-vaclavek","\u002F\u002Fwww.gravatar.com\u002Favatar\u002F90788a3f3dc9558a151a87d7fe096592?s=250&d=mm&r=x","Test Alerts using STOMP over WebSocket in Cypress E2E Tests","test-alerts-using-stomp-over-websocket-in-cypress-e2e-tests","2023-05-18T11:22:02.000+02:00","2023-04-04T15:20:14.000+02:00","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F04\u002Fcypress-e2e.png",[1870,1873,1876],{"id":278,"created_on":1828,"status":4,"label":1871,"slug":1872,"on_index_page":229},"HowTo","howto",{"id":278,"created_on":1828,"status":4,"label":1874,"slug":1875,"on_index_page":230},"DevTips","devtips",{"id":278,"created_on":1828,"status":4,"label":1877,"slug":1878,"on_index_page":229},"CI","ci",[1880,1890],{"id":342,"status":4,"owner":1881,"created_on":1882,"title":1877,"excerpt":1883,"content":1884,"slug":1878,"meta_title":8,"meta_description":8,"canonical":8,"related_terms":1885},"2bac48a8-b362-482f-b574-3bc71dca4c5b","2022-03-17T12:22:55.000Z","CI can stand for Continuous Integration or Continuous Improvement. What is the difference?","CI can stand for Continuous Integration or Continuous Improvement. \n\nWhat is the difference?\n\n+ [Continuous Improvement](\u002Fdictionary\u002Fcontinuous-improvement\u002F) in Organizational Management\n+ [Continuous Integration](\u002Fdictionary\u002Fcontinuous-integration\u002F) in Software Development",[1886,1888],{"id":1163,"slug":1887},"continuous-improvement",{"id":1102,"slug":1889},"continuous-integration",{"id":43,"status":4,"owner":1881,"created_on":1891,"title":1892,"excerpt":1893,"content":1894,"slug":1469,"meta_title":53,"meta_description":53,"canonical":53,"related_terms":1895},"2026-05-12T07:09:22.000Z","Machine translation (MT)","The process of translating using computational linguistics.","A machine translation engine is a software tool that translates a text from one language to another without the help of human translators.\n\nMachine translation, also known as MT, is widely used as the first round of translations and is frequently very effective for short strings. However, it can produce unsatisfactory results when context knowledge is required, and thus, a human review is always advised.\n\n### 💬 Methods used in machine translation\n\nMachine translation engines recently experienced huge improvements related to the advanced use of neural networks, but they generally rely on these different methods:\n\n* [Statistical machine translation (SMT)](https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fstatistical-machine-translation\u002F \"https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fstatistical-machine-translation\u002F\")\n* [Example-based machine translation (EBMT)](https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fexample-based-machine-translation \"https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fexample-based-machine-translation\")\n* [Hybrid machine translation (HMT)](https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fhybrid-machine-translation \"https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fhybrid-machine-translation\")\n* [Neural machine translation (NMT)](https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fneural-machine-translation\u002F \"https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fneural-machine-translation\u002F\")\n\nNeural machine translation (used by [AI-powered translation](https:\u002F\u002Flocalazy.com\u002Fdictionary\u002Fai-powered-translation) engines) is the most sophisticated type of instant translation today. It uses machine learning to improve its translation capabilities. As the engine translates more text with each request, the better results it produces with time by learning. Most instant translation services use this technology.\n\n### 🔍 What's the difference between HAMT and MAHT?\n\nWithin the realm of machine translation, it’s important to distinguish between **Human-Assisted Machine Translation (HAMT)** and **Machine-Assisted Human Translation (MAHT)**:\n\n* [**Human-Assisted Machine Translation (HAMT)**](\u002Fdictionary\u002Fhuman-assisted-mt): This process involves a human reviewing translations generated by machine translation (MT) engines. It is also known as MT plus post-editing and\u002For pre-editing. The machine handles the initial translation, which is then edited by a human to improve accuracy and context. This approach is useful for projects with repetitive content and where budget or time constraints are significant.\n* [**Machine-Assisted Human Translation (MAHT)**](\u002Fdictionary\u002Fmaht): In this method, human translators use computer software to aid their work. Translators receive machine translation suggestions, but they decide how to use them. This approach allows for high translation accuracy while benefiting from features like translation glossaries and memories, which enhance the efficiency and consistency of the translation process.\n\n### 🦾 MT engines available in Localazy \n\nLocalazy users can use the most popular and advanced [MT engines](https:\u002F\u002Flocalazy.com\u002Ffeatures\u002Fmachine-translation \"https:\u002F\u002Flocalazy.com\u002Ffeatures\u002Fmachine-translation\") to translate their content:\n\n* Amazon Translate (available for free)\n* Google Translate\n* DeepL\n* Azure Translator\n* OpenAI (ChatGPT), with your own API key\n\n> *Users can unlock different engines depending on the plan they buy. See our [pricing](https:\u002F\u002Flocalazy.com\u002Fpricing) and [docs](https:\u002F\u002Flocalazy.com\u002Fdocs\u002Fgeneral\u002Fadditional-mt-engines?srsltid=AfmBOoo--lURSBHDiHEoe3rYL3xSQHaZcTsl6kd7wwUYRGC-sGTTmG94 \"https:\u002F\u002Flocalazy.com\u002Fdocs\u002Fgeneral\u002Fadditional-mt-engines?srsltid=AfmBOoo--lURSBHDiHEoe3rYL3xSQHaZcTsl6kd7wwUYRGC-sGTTmG94\") for more details.*\n\n### 📚 Additional resources:\n\n* [What is machine translation?](https:\u002F\u002Fwww.gala-global.org\u002Fwhat-machine-translation)\n* [History of machine translation](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHistory_of_machine_translation)",[1896,1898,1900,1902],{"id":580,"slug":1897},"maht",{"id":1055,"slug":1899},"mtpe-machine-translation-post-editing",{"id":984,"slug":1901},"deepl",{"id":1903,"slug":1904},136,"human-assisted-mt","Learn how to test alerts using STOMP over WebSocket in Cypress E2E Tests in this Localazy Developer Tutorial by David Václavek.","\u003Ch2 id=\"introduction\">👋 Introduction \u003Ca class=\"markdownit-header-anchor\" href=\"#introduction\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Cp>Why did I even want to write this article in the first place? 😬 As a part of one of my tasks, I was supposed to handle long-running operations which use WebSockets for communication. \u003C\u002Fp>\u003Cp>The goal was to test the events that follow after finishing a long-running operation. We use STOMP over WebSocket (I will explain what it means later, don't worry). We also take advantage of CI on GitHub and Cypress framework to ensure that the product passes the automated tests before we release a new feature.\u003C\u002Fp>\u003Cp>I spent almost a day Googling and reading through GitHub threads for a good solution that would work for our case - unfortunately, without any success. 😤\u003C\u002Fp>\u003Cp>Basically, all of the methods I found use Socket.IO or a non-specified message format, and most of the solutions discussed on Stack Overflow and GitHub ended up not working for most of the users, which really surprised me.\u003C\u002Fp>\u003Cp>Do developers just not test the actions that happen after a WebSocket message is received? I do not certainly know the answer to this question, but it definitely motivated me to write this post. 🤠\u003C\u002Fp>\u003Ch2 id=\"what-is-stomp-over-websocket\">🤔 What is STOMP over WebSocket? \u003Ca class=\"markdownit-header-anchor\" href=\"#what-is-stomp-over-websocket\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Cp>STOMP itself is a simple text-oriented messaging protocol. It defines an interoperable wire format so that any of the available STOMP clients can communicate with any STOMP message broker to provide easy and widespread messaging interoperability among languages and platforms.\u003C\u002Fp>\u003Cp>Raw WebSockets can be used without STOMP. STOMP is derived on top of WebSockets. STOMP just mentions a few specific ways in which the message frames are exchanged between the client and the server using WebSockets.\u003C\u002Fp>\u003Cp>Besides \u003Ca href=\"https:\u002F\u002Fstomp.github.io\u002Fstomp-specification-1.2.html\">STOMP\u003C\u002Fa>, there are various standardized protocols, e.g. \u003Ca href=\"https:\u002F\u002Fsocket.io\u002Fdocs\u002Fv4\u002Fsocket-io-protocol\u002F\">Socket.IO\u003C\u002Fa> or \u003Ca href=\"https:\u002F\u002Fwamp-proto.org\u002Fwamp_latest_ietf.html\">WAMP\u003C\u002Fa>. For the sake of maintainability, you should definitely use something standardized. 👈\u003C\u002Fp>\u003Cp>Why do we use STOMP, then? Well, both Broker and client are easy-to-implement. We use ActiveMQ as the broker, which works basically out of the box. Also, there are good TypeScript libraries that are easy to use and work well.\u003C\u002Fp>\u003Ch2 id=\"localazy-alerts\">🚩 Localazy Alerts \u003Ca class=\"markdownit-header-anchor\" href=\"#localazy-alerts\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Cp>Now, I’d like to give you a quick overview of alerts in Localazy to fully understand the problem. In the screenshot below, you can see a \u003Cem>Success\u003C\u002Fem> and a \u003Cem>Wait\u003C\u002Fem> alert type at the bottom. Apart from those, we have a few more types, not relevant at this moment.\u003C\u002Fp>\u003Cfigure class=\"kg-card kg-image-card kg-card-hascaption\">\u003Cimg src=\"https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"2000\" height=\"1415\" srcset=\"https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw600\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 600w, https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw1000\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 1000w, https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw1600\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 1600w, https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw2400\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 2400w\" sizes=\"(min-width: 720px) 720px\">\u003Cfigcaption>Alerts sample in Localazy\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>Obviously, not all of the alerts are controlled over WebSockets. Although, some of them are:\u003C\u002Fp>\u003Cul>\u003Cli>project publishing status,\u003C\u002Fli>\u003Cli>long-running operations,\u003C\u002Fli>\u003Cli>approving translations,\u003C\u002Fli>\u003Cli>sending translations back to review,\u003C\u002Fli>\u003Cli>MT \u003Ca href=\"\u002Ffeatures\u002Fpre-translate\">pre-translate\u003C\u002Fa> keys.\u003C\u002Fli>\u003C\u002Ful>\u003Cp>“\u003Cstrong>Why are these tasks time-consuming and therefore cannot be processed immediately?\u003C\u002Fstrong>” you may ask. There are quite complex internal database processes in our backend, sometimes, we need to create physical files and make them ready for an eventual download. MT pre-translate is processed by a machine translation engine provider on the fly, which also takes time, especially when there are lots of keys sent.\u003C\u002Fp>\u003Cp>\u003Cstrong>These long-running operations can also be grouped\u003C\u002Fstrong> (for improved UX). What do I mean by that?\u003C\u002Fp>\u003Cp>An API sends these long-running operations per language (or file). Therefore triggering the pre-translate action for eight languages at the same time sends eight requests to the backend. Another example could be approving all translations in three files at once, which would send three requests.\u003C\u002Fp>\u003Cp>I believe the topic of long-running operations and their grouping is clear now. Let’s move on to the next part.\u003C\u002Fp>\u003Ch2 id=\"our-goal\">🎯 Our goal \u003Ca class=\"markdownit-header-anchor\" href=\"#our-goal\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Cp>Now, I’d like to summarize the goal and give you some more important details. So, here's a bullet list:\u003C\u002Fp>\u003Cul>\u003Cli>include alerts testing in our E2E tests\u003C\u002Fli>\u003Cli>long-running operation API request returns the \u003Ccode>taskId\u003C\u002Fcode> of a task\u003C\u002Fli>\u003Cli>under this \u003Ccode>taskId\u003C\u002Fcode>, the request will be processed on the backend\u003C\u002Fli>\u003Cli>when the task finishes, a STOMP message will be sent to the client, including the \u003Ccode>taskId\u003C\u002Fcode> - this is the moment we know that the task is finished\u003C\u002Fli>\u003Cli>want to ensure that when the project is published\u003C\u002Fli>\u003Cli>need to make sure that long-running operations are processed properly\u003C\u002Fli>\u003Cli>\u003Cem>Wait\u003C\u002Fem> alert is initiated correctly\u003C\u002Fli>\u003Cli>\u003Cem>Wait\u003C\u002Fem> progress is calculated correctly\u003C\u002Fli>\u003Cli>when one of the tasks in the tasks group is done, update the percentage progress\u003C\u002Fli>\u003Cli>when all of the tasks in the group are finished, turn the \u003Cem>Wait\u003C\u002Fem> notification into a \u003Cem>Success\u003C\u002Fem> notification\u003C\u002Fli>\u003Cli>also, when tasks from other groups finish during the processing of multiple tasks groups together (which in terms of UI means having multiple \u003Cem>Wait\u003C\u002Fem> notifications at one time), it should impact only the group the task is assigned to\u003C\u002Fli>\u003Cli>we want to include those tests in the CI process on GitHub\u003C\u002Fli>\u003Cli>we have all of the data for our E2E tests mocked and prepared in fixtures; therefore, no real server endpoints are called\u003C\u002Fli>\u003C\u002Ful>\u003Ch2 id=\"failed-attempts\">🧭 Failed attempts \u003Ca class=\"markdownit-header-anchor\" href=\"#failed-attempts\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Cp>Before we get to my solution, here's a list of some of the packages dedicated to solving our goal I’ve found and tried, such as:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcypress-websocket-plugin\">cypress-websocket-plugin\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcypress-mock-websocket-plugin\">cypress-mock-websocket-plugin\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Ffake-websocket\">fake-websocket\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmock-socket\">mock-socket\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmock-stomp-broker\">mock-stomp-broker\u003C\u002Fa>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>And as I’ve already mentioned in the Introduction, \u003Cstrong>none of the options above did work for me\u003C\u002Fstrong> for various reasons.\u003C\u002Fp>\u003Cp>That’s why I decided to solve it my way. \u003C\u002Fp>\u003Ch2 id=\"the-solution\">💎 The Solution \u003Ca class=\"markdownit-header-anchor\" href=\"#the-solution\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Ch3 id=\"own-stomp-broker\">Own STOMP Broker \u003Ca class=\"markdownit-header-anchor\" href=\"#own-stomp-broker\">🔗\u003C\u002Fa>\u003C\u002Fh3>\u003Cp>I decided to code my own STOMP Broker - I don’t mean the whole implementation, of course, but only a part of communication that needs to be mocked I could use while writing tests. So what I needed to achieve was to inform the STOMP Client that a task with some \u003Ccode>taskId\u003C\u002Fcode> has been finished so the application can react to such an event.\u003C\u002Fp>\u003Cp>I used the \u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fstomp-broker-js\">stomp-broker-js\u003C\u002Fa> package for the implementation. It was simple to set up, the README example was mostly enough to get the inspiration for how it works. \u003C\u002Fp>\u003Cp>I needed to handle messages as the real STOMP Broker (that we use) does. Quick facts:\u003C\u002Fp>\u003Cul>\u003Cli>service is subscribed to a topic \u003Ccode>\u002Ftopic\u002Flocalazy.notifications\u003C\u002Fcode>,\u003C\u002Fli>\u003Cli>process the \u003Ccode>NOTIFY\u002FN\u002F21\u002F[some_id]\u003C\u002Fcode> message for \u003Cem>Project Published\u003C\u002Fem> event\u003C\u002Fli>\u003Cli>process the \u003Ccode>TASK\u002F[some_id]\u002F[finished_task_id]\u003C\u002Fcode> message for \u003Cem>Long-running operation\u003C\u002Fem> event\u003C\u002Fli>\u003C\u002Ful>\u003Cpre>\u003Ccode class=\"language-node\">const http = require(\"http\");\n\u002F\u002F eslint-disable-next-line import\u002Fno-extraneous-dependencies\nconst StompServer = require(\"stomp-broker-js\");\n\nconst server = http.createServer((request) =&gt; {\n  console.log(request.url);\n});\nconst stompServer = new StompServer({\n  server,\n  debug: console.log,\n  path: \"\u002Fapi\u002Fws\u002Fstomp\",\n  protocol: \"ws\",\n  \u002F\u002F v10.stomp', 'v11.stomp', 'v12.stomp'\n  heartbeat: [10000, 10000],\n});\nconsole.log(\" [*] Listening on 0.0.0.0:3322\");\nserver.listen(3322, \"localhost\");\n\nstompServer.subscribe(\"\u002Fe2e\u002Flong-running-operation.finished\", (msg, headers) =&gt; {\n  const topic = headers.destination;\n  console.log(`topic:${topic} messageType: ${typeof msg}`, msg, headers);\n  stompServer.send(\n    \"\u002Ftopic\u002Flocalazy.notifications\",\n    headers,\n    `TASK\u002Fsome_id\u002F${msg}`,\n  );\n});\n\nstompServer.subscribe(\"\u002Fe2e\u002Fproject.published\", (msg, headers) =&gt; {\n  const topic = headers.destination;\n  console.log(`topic:${topic} messageType: ${typeof msg}`, msg, headers);\n  stompServer.send(\n    \"\u002Ftopic\u002Flocalazy.notifications\",\n    headers,\n    \"NOTIFY\u002FN\u002F21\u002Fsome_id\",\n  );\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>As can be seen in the code snippet above, the broker is listening to two topics:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ccode>\u002Fe2e\u002Flong-running-operation.finished\u003C\u002Fcode>\u003C\u002Fli>\u003Cli>\u003Ccode>\u002Fe2e\u002Fproject.published\u003C\u002Fcode>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Why did I do that?\u003Cstrong> The mocked broker needs to work differently than a real backend-to-broker communication does\u003C\u002Fstrong>. The real backend would process the task, and then (when finished) it would inform the broker, which would send a message to the client.\u003C\u002Fp>\u003Cp>But in our test case, nothing is really being processed. That’s why we programmatically need to send a message to our subscribed topics from the E2E test code (and hence trigger the “\u003Cem>Hey, I’m the task with \u003Ccode>taskId\u003C\u002Fcode> and I’ve just finished processing\u003C\u002Fem>” procedure). And we need to do so after the long-running operation was initiated.\u003C\u002Fp>\u003Cp>That would then return the very same message as the real broker would do. Voilà!\u003C\u002Fp>\u003Ch3 id=\"ping-the-stomp-broker-from-cypress\">Ping the STOMP Broker from Cypress \u003Ca class=\"markdownit-header-anchor\" href=\"#ping-the-stomp-broker-from-cypress\">🔗\u003C\u002Fa>\u003C\u002Fh3>\u003Cp>Notice one of the earlier sentences:\u003C\u002Fp>\u003Cblockquote>… we programmatically need to send a message to our subscribed topics from the E2E test code…\u003C\u002Fblockquote>\u003Cp>How can we do that? How do we access the very same STOMP Client instance from the App in Cypress? The solution is quite simple and effective and does not make basically any mess in the application code.\u003C\u002Fp>\u003Cp>We’ll reuse a similar concept as described in the \u003Ca href=\"https:\u002F\u002Fdocs.cypress.io\u002Fapi\u002Fcommands\u002Fwindow#Start-tests-when-app-is-ready\">Cypress Docs\u003C\u002Fa>. That way, we can attach the client instance to the global \u003Ccode>window\u003C\u002Fcode> object, which can then be accessed in the test code (by calling a \u003Ccode>cy.window\u003C\u002Fcode> method - I’ll show you that later).\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">this.client = Stomp.client(process.env.VUE_APP_WSS_URL);\n\n\u002F**\n * To access the client from Cypress tests, attach it to the window object.\n *\u002F\nif ((window as any).Cypress) {\n\t(window as any).stompClient = this.client;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cblockquote>Another note: Make sure to pass the correct \u003Ccode>VUE_APP_WSS_URL\u003C\u002Fcode> \u003Ccode>env\u003C\u002Fcode> variable regarding the environment.\u003C\u002Fblockquote>\u003Cp>I.e. for the tests, you’d want to pass the one where our mocked STOMP Broker is running.\u003C\u002Fp>\u003Cp>Normally, you’d want to pass the testing\u002Fproduction address of the broker, depending on your setup.\u003C\u002Fp>\u003Ch3 id=\"write-the-tests\">Write the Tests \u003Ca class=\"markdownit-header-anchor\" href=\"#write-the-tests\">🔗\u003C\u002Fa>\u003C\u002Fh3>\u003Cp>Writing the tests is just the icing on the cake if you know Cypress. If not, there are dozens of materials on the web - check that out! I’ll assume you do know how to work with Cypress.\u003C\u002Fp>\u003Cp>Therefore, I’ll just summarize what I had to deal with while writing WebSockets-related tests.\u003C\u002Fp>\u003Ch3 id=\"returning-a-different-response-for-the-same-request\">Returning a Different Response for the Same Request \u003Ca class=\"markdownit-header-anchor\" href=\"#returning-a-different-response-for-the-same-request\">🔗\u003C\u002Fa>\u003C\u002Fh3>\u003Cp>As mentioned above, there’s a long-running operation request sent per every language (or file). It means that every request returns its own \u003Ccode>taskId\u003C\u002Fcode>. And when the task finishes, a STOMP message is sent containing that particular \u003Ccode>taskId\u003C\u002Fcode> - identifying that the task has been finished.\u003C\u002Fp>\u003Cp>Normally, to intercept a request in Cypress that always returns the same response, I’d do something like this:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">const body = {\n\tresult: true,\n\tid: 'my-task-identifier-xx'\n};\n\ncy.intercept(\"POST\", \"\u002Fapi\u002Fproject\u002F**\u002Fphrases\u002Fbatch\", { body }).as(\"phrasesBatchPOST\");\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>But to deal with the problem, Cypress offers a \u003Ccode>times\u003C\u002Fcode> property which can be sent in an object that’s passed to the \u003Ccode>cy.intercept\u003C\u002Fcode> method:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">const apiIdResult1 = {\n\tresult: true,\n\tid: 'my-task-identifier-01'\n};\n\nconst apiIdResult2 = {\n\tresult: true,\n\tid: 'my-task-identifier-02'\n};\n\ncy.intercept({ method: \"POST\", url: `\u002Fapi\u002Fproject\u002F${project.slug}\u002Fphrases\u002Fbatch`, times: 1 }, (req) =&gt; {\n      req.reply({ body: apiIdResult1 });\n    }).as(\"phrasesBatchPOST1\");\n\ncy.intercept({ method: \"POST\", url: `\u002Fapi\u002Fproject\u002F${project.slug}\u002Fphrases\u002Fbatch`, times: 1 }, (req) =&gt; {\n      req.reply({ body: apiIdResult2 });\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>This way, we can make sure that when we call \u003Ccode>cy.wait(\"phrasesBatchPOST1\")\u003C\u002Fcode>, the request would be intercepted only once.\u003C\u002Fp>\u003Cp>So to wait for two requests (e.g. handling of two languages) to be sent, we’d call:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">cy.wait(\"@phrasesBatchPOST1\");\ncy.wait(\"@phrasesBatchPOST2\");\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"accessing-the-stomp-client-instance\">Accessing the STOMP Client Instance \u003Ca class=\"markdownit-header-anchor\" href=\"#accessing-the-stomp-client-instance\">🔗\u003C\u002Fa>\u003C\u002Fh3>\u003Cp>Just to remind ourselves, we need to access the very same instance of the STOMP Client from Cypress as there is in the application. As I already demonstrated earlier, we’ve attached the client’s instance to the global \u003Ccode>window\u003C\u002Fcode> object.\u003C\u002Fp>\u003Cp>To access it in the test code, we have to invoke the \u003Ccode>cy.window\u003C\u002Fcode> method, like so:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">cy.window().then((win) =&gt; {\n      const { stompClient } = (win as any);\n      stompClient.send(\n\t      \"\u002Fe2e\u002Flong-running-operation.finished\",\n\t      {},\n\t      apiIdResult1.id\n\t  );\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>In the code snippet above, the \u003Ccode>cy.window\u003C\u002Fcode> returns a \u003Ccode>Promise\u003C\u002Fcode>. We then (\u003Ccode>.then\u003C\u002Fcode>) resolve the \u003Ccode>Promise\u003C\u002Fcode>. When it’s resolved, we access the \u003Ccode>stompClient\u003C\u002Fcode>.\u003C\u002Fp>\u003Cp>With the \u003Ccode>stompClient\u003C\u002Fcode> available, we can simply call its \u003Ccode>send\u003C\u002Fcode> method. Notice that we also sent the mocked \u003Ccode>apiIdResult1.id\u003C\u002Fcode> as a \u003Ccode>taskId\u003C\u002Fcode> as a part of the message. The mocked STOMP Broker immediately sends a \u003Ccode>MESSAGE\u003C\u002Fcode> containing the information that \u003Ccode>TASK\u003C\u002Fcode> with \u003Ccode>taskId\u003C\u002Fcode> equal to \u003Ccode>apiIdResult1.id\u003C\u002Fcode> finished.\u003C\u002Fp>\u003Cp>At this point, \u003Cstrong>the test would react as if it was a response from the real (non-mocked) STOMP Broker implementation\u003C\u002Fstrong> we use for Localazy.\u003C\u002Fp>\u003Cp>Now, all the non-usual Cypress (at least for me) stuff is explained.\u003C\u002Fp>\u003Ch3 id=\"update-the-ci-process\">Update the CI Process \u003Ca class=\"markdownit-header-anchor\" href=\"#update-the-ci-process\">🔗\u003C\u002Fa>\u003C\u002Fh3>\u003Cp>As mentioned in the beginning, the goal is also to integrate the whole thing into the CI Process. What does that exactly mean in my case?\u003C\u002Fp>\u003Cp>Well, besides running the E2E testing process, we also need to start the mocked STOMP Broker. When the tests finish, we need to kill the STOMP Broker process respectively. All of that, using the GitHub Workflows.\u003C\u002Fp>\u003Cp>Our newly updated \u003Ccode>e2e.yml\u003C\u002Fcode> looks something like this:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-yml\"># ...\n# Run WS server has been added\n- name: Run WS server\n  run: npm run test:e2e:start-stomp\n- name: Run e2e tests\n  run: npm run test:e2e:ci\n# Stop WS server has been added\n- name: Stop WS server\n  run: npm run test:kill-stomp\n# ... \n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>We just simply added two new steps to the workflow. Let’s see what the scripts look like:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-json\">\u002F\u002F ...\n\"scripts\": {\n\t\"test:e2e:start-stomp\": \"forever start .\u002Ftests\u002Fsupport\u002Fmock-stomp-broker.js\",\n    \"test:kill-stomp\": \"forever stopall\",\n    \u002F\u002F ...\n}\n\u002F\u002F ...\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>We use the \u003Ccode>forever\u003C\u002Fcode> npm package. It offers an easy and intuitive way to run \u003Ccode>node\u003C\u002Fcode> process in the background and kill it on request when needed… Let’s push the code and run the tests!\u003C\u002Fp>\u003Cfigure class=\"kg-card kg-image-card kg-card-hascaption\">\u003Cimg src=\"https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F03\u002Falerts-ws-e2e.gif\" class=\"kg-image\" alt loading=\"lazy\" width=\"1638\" height=\"901\">\u003Cfigcaption>Alerts E2E Tests Run\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cstrong>All tests passed, and we’re all done!\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2 id=\"conclusion\">✔️ Conclusion \u003Ca class=\"markdownit-header-anchor\" href=\"#conclusion\">🔗\u003C\u002Fa>\u003C\u002Fh2>\u003Cp>In this blog post, I demonstrated how to test STOMP over the WebSocket communication we use at Localazy for long-running operations. I also demonstrated a little sneak peek at the dev stack we use.\u003C\u002Fp>\u003Cp>We went through problems I faced during the implementation - and I gave you my solutions.\u003C\u002Fp>\u003Cp>Lastly, we updated the CI process and ran tests to ensure they passed!\u003C\u002Fp>",{"id":43,"status":4,"created_on":1908,"modified_on":1909,"icon":1910,"header":1911,"description":1912,"button_label":1913,"link":1914},"2022-03-17T12:23:03.000Z","2026-05-25T10:38:47.000Z","member","Why developers love Localazy 💖","From mobile apps to SaaS platforms. See how product teams handle translations without slowing down development.\n","See case studies","case-study",{"slug":1865,"id":1858,"uuid":1916,"title":1864,"html":1917,"comment_id":1858,"feature_image":1868,"featured":230,"visibility":1918,"email_recipient_filter":1919,"created_at":1920,"updated_at":1866,"published_at":1867,"custom_excerpt":1905,"codeinjection_head":1921,"codeinjection_foot":8,"custom_template":8,"canonical_url":8,"tags":1922,"authors":1952,"primary_author":1958,"primary_tag":1959,"url":1960,"excerpt":1905,"reading_time":72,"access":230,"send_email_when_published":229,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"email_subject":8,"frontmatter":8,"dictionary":1879,"cta":1907,"plainTags":1869},"17add38f-53ec-459f-9a03-1d10adbd3d35","\u003Ch2 id=\"%F0%9F%91%8B-introduction\">👋 Introduction\u003C\u002Fh2>\u003Cp>Why did I even want to write this article in the first place? 😬 As a part of one of my tasks, I was supposed to handle long-running operations which use WebSockets for communication. \u003C\u002Fp>\u003Cp>The goal was to test the events that follow after finishing a long-running operation. We use STOMP over WebSocket (I will explain what it means later, don't worry). We also take advantage of CI on GitHub and Cypress framework to ensure that the product passes the automated tests before we release a new feature.\u003C\u002Fp>\u003Cp>I spent almost a day Googling and reading through GitHub threads for a good solution that would work for our case - unfortunately, without any success. 😤\u003C\u002Fp>\u003Cp>Basically, all of the methods I found use Socket.IO or a non-specified message format, and most of the solutions discussed on Stack Overflow and GitHub ended up not working for most of the users, which really surprised me.\u003C\u002Fp>\u003Cp>Do developers just not test the actions that happen after a WebSocket message is received? I do not certainly know the answer to this question, but it definitely motivated me to write this post. 🤠\u003C\u002Fp>\u003Ch2 id=\"%F0%9F%A4%94-what-is-stomp-over-websocket\">🤔 What is STOMP over WebSocket?\u003C\u002Fh2>\u003Cp>STOMP itself is a simple text-oriented messaging protocol. It defines an interoperable wire format so that any of the available STOMP clients can communicate with any STOMP message broker to provide easy and widespread messaging interoperability among languages and platforms.\u003C\u002Fp>\u003Cp>Raw WebSockets can be used without STOMP. STOMP is derived on top of WebSockets. STOMP just mentions a few specific ways in which the message frames are exchanged between the client and the server using WebSockets.\u003C\u002Fp>\u003Cp>Besides \u003Ca href=\"https:\u002F\u002Fstomp.github.io\u002Fstomp-specification-1.2.html\">STOMP\u003C\u002Fa>, there are various standardized protocols, e.g. \u003Ca href=\"https:\u002F\u002Fsocket.io\u002Fdocs\u002Fv4\u002Fsocket-io-protocol\u002F\">Socket.IO\u003C\u002Fa> or \u003Ca href=\"https:\u002F\u002Fwamp-proto.org\u002Fwamp_latest_ietf.html\">WAMP\u003C\u002Fa>. For the sake of maintainability, you should definitely use something standardized. 👈\u003C\u002Fp>\u003Cp>Why do we use STOMP, then? Well, both Broker and client are easy-to-implement. We use ActiveMQ as the broker, which works basically out of the box. Also, there are good TypeScript libraries that are easy to use and work well.\u003C\u002Fp>\u003Ch2 id=\"%F0%9F%9A%A9-localazy-alerts\">🚩 Localazy Alerts\u003C\u002Fh2>\u003Cp>Now, I’d like to give you a quick overview of alerts in Localazy to fully understand the problem. In the screenshot below, you can see a \u003Cem>Success\u003C\u002Fem> and a \u003Cem>Wait\u003C\u002Fem> alert type at the bottom. Apart from those, we have a few more types, not relevant at this moment.\u003C\u002Fp>\u003Cfigure class=\"kg-card kg-image-card kg-card-hascaption\">\u003Cimg src=\"https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png\" class=\"kg-image\" alt loading=\"lazy\" width=\"2000\" height=\"1415\" srcset=\"https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw600\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 600w, https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw1000\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 1000w, https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw1600\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 1600w, https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002Fsize\u002Fw2400\u002F2023\u002F03\u002FPasted-image-20230317104315-1.png 2400w\" sizes=\"(min-width: 720px) 720px\">\u003Cfigcaption>Alerts sample in Localazy\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>Obviously, not all of the alerts are controlled over WebSockets. Although, some of them are:\u003C\u002Fp>\u003Cul>\u003Cli>project publishing status,\u003C\u002Fli>\u003Cli>long-running operations,\u003C\u002Fli>\u003Cli>approving translations,\u003C\u002Fli>\u003Cli>sending translations back to review,\u003C\u002Fli>\u003Cli>MT \u003Ca href=\"https:\u002F\u002Fghost.localazy.com\u002Ffeatures\u002Fpre-translate\">pre-translate\u003C\u002Fa> keys.\u003C\u002Fli>\u003C\u002Ful>\u003Cp>“\u003Cstrong>Why are these tasks time-consuming and therefore cannot be processed immediately?\u003C\u002Fstrong>” you may ask. There are quite complex internal database processes in our backend, sometimes, we need to create physical files and make them ready for an eventual download. MT pre-translate is processed by a machine translation engine provider on the fly, which also takes time, especially when there are lots of keys sent.\u003C\u002Fp>\u003Cp>\u003Cstrong>These long-running operations can also be grouped\u003C\u002Fstrong> (for improved UX). What do I mean by that?\u003C\u002Fp>\u003Cp>An API sends these long-running operations per language (or file). Therefore triggering the pre-translate action for eight languages at the same time sends eight requests to the backend. Another example could be approving all translations in three files at once, which would send three requests.\u003C\u002Fp>\u003Cp>I believe the topic of long-running operations and their grouping is clear now. Let’s move on to the next part.\u003C\u002Fp>\u003Ch2 id=\"%F0%9F%8E%AF-our-goal\">🎯 Our goal\u003C\u002Fh2>\u003Cp>Now, I’d like to summarize the goal and give you some more important details. So, here's a bullet list:\u003C\u002Fp>\u003Cul>\u003Cli>include alerts testing in our E2E tests\u003C\u002Fli>\u003Cli>long-running operation API request returns the \u003Ccode>taskId\u003C\u002Fcode> of a task\u003C\u002Fli>\u003Cli>under this \u003Ccode>taskId\u003C\u002Fcode>, the request will be processed on the backend\u003C\u002Fli>\u003Cli>when the task finishes, a STOMP message will be sent to the client, including the \u003Ccode>taskId\u003C\u002Fcode> - this is the moment we know that the task is finished\u003C\u002Fli>\u003Cli>want to ensure that when the project is published\u003C\u002Fli>\u003Cli>need to make sure that long-running operations are processed properly\u003C\u002Fli>\u003Cli>\u003Cem>Wait\u003C\u002Fem> alert is initiated correctly\u003C\u002Fli>\u003Cli>\u003Cem>Wait\u003C\u002Fem> progress is calculated correctly\u003C\u002Fli>\u003Cli>when one of the tasks in the tasks group is done, update the percentage progress\u003C\u002Fli>\u003Cli>when all of the tasks in the group are finished, turn the \u003Cem>Wait\u003C\u002Fem> notification into a \u003Cem>Success\u003C\u002Fem> notification\u003C\u002Fli>\u003Cli>also, when tasks from other groups finish during the processing of multiple tasks groups together (which in terms of UI means having multiple \u003Cem>Wait\u003C\u002Fem> notifications at one time), it should impact only the group the task is assigned to\u003C\u002Fli>\u003Cli>we want to include those tests in the CI process on GitHub\u003C\u002Fli>\u003Cli>we have all of the data for our E2E tests mocked and prepared in fixtures; therefore, no real server endpoints are called\u003C\u002Fli>\u003C\u002Ful>\u003Ch2 id=\"%F0%9F%A7%AD-failed-attempts\">🧭 Failed attempts\u003C\u002Fh2>\u003Cp>Before we get to my solution, here's a list of some of the packages dedicated to solving our goal I’ve found and tried, such as:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcypress-websocket-plugin\">cypress-websocket-plugin\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcypress-mock-websocket-plugin\">cypress-mock-websocket-plugin\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Ffake-websocket\">fake-websocket\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmock-socket\">mock-socket\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmock-stomp-broker\">mock-stomp-broker\u003C\u002Fa>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>And as I’ve already mentioned in the Introduction, \u003Cstrong>none of the options above did work for me\u003C\u002Fstrong> for various reasons.\u003C\u002Fp>\u003Cp>That’s why I decided to solve it my way. \u003C\u002Fp>\u003Ch2 id=\"%F0%9F%92%8E-the-solution\">💎 The Solution\u003C\u002Fh2>\u003Ch3 id=\"own-stomp-broker\">Own STOMP Broker\u003C\u002Fh3>\u003Cp>I decided to code my own STOMP Broker - I don’t mean the whole implementation, of course, but only a part of communication that needs to be mocked I could use while writing tests. So what I needed to achieve was to inform the STOMP Client that a task with some \u003Ccode>taskId\u003C\u002Fcode> has been finished so the application can react to such an event.\u003C\u002Fp>\u003Cp>I used the \u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fstomp-broker-js\">stomp-broker-js\u003C\u002Fa> package for the implementation. It was simple to set up, the README example was mostly enough to get the inspiration for how it works. \u003C\u002Fp>\u003Cp>I needed to handle messages as the real STOMP Broker (that we use) does. Quick facts:\u003C\u002Fp>\u003Cul>\u003Cli>service is subscribed to a topic \u003Ccode>\u002Ftopic\u002Flocalazy.notifications\u003C\u002Fcode>,\u003C\u002Fli>\u003Cli>process the \u003Ccode>NOTIFY\u002FN\u002F21\u002F[some_id]\u003C\u002Fcode> message for \u003Cem>Project Published\u003C\u002Fem> event\u003C\u002Fli>\u003Cli>process the \u003Ccode>TASK\u002F[some_id]\u002F[finished_task_id]\u003C\u002Fcode> message for \u003Cem>Long-running operation\u003C\u002Fem> event\u003C\u002Fli>\u003C\u002Ful>\u003Cpre>\u003Ccode class=\"language-node\">const http = require(\"http\");\n\u002F\u002F eslint-disable-next-line import\u002Fno-extraneous-dependencies\nconst StompServer = require(\"stomp-broker-js\");\n\nconst server = http.createServer((request) =&gt; {\n  console.log(request.url);\n});\nconst stompServer = new StompServer({\n  server,\n  debug: console.log,\n  path: \"\u002Fapi\u002Fws\u002Fstomp\",\n  protocol: \"ws\",\n  \u002F\u002F v10.stomp', 'v11.stomp', 'v12.stomp'\n  heartbeat: [10000, 10000],\n});\nconsole.log(\" [*] Listening on 0.0.0.0:3322\");\nserver.listen(3322, \"localhost\");\n\nstompServer.subscribe(\"\u002Fe2e\u002Flong-running-operation.finished\", (msg, headers) =&gt; {\n  const topic = headers.destination;\n  console.log(`topic:${topic} messageType: ${typeof msg}`, msg, headers);\n  stompServer.send(\n    \"\u002Ftopic\u002Flocalazy.notifications\",\n    headers,\n    `TASK\u002Fsome_id\u002F${msg}`,\n  );\n});\n\nstompServer.subscribe(\"\u002Fe2e\u002Fproject.published\", (msg, headers) =&gt; {\n  const topic = headers.destination;\n  console.log(`topic:${topic} messageType: ${typeof msg}`, msg, headers);\n  stompServer.send(\n    \"\u002Ftopic\u002Flocalazy.notifications\",\n    headers,\n    \"NOTIFY\u002FN\u002F21\u002Fsome_id\",\n  );\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>As can be seen in the code snippet above, the broker is listening to two topics:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ccode>\u002Fe2e\u002Flong-running-operation.finished\u003C\u002Fcode>\u003C\u002Fli>\u003Cli>\u003Ccode>\u002Fe2e\u002Fproject.published\u003C\u002Fcode>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Why did I do that?\u003Cstrong> The mocked broker needs to work differently than a real backend-to-broker communication does\u003C\u002Fstrong>. The real backend would process the task, and then (when finished) it would inform the broker, which would send a message to the client.\u003C\u002Fp>\u003Cp>But in our test case, nothing is really being processed. That’s why we programmatically need to send a message to our subscribed topics from the E2E test code (and hence trigger the “\u003Cem>Hey, I’m the task with \u003Ccode>taskId\u003C\u002Fcode> and I’ve just finished processing\u003C\u002Fem>” procedure). And we need to do so after the long-running operation was initiated.\u003C\u002Fp>\u003Cp>That would then return the very same message as the real broker would do. Voilà!\u003C\u002Fp>\u003Ch3 id=\"ping-the-stomp-broker-from-cypress\">Ping the STOMP Broker from Cypress\u003C\u002Fh3>\u003Cp>Notice one of the earlier sentences:\u003C\u002Fp>\u003Cblockquote>… we programmatically need to send a message to our subscribed topics from the E2E test code…\u003C\u002Fblockquote>\u003Cp>How can we do that? How do we access the very same STOMP Client instance from the App in Cypress? The solution is quite simple and effective and does not make basically any mess in the application code.\u003C\u002Fp>\u003Cp>We’ll reuse a similar concept as described in the \u003Ca href=\"https:\u002F\u002Fdocs.cypress.io\u002Fapi\u002Fcommands\u002Fwindow#Start-tests-when-app-is-ready\">Cypress Docs\u003C\u002Fa>. That way, we can attach the client instance to the global \u003Ccode>window\u003C\u002Fcode> object, which can then be accessed in the test code (by calling a \u003Ccode>cy.window\u003C\u002Fcode> method - I’ll show you that later).\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">this.client = Stomp.client(process.env.VUE_APP_WSS_URL);\n\n\u002F**\n * To access the client from Cypress tests, attach it to the window object.\n *\u002F\nif ((window as any).Cypress) {\n\t(window as any).stompClient = this.client;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cblockquote>Another note: Make sure to pass the correct \u003Ccode>VUE_APP_WSS_URL\u003C\u002Fcode> \u003Ccode>env\u003C\u002Fcode> variable regarding the environment.\u003C\u002Fblockquote>\u003Cp>I.e. for the tests, you’d want to pass the one where our mocked STOMP Broker is running.\u003C\u002Fp>\u003Cp>Normally, you’d want to pass the testing\u002Fproduction address of the broker, depending on your setup.\u003C\u002Fp>\u003Ch3 id=\"write-the-tests\">Write the Tests\u003C\u002Fh3>\u003Cp>Writing the tests is just the icing on the cake if you know Cypress. If not, there are dozens of materials on the web - check that out! I’ll assume you do know how to work with Cypress.\u003C\u002Fp>\u003Cp>Therefore, I’ll just summarize what I had to deal with while writing WebSockets-related tests.\u003C\u002Fp>\u003Ch3 id=\"returning-a-different-response-for-the-same-request\">Returning a Different Response for the Same Request\u003C\u002Fh3>\u003Cp>As mentioned above, there’s a long-running operation request sent per every language (or file). It means that every request returns its own \u003Ccode>taskId\u003C\u002Fcode>. And when the task finishes, a STOMP message is sent containing that particular \u003Ccode>taskId\u003C\u002Fcode> - identifying that the task has been finished.\u003C\u002Fp>\u003Cp>Normally, to intercept a request in Cypress that always returns the same response, I’d do something like this:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">const body = {\n\tresult: true,\n\tid: 'my-task-identifier-xx'\n};\n\ncy.intercept(\"POST\", \"\u002Fapi\u002Fproject\u002F**\u002Fphrases\u002Fbatch\", { body }).as(\"phrasesBatchPOST\");\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>But to deal with the problem, Cypress offers a \u003Ccode>times\u003C\u002Fcode> property which can be sent in an object that’s passed to the \u003Ccode>cy.intercept\u003C\u002Fcode> method:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">const apiIdResult1 = {\n\tresult: true,\n\tid: 'my-task-identifier-01'\n};\n\nconst apiIdResult2 = {\n\tresult: true,\n\tid: 'my-task-identifier-02'\n};\n\ncy.intercept({ method: \"POST\", url: `\u002Fapi\u002Fproject\u002F${project.slug}\u002Fphrases\u002Fbatch`, times: 1 }, (req) =&gt; {\n      req.reply({ body: apiIdResult1 });\n    }).as(\"phrasesBatchPOST1\");\n\ncy.intercept({ method: \"POST\", url: `\u002Fapi\u002Fproject\u002F${project.slug}\u002Fphrases\u002Fbatch`, times: 1 }, (req) =&gt; {\n      req.reply({ body: apiIdResult2 });\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>This way, we can make sure that when we call \u003Ccode>cy.wait(\"phrasesBatchPOST1\")\u003C\u002Fcode>, the request would be intercepted only once.\u003C\u002Fp>\u003Cp>So to wait for two requests (e.g. handling of two languages) to be sent, we’d call:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">cy.wait(\"@phrasesBatchPOST1\");\ncy.wait(\"@phrasesBatchPOST2\");\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3 id=\"accessing-the-stomp-client-instance\">Accessing the STOMP Client Instance\u003C\u002Fh3>\u003Cp>Just to remind ourselves, we need to access the very same instance of the STOMP Client from Cypress as there is in the application. As I already demonstrated earlier, we’ve attached the client’s instance to the global \u003Ccode>window\u003C\u002Fcode> object.\u003C\u002Fp>\u003Cp>To access it in the test code, we have to invoke the \u003Ccode>cy.window\u003C\u002Fcode> method, like so:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-ts\">cy.window().then((win) =&gt; {\n      const { stompClient } = (win as any);\n      stompClient.send(\n\t      \"\u002Fe2e\u002Flong-running-operation.finished\",\n\t      {},\n\t      apiIdResult1.id\n\t  );\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>In the code snippet above, the \u003Ccode>cy.window\u003C\u002Fcode> returns a \u003Ccode>Promise\u003C\u002Fcode>. We then (\u003Ccode>.then\u003C\u002Fcode>) resolve the \u003Ccode>Promise\u003C\u002Fcode>. When it’s resolved, we access the \u003Ccode>stompClient\u003C\u002Fcode>.\u003C\u002Fp>\u003Cp>With the \u003Ccode>stompClient\u003C\u002Fcode> available, we can simply call its \u003Ccode>send\u003C\u002Fcode> method. Notice that we also sent the mocked \u003Ccode>apiIdResult1.id\u003C\u002Fcode> as a \u003Ccode>taskId\u003C\u002Fcode> as a part of the message. The mocked STOMP Broker immediately sends a \u003Ccode>MESSAGE\u003C\u002Fcode> containing the information that \u003Ccode>TASK\u003C\u002Fcode> with \u003Ccode>taskId\u003C\u002Fcode> equal to \u003Ccode>apiIdResult1.id\u003C\u002Fcode> finished.\u003C\u002Fp>\u003Cp>At this point, \u003Cstrong>the test would react as if it was a response from the real (non-mocked) STOMP Broker implementation\u003C\u002Fstrong> we use for Localazy.\u003C\u002Fp>\u003Cp>Now, all the non-usual Cypress (at least for me) stuff is explained.\u003C\u002Fp>\u003Ch3 id=\"update-the-ci-process\">Update the CI Process\u003C\u002Fh3>\u003Cp>As mentioned in the beginning, the goal is also to integrate the whole thing into the CI Process. What does that exactly mean in my case?\u003C\u002Fp>\u003Cp>Well, besides running the E2E testing process, we also need to start the mocked STOMP Broker. When the tests finish, we need to kill the STOMP Broker process respectively. All of that, using the GitHub Workflows.\u003C\u002Fp>\u003Cp>Our newly updated \u003Ccode>e2e.yml\u003C\u002Fcode> looks something like this:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-yml\"># ...\n# Run WS server has been added\n- name: Run WS server\n  run: npm run test:e2e:start-stomp\n- name: Run e2e tests\n  run: npm run test:e2e:ci\n# Stop WS server has been added\n- name: Stop WS server\n  run: npm run test:kill-stomp\n# ... \n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>We just simply added two new steps to the workflow. Let’s see what the scripts look like:\u003C\u002Fp>\u003Cpre>\u003Ccode class=\"language-json\">\u002F\u002F ...\n\"scripts\": {\n\t\"test:e2e:start-stomp\": \"forever start .\u002Ftests\u002Fsupport\u002Fmock-stomp-broker.js\",\n    \"test:kill-stomp\": \"forever stopall\",\n    \u002F\u002F ...\n}\n\u002F\u002F ...\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>We use the \u003Ccode>forever\u003C\u002Fcode> npm package. It offers an easy and intuitive way to run \u003Ccode>node\u003C\u002Fcode> process in the background and kill it on request when needed… Let’s push the code and run the tests!\u003C\u002Fp>\u003Cfigure class=\"kg-card kg-image-card kg-card-hascaption\">\u003Cimg src=\"https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F03\u002Falerts-ws-e2e.gif\" class=\"kg-image\" alt loading=\"lazy\" width=\"1638\" height=\"901\">\u003Cfigcaption>Alerts E2E Tests Run\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003Cstrong>All tests passed, and we’re all done!\u003C\u002Fstrong>\u003C\u002Fp>\u003Ch2 id=\"%E2%9C%94%EF%B8%8F-conclusion\">✔️ Conclusion\u003C\u002Fh2>\u003Cp>In this blog post, I demonstrated how to test STOMP over the WebSocket communication we use at Localazy for long-running operations. I also demonstrated a little sneak peek at the dev stack we use.\u003C\u002Fp>\u003Cp>We went through problems I faced during the implementation - and I gave you my solutions.\u003C\u002Fp>\u003Cp>Lastly, we updated the CI process and ran tests to ensure they passed!\u003C\u002Fp>","public","none","2023-03-17T12:29:10.000+01:00","https:\u002F\u002Fintercom.help\u002Flocalazy-test\u002Fen\u002Farticles\u002F7917172-test-alerts-using-stomp-over-websocket-in-cypress-e2e-tests",[1923,1926,1929,1934,1937,1942,1947],{"id":1924,"name":1871,"slug":1872,"description":1871,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1925},"60a37fc7cf7b6a0001d1f0fa","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fhowto\u002F",{"id":1927,"name":1874,"slug":1875,"description":1874,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1928},"60a37fc7cf7b6a0001d1f0ea","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fdevtips\u002F",{"id":1930,"name":1931,"slug":1932,"description":1912,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1933},"60a37fc7cf7b6a0001d1f11b","[CTA] Why developers love Localazy 💖","cta-13","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fcta-13\u002F",{"id":1935,"name":1877,"slug":1878,"description":1877,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1936},"60a37fc7cf7b6a0001d1f100","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fci\u002F",{"id":1938,"name":1939,"slug":1940,"description":8,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1941},"60fffb486f8ebe0001bd8ddd","[COMSHARE]","comshare","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fcomshare\u002F",{"id":1943,"name":1944,"slug":1945,"description":1883,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1946},"60a37fc7cf7b6a0001d1f155","[DICT] CI","term-56","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fterm-56\u002F",{"id":1948,"name":1949,"slug":1950,"description":1893,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1951},"60a37fc7cf7b6a0001d1f12a","[DICT] Machine translation (MT)","term-13","https:\u002F\u002Fghost.localazy.com\u002Ftag\u002Fterm-13\u002F",[1953],{"id":1860,"name":1861,"slug":1862,"profile_image":1863,"cover_image":8,"bio":8,"website":1954,"location":1955,"facebook":8,"twitter":1956,"meta_title":8,"meta_description":8,"url":1957},"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fdavid-vaclavek\u002F","Katowice, Poland","@dave_vaclavek","https:\u002F\u002Fghost.localazy.com\u002Fauthor\u002Fdavid-vaclavek\u002F",{"id":1860,"name":1861,"slug":1862,"profile_image":1863,"cover_image":8,"bio":8,"website":1954,"location":1955,"facebook":8,"twitter":1956,"meta_title":8,"meta_description":8,"url":1957},{"id":1924,"name":1871,"slug":1872,"description":1871,"feature_image":8,"visibility":1918,"og_image":8,"og_title":8,"og_description":8,"twitter_image":8,"twitter_title":8,"twitter_description":8,"meta_title":8,"meta_description":8,"codeinjection_head":8,"codeinjection_foot":8,"canonical_url":8,"accent_color":8,"url":1925},"https:\u002F\u002Fghost.localazy.com\u002Ftest-alerts-using-stomp-over-websocket-in-cypress-e2e-tests\u002F",[1962,1982,2001],{"id":1963,"owner":1964,"created_by":8,"sort":8,"title":1969,"slug":1970,"modified_on":53,"created_on":1971,"pinned":229,"badge":8,"priority":1824,"main_image":1972,"status":4,"tags":1973,"dictionary":1981,"reading_time":1835,"excerpt":-1,"og_title":53,"og_description":53,"og_image":53},"6372308e04709100019374c9",{"id":1965,"first_name":1966,"last_name":53,"slug":1967,"avatar":1968},"6061ffdd2a37af00016d413d","Daniel Charvát","daniel-charvat","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F12\u002Fdan-1.png","Figma in Localization: Figma as a Source of Truth","figma-series-figma-as-source-of-truth","2023-02-08T20:43:55.000+01:00","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F01\u002FFigma-Series-3.png",[1974,1976,1977,1978],{"id":1975,"created_on":1828,"status":4,"label":1138,"slug":1139,"on_index_page":230},6183,{"id":278,"created_on":1828,"status":4,"label":1871,"slug":1872,"on_index_page":229},{"id":278,"created_on":1828,"status":4,"label":1874,"slug":1875,"on_index_page":230},{"id":318,"created_on":1828,"status":4,"label":1979,"slug":1980,"on_index_page":229},"Design","design",[],{"id":1983,"owner":1984,"created_by":8,"sort":8,"title":1989,"slug":1990,"modified_on":53,"created_on":1991,"pinned":229,"badge":8,"priority":1824,"main_image":1992,"status":4,"tags":1993,"dictionary":2000,"reading_time":1835,"excerpt":-1,"og_title":53,"og_description":53,"og_image":53},"67cec8e634f1ce00011a908c",{"id":1985,"first_name":1986,"last_name":53,"slug":1987,"avatar":1988},"60a37d0bcf7b6a0001d1eca7","Localazy Team","localazy-team","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2022\u002F11\u002FLogo-Gradient.png","A beginner's guide to pluralization in software localization","pluralization-in-software-localization-beginners-guide","2025-07-21T08:47:00.000+02:00","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2025\u002F06\u002FPluralization-2.png",[1994,1996,1997],{"id":278,"created_on":1828,"status":4,"label":1995,"slug":1433,"on_index_page":229},"Plurals",{"id":278,"created_on":1828,"status":4,"label":1874,"slug":1875,"on_index_page":230},{"id":278,"created_on":1828,"status":4,"label":1998,"slug":1999,"on_index_page":229},"Guide","guide",[],{"id":2002,"owner":2003,"created_by":8,"sort":8,"title":2008,"slug":2009,"modified_on":53,"created_on":2010,"pinned":229,"badge":8,"priority":1824,"main_image":2011,"status":4,"tags":2012,"dictionary":2019,"reading_time":1835,"excerpt":-1,"og_title":53,"og_description":53,"og_image":53},"63dd1bf30470910001939f8b",{"id":2004,"first_name":2005,"last_name":53,"slug":2006,"avatar":2007},"61dc4e87df4bcb00010bd508","Mary Okosun","mary-okosun","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F12\u002Fokosun.png","The ultimate guide to Localazy API","the-ultimate-guide-to-localazy-api","2023-03-15T10:00:00.000+01:00","https:\u002F\u002Fghost.localazy.com\u002Fcontent\u002Fimages\u002F2023\u002F03\u002Fultimate-localazy-api-guide.png",[2013,2014,2017,2018],{"id":278,"created_on":1828,"status":4,"label":283,"slug":284,"on_index_page":229},{"id":278,"created_on":1828,"status":4,"label":2015,"slug":2016,"on_index_page":229},"Automated Localization","automated-localization",{"id":278,"created_on":1828,"status":4,"label":1871,"slug":1872,"on_index_page":229},{"id":278,"created_on":1828,"status":4,"label":1998,"slug":1999,"on_index_page":229},[],{"id":7,"sort":8,"created_on":2021,"name":2022,"cta_link":2023,"banner_image":2024},"2022-03-17T12:23:14.000Z","default","https:\u002F\u002Flocalazy.com\u002Ffeatures\u002Flocalazy-ai",{"id":2025},"72defd59-a21d-44b9-822c-4e183ca62b99"]