[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/messages/bg.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/messages.header.product.title": "Преводи, свързани с продукт",
  "admin/messages.header.sku.title": "Преводи, свързани с ИЕ",
  "admin/messages.header.brand.title": "Преводи, свързани с марки",
  "admin/messages.header.category.title": "Преводи, свързани с категории",
  "admin/messages.header.specification.title": "Преводи, свързани със спецификации",
  "admin/messages.navigation.label": "Превод",
  "admin/messages.navigation.product-label": "Продукт",
  "admin/messages.navigation.sku-label": "ИЕ",
  "admin/messages.navigation.category-label": "Категория",
  "admin/messages.navigation.brand-label": "Бранд",
  "admin/messages.navigation.specification-label": "Спецификация",
  "admin/messages.next": "Напред",
  "admin/messages.back": "Назад",
  "admin/messages.cancel": "Отказ",
  "admin/messages.retry": "Повторен опит",
  "admin/messages.done": "Готово",
  "admin/messages.catalog.download.instruction1": "1. Изтеглете данните, които искате да преведете, от каталога си",
  "admin/messages.catalog.download.instruction2": "2. Отворете експортирания файл в Excel или Numbers",
  "admin/messages.catalog.download.instruction3": "3. Преведете следните колони в електронната таблица:",
  "admin/messages.catalog.download.instruction4": "4. След превода: запишете файла и кликнете върху „Напред“, за да продължите",
  "admin/messages.catalog.export.catalog-exported": "Експортиране на каталог",
  "admin/messages.catalog.export.something-wrong": "Нещо се обърка, моля, опитайте отново",
  "admin/messages.catalog.export.export-began": "Каталогът в момента се експортира. Проверете имейла си след няколко минути",
  "admin/messages.catalog.export.exportCatalog": "Експортиране на каталог",
  "admin/messages.catalog.export.instruction1": "1. Експортирайте своя продуктов каталог към имейла си",
  "admin/messages.catalog.export.instruction2": "2. След експортиране: отворете имейла си и изтеглете приложения файл",
  "admin/messages.catalog.export.instruction3": "3. Отворете експортирания файл в Excel или Numbers",
  "admin/messages.catalog.export.instruction4": "4. Преведете следните колони в електронната таблица:",
  "admin/messages.catalog.export.instruction5": "5. След превода: запишете файла и кликнете върху „Напред“, за да продължите",
  "admin/messages.catalog.product.description": "Описание на продукта",
  "admin/messages.catalog.product.descriptionShort": "Кратко описание на продукта",
  "admin/messages.catalog.product.keywords": "Ключови думи",
  "admin/messages.catalog.product.metaTagDescription": "Описание на мета тагове",
  "admin/messages.catalog.product.name": "Наименовние",
  "admin/messages.catalog.product.titleTag": "Заглавие на таг",
  "admin/messages.catalog.sku.name": "Наименование",
  "admin/messages.catalog.sku.name-complete": "Пълно наименование",
  "admin/messages.catalog.brand.name": "Наименование",
  "admin/messages.catalog.brand.title": "Заглавие",
  "admin/messages.catalog.brand.metaTagDescription": "Описание на мета тагове",
  "admin/messages.catalog.category.name": "Наименование",
  "admin/messages.catalog.category.title": "Заглавие",
  "admin/messages.catalog.category.metaTagDescription": "Описание на мета тагове",
  "admin/messages.stepCounter": "Стъпка {current} от {total}",
  "admin/messages.messages-upload.target-lang": "Целеви език",
  "admin/messages.messages-upload.upload-label": "Качване",
  "admin/messages.messages-upload.pick-lang": "Избор на език",
  "admin/messages.messages-upload.pick-lang.en": "английски",
  "admin/messages.messages-upload.pick-lang.es": "испански",
  "admin/messages.messages-upload.pick-lang.pt": "португалски",
  "admin/messages.messages-upload.pick-lang.fr": "френски",
  "admin/messages.messages-upload.error-supported-file": "Файлът не се поддържа. Моля, използвайте единствено .csv и .xls файлове под 20 MB.",
  "admin/messages.messages-upload.error-id-column": "Колоната „_ProductId“ не е намерена в качения файл.",
  "admin/messages.messages-upload.error-no-translatable-field": "Не е намерено поле, което да се преведе.",
  "admin/messages.messages-upload.catalog-label": "Преведен каталог",
  "admin/messages.messages-progress.translate-progress": "{progress} от {total} продукта са преведени на {language} език",
  "admin/messages.messages-progress.translation-faileded": "{failed} неуспешни превода. Искате ли да опитате да ги преведете отново?",
  "admin/messages.messages-progress.translation-succeeded": "Преводът на {language} език е завършен успешно"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/messages/ro.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/messages.header.product.title": "Traduceri produs",
  "admin/messages.header.sku.title": "Traduceri SKU",
  "admin/messages.header.brand.title": "Traduceri marcă",
  "admin/messages.header.category.title": "Traduceri categorie",
  "admin/messages.header.specification.title": "Traduceri specificație",
  "admin/messages.navigation.label": "Traducere",
  "admin/messages.navigation.product-label": "Produs",
  "admin/messages.navigation.sku-label": "SKU",
  "admin/messages.navigation.category-label": "Categorie",
  "admin/messages.navigation.brand-label": "Marcă",
  "admin/messages.navigation.specification-label": "Specificație",
  "admin/messages.next": "Următorul",
  "admin/messages.back": "Întoarcere",
  "admin/messages.cancel": "Anulează",
  "admin/messages.retry": "Reîncearcă",
  "admin/messages.done": "Terminat",
  "admin/messages.catalog.download.instruction1": "1. Descarcă datele pe care dorești să le traduci din catalogul tău",
  "admin/messages.catalog.download.instruction2": "2. Deschide fișierul exportat în Excel sau Numbers",
  "admin/messages.catalog.download.instruction3": "3. Tradu coloanele următoare în foaia de calcul:",
  "admin/messages.catalog.download.instruction4": "4. După traducere: salvează fișierul și fă click pe Următorul pentru a continua",
  "admin/messages.catalog.export.catalog-exported": "Catalogul a fost exportat",
  "admin/messages.catalog.export.something-wrong": "A apărut o eroare, te rugăm să încerci din nou",
  "admin/messages.catalog.export.export-began": "Catalogul este în curs de exportare. Verifică-ți căsuța de e-mail în câteva momente",
  "admin/messages.catalog.export.exportCatalog": "Exportă catalogul",
  "admin/messages.catalog.export.instruction1": "1. Exportă catalogul tău de produse pe email",
  "admin/messages.catalog.export.instruction2": "2. După export: deschide-ți căsuța de e-mail și descarcă fișierul anexat",
  "admin/messages.catalog.export.instruction3": "3. Deschide fișierul exportat în Excel sau Numbers",
  "admin/messages.catalog.export.instruction4": "4. Tradu coloanele următoare în foaia de calcul:",
  "admin/messages.catalog.export.instruction5": "5. După traducere: salvează fișierul și fă clic pe Următorul pentru a continua",
  "admin/messages.catalog.product.description": "Descrierea produsului",
  "admin/messages.catalog.product.descriptionShort": "Descriere scurtă a produsului",
  "admin/messages.catalog.product.keywords": "Cuvinte cheie",
  "admin/messages.catalog.product.metaTagDescription": "Descriere etichetă meta",
  "admin/messages.catalog.product.name": "Nume",
  "admin/messages.catalog.product.titleTag": "Etichetă titlu",
  "admin/messages.catalog.sku.name": "Nume",
  "admin/messages.catalog.sku.name-complete": "Denumirea completă",
  "admin/messages.catalog.brand.name": "Nume",
  "admin/messages.catalog.brand.title": "Titlu",
  "admin/messages.catalog.brand.metaTagDescription": "Descriere etichetă meta",
  "admin/messages.catalog.category.name": "Nume",
  "admin/messages.catalog.category.title": "Titlu",
  "admin/messages.catalog.category.metaTagDescription": "Descriere etichetă meta",
  "admin/messages.stepCounter": "Pasul {current} din {total}",
  "admin/messages.messages-upload.target-lang": "Limba țintă",
  "admin/messages.messages-upload.upload-label": "Încarcă",
  "admin/messages.messages-upload.pick-lang": "Alege o limbă",
  "admin/messages.messages-upload.pick-lang.en": "Engleză",
  "admin/messages.messages-upload.pick-lang.es": "Spaniolă",
  "admin/messages.messages-upload.pick-lang.pt": "Portugheză",
  "admin/messages.messages-upload.pick-lang.fr": "Franceză",
  "admin/messages.messages-upload.error-supported-file": "Fișierul nu este acceptat. Te rugăm să incluzi numai fișiere .csv și .xls mai mici de 20 Mb.",
  "admin/messages.messages-upload.error-id-column": "Coloana „IdProdus” nu se găsește în fișierul încărcat.",
  "admin/messages.messages-upload.error-no-translatable-field": "Nu s-a găsit niciun fișier traductibil.",
  "admin/messages.messages-upload.catalog-label": "Catalog tradus",
  "admin/messages.messages-progress.translate-progress": "S-au tradus {progress} din {total} produse în {language}",
  "admin/messages.messages-progress.translation-faileded": "{failed} traduceri eșuate. Ați dori să le reîncercați?",
  "admin/messages.messages-progress.translation-succeeded": "Traducerea în {language} a fost finalizată cu succes"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/messages/context.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/messages.header.product.title": "",
  "admin/messages.header.sku.title": "",
  "admin/messages.header.brand.title": "",
  "admin/messages.header.category.title": "",
  "admin/messages.header.specification.title": "",
  "admin/messages.navigation.label": "",
  "admin/messages.navigation.product-label": "",
  "admin/messages.navigation.sku-label": "",
  "admin/messages.navigation.category-label": "",
  "admin/messages.navigation.brand-label": "",
  "admin/messages.navigation.specification-label": "",
  "admin/messages.next": "",
  "admin/messages.back": "",
  "admin/messages.cancel": "",
  "admin/messages.retry": "",
  "admin/messages.done": "",
  "admin/messages.catalog.download.instruction1": "",
  "admin/messages.catalog.download.instruction2": "",
  "admin/messages.catalog.download.instruction3": "",
  "admin/messages.catalog.download.instruction4": "",
  "admin/messages.catalog.export.catalog-exported": "",
  "admin/messages.catalog.export.something-wrong": "",
  "admin/messages.catalog.export.export-began": "",
  "admin/messages.catalog.export.exportCatalog": "",
  "admin/messages.catalog.export.instruction1": "",
  "admin/messages.catalog.export.instruction2": "",
  "admin/messages.catalog.export.instruction3": "",
  "admin/messages.catalog.export.instruction4": "",
  "admin/messages.catalog.export.instruction5": "",
  "admin/messages.catalog.product.description": "",
  "admin/messages.catalog.product.descriptionShort": "",
  "admin/messages.catalog.product.keywords": "",
  "admin/messages.catalog.product.metaTagDescription": "",
  "admin/messages.catalog.product.name": "",
  "admin/messages.catalog.product.titleTag": "",
  "admin/messages.catalog.sku.name": "",
  "admin/messages.catalog.sku.name-complete": "",
  "admin/messages.catalog.brand.name": "",
  "admin/messages.catalog.brand.title": "",
  "admin/messages.catalog.brand.metaTagDescription": "",
  "admin/messages.catalog.category.name": "",
  "admin/messages.catalog.category.title": "",
  "admin/messages.catalog.category.metaTagDescription": "",
  "admin/messages.stepCounter": "",
  "admin/messages.messages-upload.target-lang": "",
  "admin/messages.messages-upload.upload-label": "",
  "admin/messages.messages-upload.pick-lang": "",
  "admin/messages.messages-upload.pick-lang.en": "",
  "admin/messages.messages-upload.pick-lang.es": "",
  "admin/messages.messages-upload.pick-lang.pt": "",
  "admin/messages.messages-upload.pick-lang.fr": "",
  "admin/messages.messages-upload.error-supported-file": "",
  "admin/messages.messages-upload.error-id-column": "",
  "admin/messages.messages-upload.error-no-translatable-field": "",
  "admin/messages.messages-upload.catalog-label": "",
  "admin/messages.messages-progress.translate-progress": "",
  "admin/messages.messages-progress.translation-faileded": "",
  "admin/messages.messages-progress.translation-succeeded": ""
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/messages/ko.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/messages.header.product.title": "제품 번역",
  "admin/messages.header.sku.title": "SKU 번역",
  "admin/messages.header.brand.title": "브랜드 번역",
  "admin/messages.header.category.title": "카테고리 번역",
  "admin/messages.header.specification.title": "사양 번역",
  "admin/messages.navigation.label": "번역",
  "admin/messages.navigation.product-label": "제품",
  "admin/messages.navigation.sku-label": "SKU",
  "admin/messages.navigation.category-label": "카테고리",
  "admin/messages.navigation.brand-label": "브랜드",
  "admin/messages.navigation.specification-label": "사양",
  "admin/messages.next": "다음",
  "admin/messages.back": "뒤로 가기",
  "admin/messages.cancel": "취소",
  "admin/messages.retry": "재시도",
  "admin/messages.done": "끝",
  "admin/messages.catalog.download.instruction1": "1. 카탈로그에서 번역할 데이터를 다운로드합니다",
  "admin/messages.catalog.download.instruction2": "2. Excel 또는 Numbers에서 내보낸 파일을 엽니다",
  "admin/messages.catalog.download.instruction3": "3. 스프레드시트에서 다음 열을 번역합니다.",
  "admin/messages.catalog.download.instruction4": "4. 번역 후: 파일을 저장하고 다음을 클릭하여 계속합니다",
  "admin/messages.catalog.export.catalog-exported": "내보낸 카탈로그",
  "admin/messages.catalog.export.something-wrong": "문제가 발생했습니다. 나중에 다시 시도하십시오",
  "admin/messages.catalog.export.export-began": "카탈로그를 내보내고 있습니다. 잠시 후 이메일을 확인하세요",
  "admin/messages.catalog.export.exportCatalog": "카탈로그 내보내기",
  "admin/messages.catalog.export.instruction1": "1. 제품 카탈로그를 이메일로 내보냅니다",
  "admin/messages.catalog.export.instruction2": "2. 내보내기 후: 이메일을 열고 첨부 파일을 다운로드합니다",
  "admin/messages.catalog.export.instruction3": "3. Excel 또는 Numbers에서 내보낸 파일을 엽니다",
  "admin/messages.catalog.export.instruction4": "4. 스프레드시트에서 다음 열을 번역합니다.",
  "admin/messages.catalog.export.instruction5": "5. 번역 후: 파일을 저장하고 다음을 클릭하여 계속합니다",
  "admin/messages.catalog.product.description": "제품 설명",
  "admin/messages.catalog.product.descriptionShort": "짧은 제품 설명",
  "admin/messages.catalog.product.keywords": "키워드",
  "admin/messages.catalog.product.metaTagDescription": "메타 태그 설명",
  "admin/messages.catalog.product.name": "이름",
  "admin/messages.catalog.product.titleTag": "제목 태그",
  "admin/messages.catalog.sku.name": "이름",
  "admin/messages.catalog.sku.name-complete": "전체 이름",
  "admin/messages.catalog.brand.name": "이름",
  "admin/messages.catalog.brand.title": "제목",
  "admin/messages.catalog.brand.metaTagDescription": "메타 태그 설명",
  "admin/messages.catalog.category.name": "이름",
  "admin/messages.catalog.category.title": "제목",
  "admin/messages.catalog.category.metaTagDescription": "메타 태그 설명",
  "admin/messages.stepCounter": "{total}단계 중 {current}단계",
  "admin/messages.messages-upload.target-lang": "도착어",
  "admin/messages.messages-upload.upload-label": "업로드",
  "admin/messages.messages-upload.pick-lang": "언어 선택",
  "admin/messages.messages-upload.pick-lang.en": "영어",
  "admin/messages.messages-upload.pick-lang.es": "스페인어",
  "admin/messages.messages-upload.pick-lang.pt": "포르투갈어",
  "admin/messages.messages-upload.pick-lang.fr": "프랑스어",
  "admin/messages.messages-upload.error-supported-file": "지원되지 않는 파일입니다. 20MB 미만의 .csv 및 .xls만 포함하세요.",
  "admin/messages.messages-upload.error-id-column": "업로드한 파일에서 \"_ProductId\" 열을 찾을 수 없습니다.",
  "admin/messages.messages-upload.error-no-translatable-field": "번역 가능한 필드를 찾을 수 없습니다.",
  "admin/messages.messages-upload.catalog-label": "번역된 카탈로그",
  "admin/messages.messages-progress.translate-progress": "{total}개 제품 중 {progress}개가 {language}로 번역됨",
  "admin/messages.messages-progress.translation-faileded": "{failed} 번역에 실패했습니다. 다시 시도하시겠습니까?",
  "admin/messages.messages-progress.translation-succeeded": "{language} 번역이 성공적으로 완료되었습니다"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/messages/th.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/messages.header.product.title": "การแปลผลิตภัณฑ์",
  "admin/messages.header.sku.title": "การแปล SKU",
  "admin/messages.header.brand.title": "การแปลแบรนด์",
  "admin/messages.header.category.title": "การแปลหมวดหมู่",
  "admin/messages.header.specification.title": "การแปลข้อมูลจำเพาะ",
  "admin/messages.navigation.label": "การแปล",
  "admin/messages.navigation.product-label": "ผลิตภัณฑ์",
  "admin/messages.navigation.sku-label": "SKU",
  "admin/messages.navigation.category-label": "หมวดหมู่",
  "admin/messages.navigation.brand-label": "แบรนด์",
  "admin/messages.navigation.specification-label": "ข้อมูลจำเพาะ",
  "admin/messages.next": "ถัดไป",
  "admin/messages.back": "กลับ",
  "admin/messages.cancel": "ยกเลิก",
  "admin/messages.retry": "ลองใหม่",
  "admin/messages.done": "เสร็จสิ้น",
  "admin/messages.catalog.download.instruction1": "1. ดาวน์โหลดข้อมูลจากแคตาล็อกของคุณที่ต้องการแปล",
  "admin/messages.catalog.download.instruction2": "2. เปิดไฟล์ที่ส่งออกใน Excel หรือ Numbers",
  "admin/messages.catalog.download.instruction3": "3. แปลคอลัมน์ค่อไปนี้ในสเปรดชีต",
  "admin/messages.catalog.download.instruction4": "4. หลังการแปล ให้บันทึกไฟล์และคลิก ต่อไป เพื่อดำเนินการต่อ",
  "admin/messages.catalog.export.catalog-exported": "ส่งออกแคตาล็อกแล้ว",
  "admin/messages.catalog.export.something-wrong": "มีบางอย่างผิดปกติ โปรดลองอีกครั้ง",
  "admin/messages.catalog.export.export-began": "กำลังส่งออกแคตาล็อก ตรวจดูอีเมลของคุณในอีกสักครู่",
  "admin/messages.catalog.export.exportCatalog": "ส่งออกแคตาล็อก",
  "admin/messages.catalog.export.instruction1": "1. ส่งออกแคตาล็อกผลิตภัณฑ์ไปยังอีเมลของคุณ",
  "admin/messages.catalog.export.instruction2": "2. หลังส่งออก: เปิดอีเมลของคุณ และดาวน์โหลดไฟล์แนบ",
  "admin/messages.catalog.export.instruction3": "3. เปิดไฟล์ที่ส่งออกใน Excel หรือ Numbers",
  "admin/messages.catalog.export.instruction4": "4. แปลคอลัมน์ต่อไปนี้ในสเปรดชีต",
  "admin/messages.catalog.export.instruction5": "5. หลังการแปล ให้บันทึกไฟล์และคลิก ต่อไป เพื่อดำเนินการต่อ",
  "admin/messages.catalog.product.description": "คำอธิบายผลิตภัณฑ์",
  "admin/messages.catalog.product.descriptionShort": "คำอธิบายย่อผลิตภัณฑ์",
  "admin/messages.catalog.product.keywords": "คำสำคัญ",
  "admin/messages.catalog.product.metaTagDescription": "คำอธิบายแท็ก Meta",
  "admin/messages.catalog.product.name": "ชื่อ",
  "admin/messages.catalog.product.titleTag": "แท็กคำเรียก",
  "admin/messages.catalog.sku.name": "ชื่อ",
  "admin/messages.catalog.sku.name-complete": "ชื่อเต็ม",
  "admin/messages.catalog.brand.name": "ชื่อ",
  "admin/messages.catalog.brand.title": "คำเรียก",
  "admin/messages.catalog.brand.metaTagDescription": "คำอธิบายแท็ก Meta",
  "admin/messages.catalog.category.name": "ชื่อ",
  "admin/messages.catalog.category.title": "คำเรียก",
  "admin/messages.catalog.category.metaTagDescription": "คำอธิบายแท็ก Meta",
  "admin/messages.stepCounter": "ขั้นตอน {current} จาก {total}",
  "admin/messages.messages-upload.target-lang": "ภาษาปลายทาง",
  "admin/messages.messages-upload.upload-label": "อัปโหลด",
  "admin/messages.messages-upload.pick-lang": "เลือกภาษา",
  "admin/messages.messages-upload.pick-lang.en": "อังกฤษ",
  "admin/messages.messages-upload.pick-lang.es": "สเปน",
  "admin/messages.messages-upload.pick-lang.pt": "โปรตุเกส",
  "admin/messages.messages-upload.pick-lang.fr": "ฝรั่งเศส",
  "admin/messages.messages-upload.error-supported-file": "ไม่รองรับไฟล์ชนิดนี้ โปรดรวมเฉพาะไฟล์ .csv และ .xls ที่ต่ำกว่า 20MB",
  "admin/messages.messages-upload.error-id-column": "ไม่พบคอลัมน์ \"_ProductId\" ในไฟล์ที่อัปโหลด",
  "admin/messages.messages-upload.error-no-translatable-field": "ไม่พบฟิลด์ที่แปลได้",
  "admin/messages.messages-upload.catalog-label": "แคตาล็อกที่แปลแล้ว",
  "admin/messages.messages-progress.translate-progress": "แปลแล้ว {progress} จากทั้งหมด {total} ผลิตภัณฑ์ไปยังภาษา {language}",
  "admin/messages.messages-progress.translation-faileded": "{failed} การแปลไม่สำเร็จ คุณต้องการลองอีกครั้งหรือไม่",
  "admin/messages.messages-progress.translation-succeeded": "การแปลในภาษา {language} เสร็จเรียบร้อยแล้ว"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/messages/es.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/messages.header.product.title": "Traducciones de producto",
  "admin/messages.header.sku.title": "Traducciones de SKU",
  "admin/messages.header.brand.title": "Traducciones de marca",
  "admin/messages.header.category.title": "Traducciones de categoría",
  "admin/messages.header.specification.title": "Traducciones de especificación",
  "admin/messages.navigation.label": "Traducción",
  "admin/messages.navigation.product-label": "Producto",
  "admin/messages.navigation.sku-label": "SKU",
  "admin/messages.navigation.category-label": "Categoría",
  "admin/messages.navigation.brand-label": "Marca",
  "admin/messages.navigation.specification-label": "Especificación",
  "admin/messages.next": "Siguiente",
  "admin/messages.back": "Atrás",
  "admin/messages.cancel": "Cancelar",
  "admin/messages.retry": "Intentar de nuevo",
  "admin/messages.done": "Listo",
  "admin/messages.catalog.download.instruction1": "1. Descarga los datos de tu catálogo que deseas traducir",
  "admin/messages.catalog.download.instruction2": "2. Abre el archivo exportado en Excel o Numbers",
  "admin/messages.catalog.download.instruction3": "3. Traduce las siguientes columnas en la plantilla:",
  "admin/messages.catalog.download.instruction4": "4. Después de traducir, guarda el archivo y haz clic en \"Siguiente\" para continuar",
  "admin/messages.catalog.export.catalog-exported": "Catálogo exportado",
  "admin/messages.catalog.export.something-wrong": "Se produjo un error. Por favor, vuelve a intentarlo",
  "admin/messages.catalog.export.export-began": "Se está exportando el catálogo. Revisa tu email en unos momentos",
  "admin/messages.catalog.export.exportCatalog": "Exportar catálogo",
  "admin/messages.catalog.export.instruction1": "1. Exporta tu catálogo de productos a tu email",
  "admin/messages.catalog.export.instruction2": "2. Después de exportar, abre tu email y descarga el archivo adjunto",
  "admin/messages.catalog.export.instruction3": "3. Abre el archivo exportado en Excel o Numbers",
  "admin/messages.catalog.export.instruction4": "4. Traduce las siguientes columnas en la plantilla:",
  "admin/messages.catalog.export.instruction5": "5. Después de traducir, guarda el archivo y haz clic en \"Siguiente\" para continuar",
  "admin/messages.catalog.product.description": "Descripción del producto",
  "admin/messages.catalog.product.descriptionShort": "Breve descripción del producto",
  "admin/messages.catalog.product.keywords": "Palabras clave",
  "admin/messages.catalog.product.metaTagDescription": "Descripción de la meta tag",
  "admin/messages.catalog.product.name": "Nombre",
  "admin/messages.catalog.product.titleTag": "Tag del título",
  "admin/messages.catalog.sku.name": "Nombre",
  "admin/messages.catalog.sku.name-complete": "Nombre completo",
  "admin/messages.catalog.brand.name": "Nombre",
  "admin/messages.catalog.brand.title": "Título",
  "admin/messages.catalog.brand.metaTagDescription": "Descripción de la meta tag",
  "admin/messages.catalog.category.name": "Nombre",
  "admin/messages.catalog.category.title": "Título",
  "admin/messages.catalog.category.metaTagDescription": "Descripción de la meta tag",
  "admin/messages.stepCounter": "Paso {current} de {total}",
  "admin/messages.messages-upload.target-lang": "Lengua meta",
  "admin/messages.messages-upload.upload-label": "Cargar",
  "admin/messages.messages-upload.pick-lang": "Selecciona un idioma",
  "admin/messages.messages-upload.pick-lang.en": "Inglés",
  "admin/messages.messages-upload.pick-lang.es": "Español",
  "admin/messages.messages-upload.pick-lang.pt": "Portugués",
  "admin/messages.messages-upload.pick-lang.fr": "Francés",
  "admin/messages.messages-upload.error-supported-file": "Archivo incompatible. Por favor, solo incluye .csv y .xls de menos de 20 MB.",
  "admin/messages.messages-upload.error-id-column": "No se encontró la columna \"_ProductId\" en el archivo cargado.",
  "admin/messages.messages-upload.error-no-translatable-field": "No se encontró ningún campo traducible.",
  "admin/messages.messages-upload.catalog-label": "Catálogo traducido",
  "admin/messages.messages-progress.translate-progress": "{progress} de {total} productos se han traducido al {language}",
  "admin/messages.messages-progress.translation-faileded": "{failed} traducciones fallidas. ¿Deseas volver a intentarlo?",
  "admin/messages.messages-progress.translation-succeeded": "Traducción al {language} completada con éxito"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/admin/navigation.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "section": "storeSetup",
  "titleId": "admin/messages.navigation.label",
  "subSectionItems": [
    {
      "labelId": "admin/messages.navigation.product-label",
      "path": "/admin/messages/product"
    },
    {
      "labelId": "admin/messages.navigation.sku-label",
      "path": "/admin/messages/sku"
    },
    {
      "labelId": "admin/messages.navigation.category-label",
      "path": "/admin/messages/category"
    },
    {
      "labelId": "admin/messages.navigation.brand-label",
      "path": "/admin/messages/brand"
    },
    {
      "labelId": "admin/messages.navigation.specification-label",
      "path": "/admin/messages/specification"
    }
  ]
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/admin/routes.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin.app.messages-product": {
      "component": "ProductMessages",
      "path": "/admin/app/messages/product"
  },
  "admin.app.messages-sku": {
      "component": "SKUMessages",
      "path": "/admin/app/messages/sku"
  },
  "admin.app.messages-category": {
      "component": "CategoryMessages",
      "path": "/admin/app/messages/category"
  },
  "admin.app.messages-brand": {
      "component": "BrandMessages",
      "path": "/admin/app/messages/brand"
  },
  "admin.app.messages-specification": {
      "component": "SpecificationMessages",
      "path": "/admin/app/messages/specification"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/docs/README.md from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Admin Messages

A tool for translating messages on the Store Admin.
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/graphql/schema.graphql from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```graphql
input MessageTranslation {
  id: String!
  content: String
  description: String
}

input MessagesFromProvider {
  provider: String!
  messages: [MessageTranslation]
}

# Apparently you can only add a mutation if you have a query
type Query {
  MOCK_DO_NOT_CALL: String
}

type FailedTranslation {
  provider: String!
}

enum Entity {
  product
  sku
  brand
  category
  specification
}

type Mutation {
  addTranslations(translations: [MessagesFromProvider]!, entity: Entity!, language: String!): [FailedTranslation]
  exportProductCatalog: Boolean
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/service.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 5,
  "timeout": 1,
  "minReplicas": 4,
  "maxReplicas": 8,
  "routes": {
    "brands": {
      "path": "/_v/private/vtex.admin-messages/v1/brands",
      "public": true,
      "smartcache": true
    },
    "categories": {
      "path": "/_v/private/vtex.admin-messages/v1/categories",
      "public": true,
      "smartcache": true
    },
    "specifications": {
      "path": "/_v/private/vtex.admin-messages/v1/specifications",
      "public": true,
      "smartcache": true
    },
    "specificationsTextValues": {
      "path": "/_v/private/vtex.admin-messages/v1/specifications/text-values",
      "public": true,
      "smartcache": true
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/package.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "bluebird": "^3.5.5",
    "csv-parse": "^4.4.3",
    "ramda": "^0.26.1",
    "xlsx": "^0.14.3"
  },
  "devDependencies": {
    "@types/bluebird": "^3.5.27",
    "@types/csv-parse": "^1.2.2",
    "@types/node": "^10.12.17",
    "@types/ramda": "types/npm-ramda#dist",
    "@vtex/api": "^3.71.1",
    "tslint": "^5.12.0",
    "tslint-config-vtex": "^2.1.0",
    "typescript": "3.7.3"
  },
  "scripts": {
    "lint": "tsc --noEmit && tslint -c tslint.json './**/*.ts'"
  },
  "version": "0.8.1"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/index.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Service, ServiceContext } from '@vtex/api'
import { Clients } from './clients'
import routes from './handlers'
import addTranslations from './resolvers/addTranslations'
import exportProductCatalog from './resolvers/exportProductCatalog'

const TRANSLATION_CONCURRENCY = 5
const TRANSLATION_RETRIES = 3

const CATALOG_RETRIES = 3
const CATALOG_CONCURRENCY = 50
const CATALOG_TIMEOUT_MS = 5000

const SMALL_TIMEOUT_MS = 500
const HUGE_TIMEOUT_MS = 5000

declare global {
  type Context = ServiceContext<Clients>
}

export const clientOptions = {
  admin: {
    timeout: HUGE_TIMEOUT_MS,
  },
  catalog: {
    concurrency: CATALOG_CONCURRENCY,
    retries: CATALOG_RETRIES,
    timeout: CATALOG_TIMEOUT_MS,
  },
  default: {
    verbose: false,
  },
  messagesGraphQL: {
    concurrency: TRANSLATION_CONCURRENCY,
    retries: TRANSLATION_RETRIES,
    timeout: SMALL_TIMEOUT_MS,
  },
}

export default new Service<Clients>({
  clients: {
    implementation: Clients,
    options: clientOptions,
  },
  graphql: {
    resolvers: {
      Mutation: {
        addTranslations,
        exportProductCatalog,
      },
    },
  },
  routes,
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/ProductMessages.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import AdminMessagesWrapper from './components/AdminMessagesWrapper'

const ProductMessages: FC = () => {
  return <AdminMessagesWrapper entity="product" />
}

export default ProductMessages

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/BrandMessages.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import AdminMessagesWrapper from './components/AdminMessagesWrapper'

const BrandMessages: FC = () => {
  return <AdminMessagesWrapper entity="brand" />
}

export default BrandMessages

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/SKUMessages.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import AdminMessagesWrapper from './components/AdminMessagesWrapper'

const SKUMesssages: FC = () => {
  return <AdminMessagesWrapper entity="sku" />
}

export default SKUMesssages

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/package.json from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "vtex.admin-example",
  "version": "0.8.1",
  "scripts": {
    "lint": "tsc --noEmit --pretty && tslint -c tslint.json './**/*.ts'",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "devDependencies": {
    "@types/graphql": "^14.2.2",
    "@types/node": "^11.12.1",
    "@types/ramda": "^0.26.12",
    "@types/react": "^16.8.10",
    "@types/react-dropzone": "^4.2.2",
    "@types/react-intl": "^2.3.17",
    "apollo-client": "^2.6.3",
    "graphql": "^14.0.2",
    "graphql-tag": "^2.10.1",
    "react": "^16.8.6",
    "react-apollo": "^2.5.8",
    "react-dom": "^16.8.6",
    "react-intl": "^2.7.2",
    "tslint": "^5.14.0",
    "tslint-config-vtex": "^2.1.0",
    "types": "^0.1.1",
    "typescript": "3.7.3"
  },
  "dependencies": {
    "react-dropzone": "^10.1.5",
    "xlsx": "^0.14.3"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/styles.global.css from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```css
html,
body,
#render-container,
#render-provider,
.render-container,
.render-provider {
  height: 100%;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/SpecificationMessages.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import AdminMessagesWrapper from './components/AdminMessagesWrapper'

const SpecificationMessages: FC = () => {
  return <AdminMessagesWrapper entity="specification" />
}

export default SpecificationMessages

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/CategoryMessages.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import AdminMessagesWrapper from './components/AdminMessagesWrapper'

const CategoryMessages: FC = () => {
  return <AdminMessagesWrapper entity="category" />
}

export default CategoryMessages

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/admin.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ExternalClient, InstanceOptions, IOContext } from '@vtex/api'

export class Admin extends ExternalClient {
  public constructor(context: IOContext, options?: InstanceOptions) {
    super(
      `https://${context.account}.vtexcommercestable.com.br/admin/API/`,
      context,
      {
        ...options,
        headers: {
          ...(options && options.headers),
          ...(context.adminUserAuthToken
            ? { VtexIdclientAutCookie: context.adminUserAuthToken }
            : null),
        },
      }
    )
  }

  public exportCatalogToEmail = (email: string) =>
    this.http.post(`StockKeepingUnitReport/ExportToEmail/`, {
      Email: email,
      Filters: {
        StoreId: 0,
      },
      Locale: 'en-US',
    })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/index.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { IOClients } from '@vtex/api'

import { Admin } from './admin'
import { Catalog } from './catalog'
import { CatalogGraphQL } from './catalogGraphQL'

export class Clients extends IOClients {
  get admin(): Admin {
    return this.getOrSet('admin', Admin)
  }

  get catalog(): Catalog {
    return this.getOrSet('catalog', Catalog)
  }

  get catalogGraphQL(): CatalogGraphQL {
    return this.getOrSet('catalogGraphQL', CatalogGraphQL)
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/catalog.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ExternalClient, InstanceOptions, IOContext } from '@vtex/api'

/** Catalog API
 * Docs: https://documenter.getpostman.com/view/845/catalogsystem-102/Hs44
 */
export class Catalog extends ExternalClient {
  public constructor(context: IOContext, options?: InstanceOptions) {
    super(
      `http://${context.account}.vtexcommercestable.com.br/api/catalog_system/`,
      context,
      {
        ...options,
        headers: {
          ...(options && options.headers),
          ...(context.adminUserAuthToken
            ? { VtexIdclientAutCookie: context.adminUserAuthToken }
            : null),
        },
      }
    )
  }

  public exportBrands = (): Promise<Brand[]> =>
    this.http.get('pvt/brand/list')

  public exportCategories = (): Promise<Category[]> =>
    this.http.get('pub/category/listAll')

  public getSpecificationsByCategory = (id: number): Promise<Specification[]> =>
    this.http.get(`pub/specification/field/listByCategoryId/${id}`)

  public getSpecificationsTreeByCategory = (id: number): Promise<Specification[]> =>
    this.http.get(`pub/specification/field/listTreeByCategoryId/${id}`)

  public getSpecificationValues = (id: number): Promise<SpecificationValue[]> =>
    this.http.get(`pub/specification/fieldvalue/${id}`)

  public getSpecificationFields = (id: number): Promise<SpecificationFields> =>
    this.http.get(`pub/specification/fieldGet/${id}`)

  public getProductAndSkuByCategory = (categoryId: number, from: number, to: number): Promise<ProductAndSkuByCategoryResult> =>
    this.http.get(`pvt/products/GetProductAndSkuIds?categoryId=${categoryId}&_from=${from}&_to=${to}`)

  public getProductSpecification = (id: string): Promise<ProductSpecification[]> =>
    this.http.get(`pvt/products/${id}/specification`)

}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/category.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { pick } from 'ramda'
import { createXLSX, jsonToXLSXFields } from './xlsx'

const jsonToXLSXMap: Record<keyof CategoryTranslatables, string> = {
  MetaTagDescription: '_MetaTagDescription',
  Title: '_Title',
  id: '_CategoryId',
  name: '_Name',
}

const getBrandTranslatableFields = pick(Object.keys(jsonToXLSXMap) as Array<
  keyof CategoryTranslatables
>)

export async function getCategoryXLSX(ctx: Context) {
  const { clients: { catalog } } = ctx
  const categories = await catalog.exportCategories()
  const categoriesTranslatableFields = categories.map(getBrandTranslatableFields)
  const categoriesXLSX = categoriesTranslatableFields.map(category => jsonToXLSXFields(category, jsonToXLSXMap))
  return createXLSX({ Categories: categoriesXLSX })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/brand.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { createXLSX, jsonToXLSXFields } from './xlsx'

const jsonToXLSXMap: Record<keyof BrandTranslatables, string> = {
  id: '_BrandId',
  metaTagDescription: '_MetaTagDescription',
  name: '_Name',
  title: '_Title',
}

export async function getBrandXLSX(ctx: Context) {
  const { clients: { catalog } } = ctx
  const brands = await catalog.exportBrands()

  return createXLSX({ Brands: brands.map(brand => jsonToXLSXFields(brand as any, jsonToXLSXMap)) })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/xlsx.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import xlsx from 'xlsx'

export function createXLSX(sheets: Record<string, Array<unknown>>): Buffer {
  const book = xlsx.utils.book_new()

  Object.entries(sheets).forEach(([sheetName, data]) => {
    const sheet = xlsx.utils.json_to_sheet(data)
    xlsx.utils.book_append_sheet(book, sheet, sheetName)
  })

  return xlsx.write(book, { type: 'buffer', bookType: 'xlsx' })
}

export function jsonToXLSXFields <T extends Record<string, unknown>>(data: T, jsonToXLSXMap: Record<string, string>) {
  return Object.entries(jsonToXLSXMap).reduce(
    (result, [jsonKey, xlsxKey]) => {
      result[xlsxKey] = data[jsonKey]
      return result
    },
    {} as Record<string, unknown>
  )
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/utils.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
export function range(from: number, to: number, step: number = 1): number[] {
  const values: number[] = []
  for (let value = from; value <= to; value += step) {
    values.concat(from)
  }
  return values
}

/*
FieldTypeName by FieldTypeID:
1 - Texto
2 - Texto Grande
4 - Número
5 - Combo
6 - Radio
7 - CheckBox
8 - Texto Indexado
9 - Texto Grande Indexado

Only "Texto", "Texto Grande", "Texto Indexado" and "Texto Grande Indexado" are translated on a product level.
The other FieldTypes are stored as refereces and their values are stored as SpecificationField.
*/
export function isProductSpecification({ FieldTypeId }: SpecificationFields) {
  return [1, 2, 8, 9].findIndex(id => FieldTypeId === id) !== -1
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/productSpecs.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { chain, uniq, unnest } from 'ramda'
import { Catalog } from '../clients/catalog'
import { getSpecifications } from './categorySpecs'
import { isProductSpecification, range } from './utils'
import { createXLSX, jsonToXLSXFields } from './xlsx'

// Limit of the API
const BATCH_SIZE = 51

const specificationToXLSXMap: Record<keyof ProductSpecification, string> = {
  Id: '_SpecificationId',
  Name: '_SpecificationName',
  Value: '_SpecificationValue',
  productId: '_ProductId',
}

async function getCategoryProducts({ id }: Category, catalog: Catalog): Promise<string[]> {
  const {
    range: { total },
    data: firstData,
  } = await catalog.getProductAndSkuByCategory(id, 1, BATCH_SIZE)

  const froms = range(BATCH_SIZE + 1, total, BATCH_SIZE)

  const results = await Promise.all(
    froms.map(from =>
      catalog.getProductAndSkuByCategory(id, from, from + BATCH_SIZE - 1)
    )
  )

  return [
    ...Object.keys(firstData),
    ...chain(({ data }) => Object.keys(data), results),
  ]
}

async function getProductsSpecificationsFromCategories(
  categories: Category[],
  { clients: { catalog } }: Context
): Promise<ProductSpecification[]> {
  const products = await Promise.all(
    categories.map(category => getCategoryProducts(category, catalog))
  )
    .then(productsByCategory => unnest(productsByCategory))
    .then(repeatedProducts => uniq(repeatedProducts))

  const specificationsByProduct = await Promise.all(
    products.map(async productId => {
      const specifications = await catalog.getProductSpecification(productId)
      return specifications.map(specification => ({
        ...specification,
        productId: parseInt(productId, 10),
      }))
    })
  )

  return unnest(specificationsByProduct)
}

async function getCategoriesSpecificationsFieldsById(
  categories: Category[],
  ctx: Context
): Promise<Record<string, SpecificationFields>> {
  const {
    clients: { catalog },
  } = ctx
  const specifications = await getSpecifications(categories, ctx)
  const specificationsFieldsById: Record<string, SpecificationFields> = {}

  await Promise.all(
    specifications.map(async ({ FieldId }) => {
      specificationsFieldsById[FieldId] = await catalog.getSpecificationFields(
        FieldId
      )
    })
  )

  return specificationsFieldsById
}

export async function getTextSpecificationstValues(ctx: Context) {
  const { clients: { catalog } } = ctx
  const categories = await catalog.exportCategories()

  const [specifications, specificationFieldById] = await Promise.all([
    getProductsSpecificationsFromCategories(categories, ctx),
    getCategoriesSpecificationsFieldsById(categories, ctx),
  ])

  const productSpecifications = specifications.filter(({ Id }) =>
    isProductSpecification(specificationFieldById[Id])
  )

  // Product specifications are supposed to have ONLY ONE item on the Value list
  const normalizedSpecifications = productSpecifications.map(
    ({ Value: [Value], ...specification }) => ({
      ...specification,
      Value,
    })
  )

  const specificationsXLSX = normalizedSpecifications.map(specification =>
    jsonToXLSXFields(specification, specificationToXLSXMap)
  )

  return createXLSX({
    'Text Specification Values': specificationsXLSX,
  })
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/categorySpecs.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { uniqBy, unnest } from 'ramda'
import { createXLSX, jsonToXLSXFields } from './xlsx'

const specificationToXLSXMap: Record<keyof SpecificationTranslatables, string> = {
  FieldId: '_FieldId',
  Name: '_Name',
}

const valueToXLSXMap: Record<keyof SpecificationValueTranslatables, string> = {
  FieldValueId: '_ValueId',
  Value: '_Value',
}

export function getSpecifications(
  categories: Category[],
  { clients: { catalog } }: Context
): Promise<Specification[]> {
  return Promise.all([
    catalog.getSpecificationsTreeByCategory(categories[0].id),
    ...categories.map(({ id }) => catalog.getSpecificationsByCategory(id)),
  ])
    .then(specificationsByCategory => unnest(specificationsByCategory))
    .then(uniqBy(({ FieldId }) => FieldId))
}

export async function getSpecificationsXLXS(ctx: Context) {
  const { clients: { catalog } } = ctx
  const categories = await catalog.exportCategories()
  const specifications = await getSpecifications(categories, ctx)

  const specificationValues = await Promise.all(
    specifications.map(({ FieldId }) => catalog.getSpecificationValues(FieldId))
  )
    .then(valuesBySpecification => unnest(valuesBySpecification))
    .then(uniqBy(({ FieldValueId }) => FieldValueId))

  const specificationsXLSX = specifications.map(specification =>
    jsonToXLSXFields(specification as any, specificationToXLSXMap)
  )
  const valuesXLSX = specificationValues.map(value =>
    jsonToXLSXFields(value as any, valueToXLSXMap)
  )

  return createXLSX({
    Specifications: specificationsXLSX,
    Values: valuesXLSX,
  })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resources/addTranslations.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { IOMessageSaveInput, MessageSaveInputV2, SaveArgs as TranslateMessageArgs } from '@vtex/api'
import { map } from 'bluebird'
import { path, prop } from 'ramda'

import { clientOptions } from '..'
import { Clients } from '../clients'

type MessagesOfProvider = TranslateMessageArgs['messagesByProvider'][0]

const saveInputV1InputToSaveInputV2 = async (clients: Clients, entity: Entity, entityId: string, srcLang: string) => {
  const fetcher = clients.catalogGraphQL[entity]
  const response = typeof fetcher === 'function'
    ? await fetcher(entityId)
    : null
  const instance = response && prop(entity, response) as Record<string, string>
  return (message: IOMessageSaveInput): MessageSaveInputV2 | null => {
    const { id, content } = message
    const srcMessage = instance ? instance[id] : content

    if (!srcMessage) {
      if (clientOptions.default.verbose) {
        console.log(`id ${id} not available for instance of entity ${entity} of id ${entityId}`)
      }
      return null
    }

    return {
      groupContext: entity,
      srcLang,
      srcMessage,
      targetMessage: content,
    }
  }
}

async function addProductTranslations(
  messagesByProvider: MessagesOfProvider[],
  entity: Entity,
  language: string,
  ctx: Context
): Promise<FailedTranslation[]> {
  const { clients: { segment, messagesGraphQL }, clients } = ctx

  const { cultureInfo: defaultLang } = await segment.getSegment()

  const messagesFormattedV2Byprovider = await map(
    messagesByProvider,
    async ({provider: entityId, messages}) => {
      const toV2 = await saveInputV1InputToSaveInputV2(clients, entity, entityId, defaultLang)
      return {
        messages: messages.map(toV2).filter(x => !!x) as MessageSaveInputV2[],
        provider: entityId,
        to: language,
      }
    }
  )

  if (clientOptions.default.verbose) {
    console.log('saving', JSON.stringify(messagesFormattedV2Byprovider, null, 2))
  }

  const results = await map(
    messagesFormattedV2Byprovider,
    ({messages, provider, to}) =>
      messagesGraphQL
      .saveV2({messages, to})
      .then(success => [success, { provider }] as [boolean, { provider: string }])
      .catch(err => {
        const errors = path(['response', 'data', 'errors'], err)
        if (clientOptions.default.verbose) {
          if (errors) {
            console.log(errors)
          } else {
            console.log(err)
          }
        }
        throw err
      })
  )

  const failures = results.filter(([success]) => !success)
  return failures.map(([_, data]) => data)
}

export default addProductTranslations

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/typings/typings.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { SaveArgs as TranslateMessageArgs } from '@vtex/api'

export type ID = string
export type Float = number
export type Int = number

declare global {

  type MessagesOfProvider = TranslateMessageArgs['messagesByProvider'][0]

  interface FailedTranslation {
    provider: string
  }

  type Entity = 'product' | 'sku' | 'brand' | 'category'  // | 'specification'

  interface CategoryTranslatables {
    id: number
    name: string
    Title: string
    MetaTagDescription: string
  }

  interface Category extends CategoryTranslatables {
    hasChildren: boolean
    url: string | null
    children: Category[] | null
    fathercategoryid: number
  }

  interface BrandTranslatables {
    id: number
    name: string
    title: string
    metaTagDescription: string
  }

  interface Brand extends BrandTranslatables {
    isActive: boolean
    imageUrl: string | null
  }

  interface SpecificationTranslatables {
    Name: string
    FieldId: number
  }

  interface Specification extends SpecificationTranslatables {
    CategoryId: number
    IsActive: boolean
    IsStockKeepingUnit: boolean
  }

  interface SpecificationValueTranslatables {
    FieldValueId: number
    Value: string
  }

  interface SpecificationValue extends SpecificationValueTranslatables {
    IsActive: boolean
    Position: number
  }

  interface SkusByProduct {
    [productId: number]: [number]
  }

  interface ProductAndSkuByCategoryResult {
    data: SkusByProduct
    range: {
      total: number
      from: number
      to: number
    }
  }

  interface ProductSpecification {
    productId: number | null
    Value: string[]
    Id: number
    Name: string
  }

  interface SpecificationFields {
    Name: string
    CategoryId: number | null
    FieldId: number
    IsActive: boolean
    IsRequired: boolean
    FieldTypeId: number
    FieldTypeName: string
    FieldValueId: number | null
    Description: string
    IsStockKeepingUnit: boolean
    IsFilter: boolean
    IsOnProductDetails: boolean
    Position: number
    IsWizard: boolean
    IsTopMenuLinkActive: boolean
    IsSideMenuLinkActive: boolean
    DefaultValue: string | number | null
    FieldGroupId: number
    FieldGroupName: string
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resolvers/addTranslations.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import addTranslations from '../resources/addTranslations'

interface AddTranslationsArgs {
  entity: Entity
  language: string
  translations : MessagesOfProvider[]
}

function addTranslationsResolver(
  _: unknown,
  { entity, language, translations }: AddTranslationsArgs,
  ctx: Context
): Promise<FailedTranslation[]> {
  return addTranslations(translations, entity, language, ctx)
}

export default addTranslationsResolver

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/resolvers/exportProductCatalog.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AuthenticationError } from '@vtex/api'

const E_AUTH = 'VtexIdclientAutCookie not found'

async function exportProductCatalog(
  _: unknown,
  __: unknown,
  ctx: Context
): Promise<boolean> {
  const {
    cookies,
    clients: { admin, licenseManager },
  } = ctx
    const VtexIdclientAutCookie = cookies.get('VtexIdclientAutCookie')
    if (!VtexIdclientAutCookie) {
      throw new AuthenticationError(E_AUTH)
    }

    const profileData = await licenseManager.getTopbarData(VtexIdclientAutCookie)
    const email = profileData && profileData.profile && profileData.profile.email

    // Cannot await this promise because it can take several minutes to get resolved.
    // In practice the connection will timeout before it...
    admin.exportCatalogToEmail(email)

    return true
}

export default exportProductCatalog

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/handlers/specifications.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getSpecificationsXLXS } from '../resources/categorySpecs'

export default async function getSpecificationsHandler(ctx: Context) {
  ctx.status = 200
  ctx.body = await getSpecificationsXLXS(ctx)
  ctx.set('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
  ctx.set('cache-control', 'no-cache')
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/handlers/brands.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getBrandXLSX } from '../resources/brand'

export default async function brandsHandler(ctx: Context) {
  ctx.status = 200
  ctx.body = await getBrandXLSX(ctx)
  ctx.set('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
  ctx.set('cache-control', 'no-cache')
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/handlers/specificationsTextValues.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getTextSpecificationstValues } from '../resources/productSpecs'

export default async function textSpecificationstValuesHandler(ctx: Context) {
  ctx.status = 200
  ctx.body = await getTextSpecificationstValues(ctx)
  ctx.set('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
  ctx.set('cache-control', 'no-cache')
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/handlers/categories.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getCategoryXLSX } from '../resources/category'

export default async function categoriesHandler(ctx: Context) {
  ctx.status = 200
  ctx.body = await getCategoryXLSX(ctx)
  ctx.set('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
  ctx.set('cache-control', 'no-cache')
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/handlers/index.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import brands from './brands'
import categories from './categories'
import specifications from './specifications'
import textSpecificationstValues from './specificationsTextValues'

export default {
  brands,
  categories,
  specifications,
  textSpecificationstValues,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/catalogGraphQL/category.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const query = `
query GetCategory($id: ID!) {
  category (id: $id) {
    name
    title
    parentCategoryId
    description
    isActive
    globalCategoryId
    score
  }
}
`

export interface CategoryTranslatableField {
  name: string
  title?: string
}

export type Category = CategoryTranslatableField

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/catalogGraphQL/brand.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const query = `
query GetBrand($id: ID!) {
  brand (id: $id) {
    name
    text
    keywords
    siteTitle
    active
    menuHome
    adWordsRemarketingCode
    lomadeeCampaignCode
    score
  }
}
`

export interface BrandTranslatableField {
  name: string
}

export type Brand = BrandTranslatableField

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/catalogGraphQL/product.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const query = `
query GetProduct ($identifier: ProductUniqueIdentifier!) {
  product (identifier: $identifier) {
    name
    description
    descriptionShort: shortDescription
    titleTag: title
    metaTagDescription
  }
}
`

export interface ProductTranslatableField {
  name: string
  description?: string
  descriptionShort?: string
  titleTag?: string
  metaTagDescription?: string
}

export type Product = ProductTranslatableField

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/catalogGraphQL/index.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AppGraphQLClient, InstanceOptions, IOContext } from '@vtex/api'
import { prop } from 'ramda'

import { ID } from '../../typings/typings'
import { Brand, query as getBrand } from './brand'
import { Category, query as getCategory } from './category'
import { Product, query as getProduct } from './product'
import { query as getSKU, SKU } from './sku'

export class CatalogGraphQL extends AppGraphQLClient {
  public constructor(ctx: IOContext, opts?: InstanceOptions) {
    super('vtex.catalog-graphql@1.x', ctx, {
      ...opts,
      headers: {
        ...opts && opts.headers,
        cookie: `VtexIdclientAutCookie=${ctx.authToken}`,
      }})
  }

  public sku = (id: string) => {
    const variables = {
      identifier: {
        field: 'id',
        value: id,
      },
    }
    return this.graphql
      .query<{sku: SKU}, typeof variables>({
        inflight: true,
        query: getSKU,
        variables,
      })
      .then(prop('data'))
  }

  public product = (id: string) => {
    const variables = {
      identifier: {
        field: 'id',
        value: id,
      },
    }
    return this.graphql
      .query<{product: Product}, typeof variables>({
        inflight: true,
        query: getProduct,
        variables,
      })
      .then(prop('data'))
  }

  public category = (id: string) =>
    this.graphql
      .query<{category: Category}, { id: ID }>({
        inflight: true,
        query: getCategory,
        variables: { id },
      })
      .then(prop('data'))

  public brand = (id: string) =>
    this.graphql
      .query<{brand: Brand}, { id: ID }>({
        inflight: true,
        query: getBrand,
        variables: { id },
      })
      .then(prop('data'))
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/node/clients/catalogGraphQL/sku.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const query = `
query GetSKU ($identifier: SKUUniqueIdentifier!) {
  sku (identifier: $identifier) {
    name
  }
}
`

export interface SKUTranslatableField {
  name: string
}

export type SKU = SKUTranslatableField

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/mutations/AddTranslations.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Mutation, MutationFn } from 'react-apollo'
import AddTranslations from '../graphql/AddTranslations.graphql'
import { MessagesOfProvider } from '../typings/typings'
import { Entity } from '../utils/constants'

interface FailedTranslation {
  provider: string
}

interface AddTranslationsData {
  addTranslations: FailedTranslation[]
}

interface AddTranslationsVariables {
  entity: Entity
  language: string
  translations : MessagesOfProvider[]
}

export type AddTranslationsMutationFn = MutationFn<
  AddTranslationsData,
  AddTranslationsVariables
>

class AddTranslationsMutation extends Mutation<
  AddTranslationsData,
  AddTranslationsVariables
> {
  public static defaultProps = {
    mutation: AddTranslations,
  }
}

export default AddTranslationsMutation

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/mutations/ExportProductCatalog.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Mutation, MutationFn } from 'react-apollo'
import ExportProductCatalog from '../graphql/ExportProductCatalog.graphql'

interface ExportProductCatalogData {
  exportProductCatalog: boolean
}

type ExportProductCatalogVariables = void

export type ExportProductCatalogMutationFn = MutationFn<
  ExportProductCatalogData,
  ExportProductCatalogVariables
>

class ExportProductCatalogMutation extends Mutation<
  ExportProductCatalogData,
  ExportProductCatalogVariables
> {
  public static defaultProps = {
    mutation: ExportProductCatalog,
  }
}

export default ExportProductCatalogMutation

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/typings/typings.d.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare global {
  declare module '*.graphql' {
    import { DocumentNode } from 'graphql'

    const value: DocumentNode
    export default value
  }
}

export interface TranslationMessage {
  id: string
  content: string
  description?: string
}

interface MessagesOfProvider {
  messages: TranslationMessage[]
  provider: string
}

export interface MessagesTranslation {
    to: string
    messagesByProvider: MessagesOfProvider[]
}

export interface StepCounterControl {
  current: number
  total: number
  next: () => void
  back: () => void
}

type StateHook<T> = [T, Dispatch<SetStateAction<T>>]

export interface TranslationDataHooks {
  locale: StateHook<SupportedLocale | null>
  messages: StateHook<MessagesOfProvider[] | null>
}

export interface ButtonProps {
  disabled: boolean
}

export type SupportedLocale = 'en' | 'pt' | 'es' | 'fr'

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/typings/vtex.render-runtime.d.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* Typings for `render-runtime` */
declare module 'vtex.render-runtime' {
  export const Helmet: any
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/typings/vtex.styleguide.d.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript

/* Typings for `vtex.styleguide` */
declare module 'vtex.styleguide' {
  import { ComponentClass, ComponentType } from 'react'

  interface ShowToastOptions {
    action?: {
      label: string
      onClick: () => void
    }
    message: string
    duration?: number
    horizontalPosition?: 'right' | 'left'
  }

  export type ShowToastFunction = (a: ShowToastOptions | string) => void

  export interface ToastProps {
    showToast: ShowToastFunction
    hideToast: () => void
    toastState: unknown
  }

  export function withToast<P>(
    component: ComponentType<P & ToastProps>
  ): ComponentClass<Pick<P, Exclude<keyof P, keyof ToastProps>>>

  export const Alert: any
  export const Box: any
  export const Button: any
  export const Dropdown: any
  export const IconClose: any
  export const Layout: any
  export const PageBlock: any
  export const PageHeader: any
  export const ProgressBar: any
  export const ToastProvider: any
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/queries/GetUserEmail.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Query } from 'react-apollo'
import GetUserEmail from '../graphql/GetUserEmail.graphql'

export interface EmailData {
  topbarData : {
    profile? : {
      email? : string
    }
  }
}

class GetUserEmailQuery extends Query<EmailData> {
  public static defaultProps = {
    query: GetUserEmail,
  }
}

export default GetUserEmailQuery

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/utils/csv.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { read, utils } from 'xlsx'

import { uniqBy } from 'ramda'
import { MessagesOfProvider, TranslationMessage } from '../typings/typings'
import { Entity, ENTITY_FIELDS } from './constants'

const ENTITY_ID_HEADER: Partial<Record<Entity, string>> = {
  brand: '_BrandId',
  category: '_CategoryId',
  product: '_ProductId',
  sku: '_SkuId',
  specification: '_Name',
}

const uniqueByProvider = uniqBy(({ provider }: MessagesOfProvider) => provider)

async function parse(csv: File): Promise<string[][]> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsBinaryString(csv)
    reader.onload = () => {
      const book = read(reader.result, {type: 'binary'})

      if (book.SheetNames.length !== 1) {
        throw new Error('XLS_SINGLE_SHEET')
      }

      const sheet = Object.values(book.Sheets)[0]

      const data = utils.sheet_to_json(sheet) as Array<Record<string, string>>
      const headers = Object.keys(data[0])

      // Export as CSV table, first line contain headers and subsequent lines contain data
      resolve([
        headers,
        ...data.map(row => headers.map(header => row[header])),
      ])
    }

    reader.onerror = (e) => reject(e)
  })
}

function getProviderMessages(
  fieldAndIndex: Array<[string, number]>,
  row: string[]
): TranslationMessage[] {
  return (
    fieldAndIndex
      .map(([key, index]) => ({
        content: row[index!],
        description: '',
        id: key,
      }))
      // TODO: check if this filter is right
      .filter(({ content }) => !!content)
  )
}

export async function getMessages(entity: Entity, csv: File): Promise<MessagesOfProvider[]> {
  const [headers, ...data] = await parse(csv)
  const fieldToIndex: Partial<Record<string, number>> = {}

  Object.entries(ENTITY_FIELDS[entity]).forEach(([key, desc]) => {
    const index = headers.findIndex(header => header.startsWith(desc))
    if (index !== -1) {
      fieldToIndex[key] = index
    }
  })

  const fieldAndIndex = Object.entries(fieldToIndex) as Array<[string, number]>
  if (fieldAndIndex.length === 0) {
    throw new Error('NO_TRANSLATABLE_FIELD_FOUND')
  }

  const id = ENTITY_ID_HEADER[entity] || ''
  const idIndex = headers.findIndex(header => header.startsWith(id))
  if (idIndex === -1) {
    throw new Error('ID_NOT_FOUND')
  }

  const messagesByProvider = uniqueByProvider(
    data.map(row => ({
      messages: getProviderMessages(fieldAndIndex, row),
      provider: row[idIndex] && row[idIndex].toString(),
    }))
  ).filter(({ messages, provider }) => messages.length > 0 && !!provider)

  return messagesByProvider
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/utils/constants.ts from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { BrandTranslatableField } from '../../node/clients/catalogGraphQL/brand'
import { CategoryTranslatableField } from '../../node/clients/catalogGraphQL/category'
import { ProductTranslatableField } from '../../node/clients/catalogGraphQL/product'
import { SKUTranslatableField } from '../../node/clients/catalogGraphQL/sku'

export const PRODUCT_FIELD_TO_CSV_COL : Record<keyof ProductTranslatableField, string> = {
  description: '_ProductDescription',
  descriptionShort : '_ProductShortDescription',
  metaTagDescription : '_MetaTagDescription',
  name: '_ProductName',
  titleTag : '_SiteTitle',
}

export const SKU_FIELD_TO_CSV_DESC : Record<keyof SKUTranslatableField, string> = {
  name: '_SkuName',
  // nameComplete: '_SkuNameComplete',
}

export const BRAND_FIELD_TO_CSV_DESC : Record<keyof BrandTranslatableField, string> = {
  // metaTagDescription: '_MetaTagDescription',
  name: '_Name',
  // title: '_Title',
}

export const CATEGORY_FIELD_TO_CSV_DESC : Record<keyof CategoryTranslatableField, string> = {
  // metaTagDescription: '_MetaTagDescription',
  name: '_Name',
  title: '_Title',
}

export const SPECIFICATION_FIELD_TO_CSV_DESC = {
  name: '_Name',
}

export type Entity = 'product' | 'sku' | 'brand' | 'category' | 'specification'

export const ENTITY_FIELDS: Record<Entity, Record<string, string>> = {
  brand: BRAND_FIELD_TO_CSV_DESC,
  category: CATEGORY_FIELD_TO_CSV_DESC,
  product: PRODUCT_FIELD_TO_CSV_COL,
  sku: SKU_FIELD_TO_CSV_DESC,
  specification: SPECIFICATION_FIELD_TO_CSV_DESC,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/components/MessagesProgress.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
import { defineMessages, InjectedIntl, injectIntl } from 'react-intl'

import { Button, PageBlock, ProgressBar } from 'vtex.styleguide'

import { AddTranslationsMutationFn } from '../mutations/AddTranslations'
import { MessagesOfProvider, StepCounterControl, SupportedLocale } from '../typings/typings'
import { Entity } from '../utils/constants'
import { LOCALE_TO_MESSAGE } from './utils/LanguagePicker'
import StepCounter from './utils/StepCounter'

const BATCH_SIZE = 10
const PROGRESS_BARS = 50

const messages = defineMessages({
  cancel: {
    defaultMessage: '',
    id: 'admin/messages.cancel',
  },
  done: {
    defaultMessage: '',
    id: 'admin/messages.done',
  },
  progress: {
    defaultMessage: '',
    id: 'admin/messages.messages-progress.translate-progress',
  },
  retry: {
    defaultMessage: '',
    id: 'admin/messages.retry',
  },
  translationFaileded: {
    defaultMessage: '',
    id: 'admin/messages.messages-progress.translation-faileded',
  },
  translationSucceeded: {
    defaultMessage: '',
    id: 'admin/messages.messages-progress.translation-succeeded',
  },
})

function getProgressBarState(progress: number, total: number): string[] {
  const completed = Math.floor((progress / total) * PROGRESS_BARS)
  const inProgress =
    progress < total
      ? Math.min(
          Math.max(1, Math.ceil((PROGRESS_BARS * BATCH_SIZE) / total)),
          PROGRESS_BARS - completed
        )
      : 0
  return [
    ...Array(completed).fill('completed'),
    ...Array(inProgress).fill('inProgress'),
    ...Array(PROGRESS_BARS - completed - inProgress).fill('toDo'),
  ]
}

function getUploadProgressMessage(
  uploaded: number,
  total: number,
  failed: number,
  language: string,
  intl: InjectedIntl
) {
  if (uploaded < total) {
    return intl.formatMessage(messages.progress, {
      language,
      progress: uploaded - failed,
      total,
    })
  }

  if (failed > 0) {
    return intl.formatMessage(messages.translationFaileded, { failed })
  }

  return intl.formatMessage(messages.translationSucceeded, { language })
}

function getCurrentProgressPercentage(progress: number, total: number): string {
  return `${Math.floor((100 * progress) / total)} %`
}

interface Props {
  addTranslations: AddTranslationsMutationFn
  done: () => void
  entity: Entity
  intl: InjectedIntl
  locale: SupportedLocale
  stepCounterControl: StepCounterControl
  messages: MessagesOfProvider[]
  setMessages: Dispatch<SetStateAction<MessagesOfProvider[] | null>>
}

const MessagesProgress: FC<Props> = ({
  addTranslations,
  done,
  entity,
  intl,
  locale,
  messages: translationMessages,
  setMessages,
  stepCounterControl,
}) => {
  const [cancelled, setCancelled] = useState(false)
  const [batchProgress, setBatchProgress] = useState(0)
  const [lastRetry, setLastRetry] = useState(-1)
  const [failedTranslations, setFailedTranslations] = useState(
    [] as MessagesOfProvider[]
  )

  const batchesNumber = Math.ceil(translationMessages.length / BATCH_SIZE)

  useEffect(() => {
    if (cancelled) {
      return
    }

    const start = batchProgress * BATCH_SIZE
    const end = Math.min(
      start + BATCH_SIZE,
      translationMessages.length
    )
    const translations = translationMessages.slice(start, end)

    addTranslations({ variables: { entity, translations, language: locale! } })
      .then(result => {
        if (result && result.data) {
          const failedProviders = new Set(
            result.data.addTranslations.map(({ provider }) => provider)
          )
          setFailedTranslations([
            ...failedTranslations,
            ...translations.filter(({ provider }) =>
              failedProviders.has(provider)
            ),
          ])
        }
      })
      .catch(() => {
        if (lastRetry === batchProgress) {
          setFailedTranslations([...failedTranslations, ...translations])
          return
        }
        setLastRetry(batchProgress)
      })
      .then(() => {
        if (batchProgress < batchesNumber) {
          setBatchProgress(batchProgress + 1)
        }
      })
  }, [batchProgress, cancelled, lastRetry])

  const progress = Math.min(
    batchProgress * BATCH_SIZE,
    translationMessages.length
  )
  const total = translationMessages.length

  const language = intl.formatMessage(LOCALE_TO_MESSAGE[locale])

  const retry = () => {
    setMessages(failedTranslations)
    setFailedTranslations([])
    setCancelled(false)
    setBatchProgress(0)
    setLastRetry(-1)
  }

  const cancel = () => {
    setCancelled(true)
    done()
  }

  return (
    <PageBlock>
      <div className="flex items-center flex-column mb3">
        <p>
          {getUploadProgressMessage(
            progress,
            total,
            failedTranslations.length,
            language,
            intl
          )}
        </p>
        <div className="mv3 w-100">
          <ProgressBar
            danger={failedTranslations.length > 0}
            steps={getProgressBarState(progress, total)}
          />
        </div>
        <p>{getCurrentProgressPercentage(progress, total)}</p>
        {progress < total ? (
          <Button variation="secondary" onClick={cancel}>
            {intl.formatMessage(messages.cancel)}
          </Button>
        ) : failedTranslations.length > 0 ? (
          <Button onClick={retry}>{intl.formatMessage(messages.retry)}</Button>
        ) : (
          <Button onClick={done}>{intl.formatMessage(messages.done)}</Button>
        )}
      </div>
      <StepCounter removeBack {...stepCounterControl} intl={intl} />
    </PageBlock>
  )
}

export default injectIntl(MessagesProgress)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/components/AdminMessages.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useState } from 'react'
import { defineMessages, InjectedIntl, injectIntl } from 'react-intl'

import { Layout, PageHeader } from 'vtex.styleguide'

import { AddTranslationsMutationFn } from '../mutations/AddTranslations'
import { ExportProductCatalogMutationFn } from '../mutations/ExportProductCatalog'
import { MessagesOfProvider, StepCounterControl, SupportedLocale } from '../typings/typings'
import { Entity } from '../utils/constants'
import MessagesExport from './MessagesExport'
import MessagesImport from './MessagesImport'
import MessagesProgress from './MessagesProgress'

const TOTAL_STEPS = 3

const title = defineMessages({
  brand: { defaultMessage: '', id: 'admin/messages.header.brand.title' },
  category: { defaultMessage: '', id: 'admin/messages.header.category.title' },
  product: { defaultMessage: '', id: 'admin/messages.header.product.title' },
  sku: { defaultMessage: '', id: 'admin/messages.header.sku.title' },
  specification: { defaultMessage: '', id: 'admin/messages.header.specification.title' },
})

interface Props {
  addProductTranslations: AddTranslationsMutationFn
  email: string
  entity: Entity
  exportProductCatalog: ExportProductCatalogMutationFn
  intl: InjectedIntl
}

const AdminMessages: FC<Props> = ({
  addProductTranslations,
  email,
  entity,
  exportProductCatalog,
  intl,
}) => {
  const [step, setStep] = useState(1)

  const translationDataHooks = {
    locale: useState<SupportedLocale | null>(null),
    messages: useState<MessagesOfProvider[] | null>(null),
  }

  const {
    locale: [locale, setLocale],
    messages: [messages, setMessages],
  } = translationDataHooks

  const next = () => setStep(step + 1)
  const back = () => setStep(step - 1)

  const stepCounterControl: StepCounterControl = {
    back,
    current: step,
    next,
    total: TOTAL_STEPS,
  }

  const done = () => {
    setLocale(null)
    setMessages(null)
    setStep(1)
  }

  return (
    <div className="min-vh-100 bg-muted-5">
      <Layout
        pageHeader={<PageHeader title={intl.formatMessage(title[entity])} />}
      >
        {step === 1 && (
          <MessagesExport
            email={email}
            entity={entity}
            exportCSV={exportProductCatalog}
            stepCounterControl={stepCounterControl}
          />
        )}
        {step === 2 && (
          <MessagesImport
            entity={entity}
            stepCounterControl={stepCounterControl}
            translationDataHooks={translationDataHooks}
          />
        )}
        {step === 3 && (
          <MessagesProgress
            addTranslations={addProductTranslations}
            done={done}
            entity={entity}
            locale={locale!}
            stepCounterControl={stepCounterControl}
            messages={messages!}
            setMessages={setMessages}
          />
        )}
      </Layout>
    </div>
  )
}

export default injectIntl(AdminMessages)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/components/AdminMessagesWrapper.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useState } from 'react'
import { defineMessages, InjectedIntlProps, injectIntl } from 'react-intl'

import { Helmet } from 'vtex.render-runtime'

import { ToastProvider } from 'vtex.styleguide'
import AddTranslationsMutation from '../mutations/AddTranslations'
import ExportProductCatalogMutation from '../mutations/ExportProductCatalog'
import GetUserEmailQuery, { EmailData } from '../queries/GetUserEmail'
import { Entity } from '../utils/constants'
import AdminMessages from './AdminMessages'

const { header } = defineMessages({
  header: {
    defaultMessage: '',
    id: 'admin/messages.navigation.label',
  },
})

function extractEmail(data: EmailData | undefined): string {
  try {
    return data!.topbarData!.profile!.email || ''
  } catch {
    return ''
  }
}

interface Props extends InjectedIntlProps {
  entity: Entity
}

const AdminMessagesWrapper: FC<Props> = ({ entity, intl }) => {
  return (
    <>
      <Helmet>
        <title>{intl.formatMessage(header)}</title>
      </Helmet>
      <ToastProvider positioning="parent">
        <GetUserEmailQuery>
          {result => (
            <AddTranslationsMutation>
              {addProductTranslations => (
                <ExportProductCatalogMutation>
                  {exportProductCatalog => (
                    <AdminMessages
                      addProductTranslations={addProductTranslations}
                      email={extractEmail(result.data)}
                      entity={entity}
                      exportProductCatalog={exportProductCatalog}
                    />
                  )}
                </ExportProductCatalogMutation>
              )}
            </AddTranslationsMutation>
          )}
        </GetUserEmailQuery>
      </ToastProvider>
    </>
  )
}

export default injectIntl(AdminMessagesWrapper)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/components/MessagesImport.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { InjectedIntl, injectIntl } from 'react-intl'

import { PageBlock } from 'vtex.styleguide'

import { StepCounterControl, TranslationDataHooks } from '../typings/typings'
import { Entity } from '../utils/constants'
import CSVUploader from './CSVUploader'
import LanguagePicker from './utils/LanguagePicker'
import StepCounter from './utils/StepCounter'
interface Props {
  entity: Entity
  intl: InjectedIntl
  stepCounterControl: StepCounterControl
  translationDataHooks: TranslationDataHooks
}

const MessagesImport: FC<Props> = ({
  entity,
  intl,
  stepCounterControl,
  translationDataHooks: {
    locale: [locale, setLocale],
    messages: [messages, setMessages],
  },
}) => {
  return (
    <PageBlock>
      <CSVUploader entity={entity} intl={intl} setMessages={setMessages} />
      <LanguagePicker
        intl={intl}
        locale={locale}
        setLocale={setLocale}
      />
      <StepCounter
        {...stepCounterControl}
        intl={intl}
        nextDisabled={!locale || !messages}
      />
    </PageBlock>
  )
}

export default injectIntl(MessagesImport)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of admin-messages-catalog/react/components/CSVUploader.tsx from the admin-messages-catalog VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC, useState } from 'react'
import { useDropzone } from 'react-dropzone'
import { defineMessages, InjectedIntl } from 'react-intl'

import { Alert, Button, IconClose } from 'vtex.styleguide'
import { MessagesOfProvider } from '../typings/typings'
import { Entity } from '../utils/constants'
import { getMessages } from '../utils/csv'

const MEGA = 2**20

const {
  productCatalog,
  upload,
  noIdColumn,
  notSupportedFile,
  noTranslatableField,
} = defineMessages({
  noIdColumn: {
    defaultMessage: '',
    id: 'admin/messages.messages-upload.error-id-column',
  },
  noTranslatableField: {
    defaultMessage: '',
    id: 'admin/messages.messages-upload.error-no-translatable-field',
  },
  notSupportedFile: {
    defaultMessage: '',
    id: 'admin/messages.messages-upload.error-supported-file',
  },
  productCatalog: {
    defaultMessage: '',
    id: 'admin/messages.messages-upload.catalog-label',
  },
  upload: {
    defaultMessage: '',
    id: 'admin/messages.messages-upload.upload-label',
  },
})

type ErrorCode = null | 'REJECTED' | 'NO_TRANSLATABLE_FIELD_FOUND' | 'ID_NOT_FOUND'

function errorToMessage(
  error: ErrorCode,
  { formatMessage }: InjectedIntl
): string {
  switch (error) {
    case null:
      return ''
    case 'REJECTED':
      return formatMessage(notSupportedFile)
    case 'NO_TRANSLATABLE_FIELD_FOUND':
      return formatMessage(noTranslatableField)
    case 'ID_NOT_FOUND':
      return formatMessage(noIdColumn)
  }
}

interface CSVUploaderProps {
  entity: Entity
  intl: InjectedIntl
  setMessages: (messages: MessagesOfProvider[] | null) => void
}

const CSVUploader: FC<CSVUploaderProps> = ({ entity, intl, setMessages }) => {
  const [name, setName] = useState('')
  const [error, setError] = useState<ErrorCode>(null)
  const [loading, setLoading] = useState(false)

  const { getRootProps, getInputProps } = useDropzone({
    accept: ['.csv', '.xls', '.xlsx'],
    maxSize: 20 * MEGA,
    multiple: false,
    onDrop: async ([uploadedFile]: File[]) => {
      if (!uploadedFile) {
        setError('REJECTED')
        return
      }

      let errorCode: ErrorCode = null
      setLoading(true)
      const messages = await getMessages(entity, uploadedFile)
        .catch((e: Error) => {
          errorCode = e.message as ErrorCode
          return [] as MessagesOfProvider[]
        })
        .finally(() => setLoading(false))

      if (!errorCode) {
        setName(uploadedFile.name)
        setMessages(messages)
        setError(null)
        return
      }

      setError(errorCode)
    },
  })

  const reset = () => {
    setMessages(null)
    setName('')
  }

  return (
    <div className="bb b--muted-4 nh7 ph7 pb7 mb7">
      {!!error ? (
        <div className="mb7">
          <Alert type="error" onClose={() => setError(null)}>
            {errorToMessage(error, intl)}
          </Alert>
        </div>
      ) : null}
      <div className="flex items-center">
        <div className="flex-grow-1 tl">
          <p className="mb1 mt0">
            {intl.formatMessage(productCatalog)}
          </p>
        </div>
        {!name ? (
          <div {...getRootProps()}>
            <Button variation="secondary" isLoading={loading}>
              {intl.formatMessage(upload)}
            </Button>
            <input {...getInputProps()} />
          </div>
        ) : (
          <>
            <p>{name}</p>
            <div className="ph3 pointer" onClick={reset}>
              <IconClose />
            </div>
          </>
        )}
      </div>
    </div>
  )
}

export default CSVUploader
```