msds-tds/scripts/generate-sds-lang.py
2026-07-08 13:12:20 +00:00

914 lines
60 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Generate BG and RO SDS by translating the EN template."""
import os, base64, re, json, sys
from weasyprint import HTML
PRIMARY = "#004C98"
SECONDARY = "#2B2E33"
MUTED = "#5B6670"
ACCENT = "#0071B8"
HIGHLIGHT = "#F2F6FA"
BORDER = "#D9E1E8"
WHITE = "#FFFFFF"
WARNING_AMBER = "#C77700"
def img_b64(path):
with open(path, 'rb') as f:
return f"data:image/png;base64,{base64.b64encode(f.read()).decode()}"
def svg_b64(path):
with open(path, 'rb') as f:
return f"data:image/svg+xml;base64,{base64.b64encode(f.read()).decode()}"
logo_b64 = img_b64('/home/bachko/msds-tds/assets/logo-synthesia.png')
iso_b64 = svg_b64('/home/bachko/msds-tds/assets/iso-tuv-rheinland.svg')
# ─── Language-specific content ───
TR = {}
# Bulgarian
TR['BG'] = {
'lang': 'bg',
'company': 'Синтезия ООД',
'sds_title': 'ИНФОРМАЦИОНЕН ЛИСТ ЗА БЕЗОПАСНОСТ',
'product_name': 'Ethyl acetate (Етилацетат)',
'reg_line': 'Съгласно Регламент (ЕС) 2020/878 (Приложение II на REACH) · Регламент (ЕО) 1272/2008 (CLP), изменен с (ЕС) 2024/2865',
'footer_contact': 'Синтезия ООД · ДДС BG121306542 · Тодор Радунчев 9, Кривина 1588, България · +359 2 974 4968 · office@synthesia.bg',
'footer_cert': 'Сертифициран ISO 9001:2015 · ISO 14001:2015 · ISO 45001:2018 — TÜV Rheinland, ID 9105074744',
'hdr_title': 'ИНФОРМАЦИОНЕН ЛИСТ ЗА БЕЗОПАСНОСТ',
'hdr_sub': 'Ethyl acetate (Етилацетат)',
'hdr_ref': 'SDS-ETHYL-ACETATE-REV1-BG · 07/07/2026',
# Section titles
'sec1': 'РАЗДЕЛ 1: Идентифициране на веществото/сместа и на дружеството/предприятието',
'sec1_1': '1.1 Идентификатор на веществото/сместа',
'sec1_2': '1.2 Посочени съществени употреби на веществото или сместа и употреби, които не се препоръчват',
'sec1_3': '1.3 Подробни данни за доставчика на информационния лист за безопасност',
'sec1_4': '1.4 Телефонен номер при спешни случаи',
'sec2': 'РАЗДЕЛ 2: Описание на опасностите',
'sec2_1': '2.1 Класификация на веществото или сместа',
'sec2_2': '2.2 Елементи на етикета',
'sec2_3': '2.3 Други опасности',
'sec3': 'РАЗДЕЛ 3: Състав/информация за съставките',
'sec3_1': '3.1 Вещества',
'sec3_2': '3.2 Смеси',
'sec4': 'РАЗДЕЛ 4: Мерки за първа помощ',
'sec4_1': '4.1 Описание на мерките за първа помощ',
'sec4_2': '4.2 Най-важни симптоми и ефекти, остри и забавени',
'sec4_3': '4.3 Указание за необходимостта от всякакви неотложни медицински грижи и специално лечение',
'sec5': 'РАЗДЕЛ 5: Противопожарни мерки',
'sec5_1': '5.1 Средства за гасене на пожар',
'sec5_2': '5.2 Особени опасности, произтичащи от веществото или сместа',
'sec5_3': '5.3 Съвети за пожарникарите',
'sec6': 'РАЗДЕЛ 6: Мерки при аварийно изпускане',
'sec6_1': '6.1 Лични предпазни мерки, предпазно оборудване и процедури при спешни случаи',
'sec6_2': '6.2 Предпазни мерки за опазване на околната среда',
'sec6_3': '6.3 Методи и материали за ограничаване и почистване',
'sec6_4': '6.4 Позоваване на други раздели',
'sec7': 'РАЗДЕЛ 7: Работа и съхранение',
'sec7_1': '7.1 Предпазни мерки за безопасна работа',
'sec7_2': '7.2 Условия за безопасно съхранение, включително несъвместимости',
'sec7_3': '7.3 Специфична(и) крайна(и) употреба(и)',
'sec8': 'РАЗДЕЛ 8: Контрол на експозицията/лични предпазни средства',
'sec8_1': '8.1 Параметри на контрол',
'sec8_2': '8.2 Контрол на експозицията',
'sec9': 'РАЗДЕЛ 9: Физични и химични свойства',
'sec9_1': '9.1 Информация относно основните физични и химични свойства',
'sec10': 'РАЗДЕЛ 10: Стабилност и реактивоспособност',
'sec11': 'РАЗДЕЛ 11: Токсикологична информация',
'sec11_1': '11.1 Информация относно класовете на опасност',
'sec11_2': '11.2 Информация за други опасности',
'sec12': 'РАЗДЕЛ 12: Екологична информация',
'sec13': 'РАЗДЕЛ 13: Обезвреждане',
'sec13_1': '13.1 Методи за третиране на отпадъци',
'sec14': 'РАЗДЕЛ 14: Информация относно транспортирането',
'sec15': 'РАЗДЕЛ 15: Информация относно нормативната уредба',
'sec15_1': '15.1 Специфични за веществото или сместа разпоредби за безопасност, здраве и околна среда/законодателство',
'sec15_2': '15.2 Оценка на химичната безопасност',
'sec16': 'РАЗДЕЛ 16: Друга информация',
# Label headers
'property': 'Свойство',
'value': 'Стойност',
'product_form': 'Вид на продукта',
'substance': 'Вещество',
'chem_name': 'Химично наименование',
'index_no': 'Индекс No по ЕО',
'ec_no': 'EO No',
'cas_no': 'CAS No',
'reach_no': 'Регистрационен No по REACH',
'mol_formula': 'Молекулна формула',
'use_substance': 'Употреба на веществото/сместа',
'restrictions': 'Ограничения на употреба',
'industrial': 'Промишлена употреба',
'no_data': 'Няма налични данни',
'field': 'Поле',
'details': 'Данни',
'company': 'Дружество',
'address': 'Адрес',
'vat': 'ДДС No',
'phone': 'Телефон',
'email': 'Имейл',
'emergency': 'Спешен телефон',
'classification': 'Класификация съгласно Регламент (ЕО) No 1272/2008 [CLP], изменен с (ЕС) 2024/2865',
'hazard_class': 'Клас на опасност',
'category': 'Категория',
'hazard_statement': 'Предупреждение за опасност',
'full_h_text': 'Пълен текст на H-предупрежденията: вижте раздел 16.',
'element': 'Елемент',
'pictograms': 'Пиктограми за опасност',
'signal_word': 'Сигнална дума',
'danger': 'ОПАСНОСТ',
'hazard_statements': 'Предупреждения за опасност',
'precautions': 'Препоръки за безопасност',
'euh_statements': 'Допълнителни предупреждения',
'component': 'Компонент',
'concentration': 'Концентрация',
'mw_formula': 'Молекулна маса: {} g/mol  |  Формула: {}',
'not_applicable': 'Не се прилага',
'route': 'Път на експозиция',
'measures': 'Мерки',
'general': 'Общи мерки',
'inhalation': 'След вдишване',
'skin_contact': 'След контакт с кожата',
'eye_contact': 'След контакт с очите',
'ingestion': 'След поглъщане',
'symptoms': 'Симптоми/ефекти',
'description': 'Описание',
'medical': 'Лекувайте симптоматично',
'suitable_media': 'Подходящи средства за гасене',
'unsuitable_media': 'Неподходящи средства за гасене',
'fire_hazard': 'Пожарна опасност',
'decomp_products': 'Опасни продукти на разпадане',
'firefighters': 'Не предприемайте действия без подходящи защитни средства.',
'personnel': 'Персонал',
'non_emergency': 'За персонал, работещ не при спешни случаи',
'emergency_responders': 'За лица, оказващи помощ при спешни случаи',
'env_precautions': 'Да се избягва изпускане в околната среда.',
'cleaning_methods': 'Методи за почистване',
'other_info': 'Друга информация',
'ref_sections': 'Вижте предпазните мерки, посочени в раздели 7 и 8.',
'hygiene': 'Хигиенни мерки:',
'storage_conditions': 'Условия на съхранение',
'incompatibilities': 'Несъвместимости',
'no_additional': 'Няма допълнителна информация.',
'control_type': 'Вид контрол',
'engineering': 'Инженерни мерки',
'hand_protection': 'Защита на ръцете',
'eye_protection': 'Защита на очите',
'respiratory': 'Дихателна защита',
'env_exposure': 'Контрол на околната среда',
'abbr': 'Съкращения и акроними',
'abbreviation': 'Съкращение',
'full_form': 'Пълна форма',
'code': 'Код',
'text': 'Текст',
'disclaimer': 'Отказ от отговорност: Информацията в настоящия информационен лист за безопасност е получена от източници, които смятаме за надеждни. Информацията обаче се предоставя без каквато и да е гаранция, изрична или подразбираща се, относно нейната коректност. Условията или методите на работа, съхранение, употреба или обезвреждане на продукта са извън нашия контрол. Ние не поемаме отговорност и изрично отхвърляме отговорност за загуба, щета или разход, произтичащи от или свързани по какъвто и да е начин с работата, съхранението, употребата или обезвреждането на продукта.',
# CLP statements (correct Bulgarian)
'h225': 'Силно запалими течност и пари.',
'h319': 'Предизвиква сериозно дразнене на очите.',
'h336': 'Може да предизвика сънливост или световъртеж.',
'euh066': 'Повтарящата се експозиция може да предизвика изсушаване или напукване на кожата.',
'p210': 'Да се пази от топлина/горещи повърхности/искри/открит пламък/други източници на запалване. Тютюнопушенето забранено.',
'p280': 'Използвайте предпазни ръкавици/предпазно облекло/предпазни очила/предпазна маска за лице.',
'p304_p340': 'ПРИ ВДИШВАНЕ: Изведете лицето на чист въздух и го поставете в позиция, удобна за дишане.',
'p305_p351_p338': 'ПРИ КОНТАКТ С ОЧИТЕ: Промивайте внимателно с вода в продължение на няколко минути. Свалете контактните лещи, ако има такива и ако това може да стане лесно. Продължете с промиването.',
'p337_p313': 'Ако дразненето на очите не премине: Потърсете медицински съвет/помощ.',
'p403_p233': 'Да се съхранява на добре проветриво място. Да се съхранява в плътно затворен съд.',
# First aid text
'fa_general': 'Потърсете медицински съвет/помощ ако не се чувствате добре.',
'fa_inhalation': 'Изведете лицето на чист въздух и го поставете в позиция, удобна за дишане.',
'fa_skin': 'Измийте кожата с вода/вземете душ. Незабавно съблечете цялото замърсено облекло.',
'fa_eye': 'Промивайте внимателно с вода в продължение на няколко минути. Свалете контактните лещи, ако има такива и ако това може да стане лесно. Продължете с промиването.',
'fa_ingestion': 'Изплакнете устата. НЕ предизвиквайте повръщане. Потърсете медицински съвет/помощ ако не се чувствате добре.',
'sym_general': 'Може да предизвика сънливост или световъртеж.',
'sym_skin': 'Повтарящата се експозиция може да предизвика изсушаване или напукване на кожата.',
'sym_eye': 'Дразнене на очите.',
# Transport
'transport_note': 'В съответствие с ADR / RID / IMDG / IATA / ADN',
'transport_mode': 'Транспортен режим',
'un_no': 'UN No',
'shipping_name': 'Точно наим. за превоз',
'class': 'Клас',
'pg': 'Опак. група',
'env': 'Окол. среда',
'adr_details': 'ADR Подробности',
'class_code': 'Класификационен код',
'ltd_qty': 'Ограничени количества',
'exc_qty': 'Освободени количества',
'tunnel': 'Код за рестрикция в тунели',
'kemler': 'Идент. No на опасността (Kemler)',
'transp_cat': 'Транспортна категория',
'transport_bulk': 'Транспортиране в насипно състояние',
'not_applicable_transport': 'Не се прилага.',
# Section 15
'eu_regs': '15.1.1 Регламенти на ЕС',
'national_regs': '15.1.2 Национални разпоредби',
'country': 'Държава',
'regulation': 'Регламент',
'status': 'Статус',
'no_annex': 'Няма ограничения по Приложение XVII на REACH.',
'not_svhc': 'Ethyl acetate не е в списъка на кандидат-веществата (SVHC) на REACH.',
'not_annex': 'Ethyl acetate не е в Приложение XIV на REACH (Списък на разрешените).',
'not_pic': 'Не подлежи на Регламент (ЕС) No 649/2012 (PIC).',
'not_pop': 'Не подлежи на Регламент (ЕС) 2019/1021 (POP).',
'no_csa': 'Не е извършена оценка на химичната безопасност.',
# Section 16
'full_h_text_title': 'Пълен текст на H- и EUH-предупрежденията',
# Other BG-specific
'general_measures': 'Общи мерки',
'personnel_non_emergency': 'Носете препоръчаните ЛПС. Проветрете зоната. Без открит пламък, без искри и без пушене.',
'personnel_emergency': 'Отстранете всички източници на запалване. Евакуирайте ненужния персонал.',
'safe_handling': 'Да се пази от топлина, горещи повърхности, искри, открит пламък и други източници на запалване. Тютюнопушенето забранено. Заземете/еквипотенциално свържете съда и приемното оборудване. Използвайте само инструменти, които не предизвикват искри. Предприемете мерки срещу статично електричество. Да се използва само на открито или на добре проветриво място.',
'hygiene_text': 'Да не се яде, пие и пуши при работа с продукта.',
'storage_text': 'Да се съхранява на добре проветриво място. Да се съхранява на хладно. Да се съхранява в плътно затворен съд.',
'incomp_text': 'Топлина и източници на запалване.',
'eng_controls': 'Осигурете добра вентилация.',
'hand_text': 'Предпазни ръкавици.',
'eye_text': 'Предпазни очила.',
'resp_text': 'При недостатъчна вентилация използвайте подходящи дихателни средства.',
'env_text': 'Да се избягва изпускане в околната среда.',
}
# Romanian
TR['RO'] = {
'lang': 'ro',
'company': 'Societatea',
'sds_title': 'FIȘĂ CU DATE DE SECURITATE',
'product_name': 'Ethyl acetate (Acetat de etil)',
'reg_line': 'Conform Regulamentului (UE) 2020/878 (Anexa II REACH) · Regulamentului (CE) 1272/2008 (CLP), modificat prin (UE) 2024/2865',
'footer_contact': 'Synthesia Grup SRL · TVA RO15163170 · Șos. Dudesti-Pantelimon, 19, București-Sector 3, București, 033091, România · +40 21 255 66 65 · office@synthesia.ro',
'footer_cert': '',
'hdr_title': 'FIȘĂ CU DATE DE SECURITATE',
'hdr_sub': 'Ethyl acetate (Acetat de etil)',
'hdr_ref': 'SDS-ETHYL-ACETATE-REV1-RO · 07/07/2026',
# Section titles
'sec1': 'SECȚIUNEA 1: Identificarea substanței/amestecului și a societății/întreprinderii',
'sec1_1': '1.1 Identificator de produs',
'sec1_2': '1.2 Utilizări relevante identificate ale substanței sau amestecului și utilizări contraindicate',
'sec1_3': '1.3 Detalii privind furnizorul fișei cu date de securitate',
'sec1_4': '1.4 Număr de telefon de urgență',
'sec2': 'SECȚIUNEA 2: Identificarea pericolelor',
'sec2_1': '2.1 Clasificarea substanței sau a amestecului',
'sec2_2': '2.2 Elemente de etichetă',
'sec2_3': '2.3 Alte pericole',
'sec3': 'SECȚIUNEA 3: Compoziție/informații privind componenții',
'sec3_1': '3.1 Substanțe',
'sec3_2': '3.2 Amestecuri',
'sec4': 'SECȚIUNEA 4: Măsuri de prim ajutor',
'sec4_1': '4.1 Descrierea măsurilor de prim ajutor',
'sec4_2': '4.2 Cele mai importante simptome și efecte, atât acute cât și întârziate',
'sec4_3': '4.3 Indicații privind orice asistență medicală imediată și tratamente speciale necesare',
'sec5': 'SECȚIUNEA 5: Măsuri de combatere a incendiilor',
'sec5_1': '5.1 Mijloace de stingere',
'sec5_2': '5.2 Pericole speciale cauzate de substanță sau amestec',
'sec5_3': '5.3 Recomandări pentru pompieri',
'sec6': 'SECȚIUNEA 6: Măsuri de evacuare în caz de scurgeri accidentale',
'sec6_1': '6.1 Precauții personale, echipament de protecție și proceduri de urgență',
'sec6_2': '6.2 Precauții pentru mediul înconjurător',
'sec6_3': '6.3 Metode și materiale pentru izolare și curățare',
'sec6_4': '6.4 Trimitere la alte secțiuni',
'sec7': 'SECȚIUNEA 7: Manipulare și depozitare',
'sec7_1': '7.1 Precauții pentru manipulare în condiții de siguranță',
'sec7_2': '7.2 Condiții de depozitare în condiții de siguranță, inclusiv eventuale incompatibilități',
'sec7_3': '7.3 Utilizare(i) finală( e) specifică( e)',
'sec8': 'SECȚIUNEA 8: Controale ale expunerii/protecție personală',
'sec8_1': '8.1 Parametri de control',
'sec8_2': '8.2 Controale ale expunerii',
'sec9': 'SECȚIUNEA 9: Proprietăți fizice și chimice',
'sec9_1': '9.1 Informații privind proprietățile fizice și chimice de bază',
'sec10': 'SECȚIUNEA 10: Stabilitate și reactivitate',
'sec11': 'SECȚIUNEA 11: Informații toxicologice',
'sec11_1': '11.1 Informații privind clasele de pericol',
'sec11_2': '11.2 Informații privind alte pericole',
'sec12': 'SECȚIUNEA 12: Informații ecologice',
'sec13': 'SECȚIUNEA 13: Considerații privind eliminarea',
'sec13_1': '13.1 Metode de tratare a deșeurilor',
'sec14': 'SECȚIUNEA 14: Informații privind transportul',
'sec15': 'SECȚIUNEA 15: Informații de reglementare',
'sec15_1': '15.1 Reglementări/legislație specifică pentru substanță sau amestec în domeniul securității, sănătății și mediului',
'sec15_2': '15.2 Evaluarea securității chimice',
'sec16': 'SECȚIUNEA 16: Alte informații',
# Label headers
'property': 'Proprietate',
'value': 'Valoare',
'product_form': 'Forma produsului',
'substance': 'Substanță',
'chem_name': 'Denumire chimică',
'index_no': 'Index-No. CE',
'ec_no': 'Nr. CE',
'cas_no': 'Nr. CAS',
'reach_no': 'Nr. înregistrare REACH',
'mol_formula': 'Formulă moleculară',
'use_substance': 'Utilizarea substanței/amestecului',
'restrictions': 'Restricții de utilizare',
'industrial': 'Utilizare industrială',
'no_data': 'Nu există date disponibile',
'field': 'Câmp',
'details': 'Detalii',
'company': 'Societatea',
'address': 'Șos. Dudesti-Pantelimon, 19, București-Sector 3, București, 033091, România',
'vat': 'RO15163170',
'phone': '+40 21 255 66 65',
'email': 'office@synthesia.ro',
'emergency': 'Telefon de urgență',
'classification': 'Clasificare conform Regulamentului (CE) nr. 1272/2008 [CLP], modificat prin (UE) 2024/2865',
'hazard_class': 'Clasa de pericol',
'category': 'Categoria',
'hazard_statement': 'Fraze de pericol',
'full_h_text': 'Textul complet al frazelor H: vezi Secțiunea 16.',
'element': 'Element',
'pictograms': 'Pictograme de pericol',
'signal_word': 'Cuvânt de avertizare',
'danger': 'PERICOL',
'hazard_statements': 'Fraze de pericol',
'precautions': 'Fraze de precauție',
'euh_statements': 'Fraze EUH',
'component': 'Component',
'concentration': 'Concentrație',
'mw_formula': 'Masă moleculară: {} g/mol  |  Formula: {}',
'not_applicable': 'Nu se aplică.',
'route': 'Cale de expunere',
'measures': 'Măsuri',
'general': 'Măsuri generale',
'inhalation': 'După inhalare',
'skin_contact': 'După contactul cu pielea',
'eye_contact': 'După contactul cu ochii',
'ingestion': 'După înghițire',
'symptoms': 'Simptome/efecte',
'description': 'Descriere',
'medical': 'Tratați simptomatic.',
'suitable_media': 'Mijloace de stingere adecvate',
'unsuitable_media': 'Mijloace de stingere neadecvate',
'fire_hazard': 'Pericol de incendiu',
'decomp_products': 'Produși de descompunere periculoși',
'firefighters': 'Nu încercați să acționați fără echipament de protecție adecvat.',
'personnel': 'Personal',
'non_emergency': 'Pentru personalul care nu intervine în situații de urgență',
'emergency_responders': 'Pentru personalul de intervenție în situații de urgență',
'env_precautions': 'Evitați eliberarea în mediu.',
'cleaning_methods': 'Metode de curățare',
'other_info': 'Alte informații',
'ref_sections': 'Vezi măsurile de protecție din Secțiunile 7 și 8.',
'hygiene': 'Măsuri de igienă:',
'storage_conditions': 'Condiții de depozitare',
'incompatibilities': 'Incompatibilități',
'no_additional': 'Nu există informații suplimentare.',
'control_type': 'Tip control',
'engineering': 'Măsuri tehnice',
'hand_protection': 'Protecția mâinilor',
'eye_protection': 'Protecția ochilor',
'respiratory': 'Protecție respiratorie',
'env_exposure': 'Control al expunerii mediului',
'abbr': 'Abrevieri și acronime',
'abbreviation': 'Abreviere',
'full_form': 'Forma completă',
'code': 'Cod',
'text': 'Text',
'disclaimer': 'Declinarea răspunderii: Informațiile din această fișă cu date de securitate au fost obținute din surse pe care le considerăm de încredere. Cu toate acestea, informațiile sunt furnizate fără nicio garanție, expresă sau implicită, privind corectitudinea lor. Condițiile sau metodele de manipulare, depozitare, utilizare sau eliminare a produsului sunt dincolo de controlul nostru. Nu ne asumăm răspunderea și declinăm în mod expres orice răspundere pentru pierderi, daune sau cheltuieli care decurg din sau sunt legate în orice mod de manipularea, depozitarea, utilizarea sau eliminarea produsului.',
# CLP statements will be loaded from lookup table
# First aid text
'fa_general': 'Sunați la un centru de informare toxicologică sau la un medic dacă nu vă simțiți bine.',
'fa_inhalation': 'Transportați persoana la aer liber și mențineți-o într-o poziție confortabilă pentru respirație.',
'fa_skin': 'Clătiți pielea cu apă/faceți duș. Scoateți imediat toată îmbrăcămintea contaminată.',
'fa_eye': 'Clătiți cu atenție cu apă timp de mai multe minute. Scoateți lentilele de contact, dacă este cazul și este ușor de făcut. Continuați să clătiți.',
'fa_ingestion': 'Clătiți gura. NU provocați voma. Sunați la un centru de informare toxicologică sau la un medic dacă nu vă simțiți bine.',
'sym_general': 'Poate provoca somnolență sau amețeli.',
'sym_skin': 'Expunerea repetată poate provoca uscarea sau crăparea pielii.',
'sym_eye': 'Iritarea ochilor.',
# Transport
'transport_note': 'Conform ADR / RID / IMDG / IATA / ADN',
'transport_mode': 'Mod de transport',
'un_no': 'Nr. ONU',
'shipping_name': 'Denumire oficială de transport',
'class': 'Clasa',
'pg': 'Gp. ambal.',
'env': 'Mediu',
'adr_details': 'Detalii ADR',
'class_code': 'Cod de clasificare',
'ltd_qty': 'Cantități limitate',
'exc_qty': 'Cantități exceptate',
'tunnel': 'Cod restricție tunel',
'kemler': 'Nr. de identificare pericol (Kemler)',
'transp_cat': 'Categoria de transport',
'transport_bulk': 'Transport în vrac conform instrumentelor IMO',
'not_applicable_transport': 'Nu se aplică.',
# Section 15
'eu_regs': '15.1.1 Reglementări UE',
'national_regs': '15.1.2 Reglementări naționale',
'country': 'Țara',
'regulation': 'Reglementare',
'status': 'Stare',
'no_annex': 'Nu există restricții conform Anexei XVII REACH.',
'not_svhc': 'Acetatul de etil nu se află pe Lista candidaților (SVHC) REACH.',
'not_annex': 'Acetatul de etil nu se află pe Anexa XIV REACH (Lista de autorizare).',
'not_pic': 'Nu face obiectul Regulamentului (UE) nr. 649/2012 (PIC).',
'not_pop': 'Nu face obiectul Regulamentului (UE) 2019/1021 (POP).',
'no_csa': 'Nu a fost efectuată o evaluare a securității chimice.',
# Section 16
'full_h_text_title': 'Textul complet al frazelor H și EUH',
# Other
'general_measures': 'Măsuri generale',
'personnel_non_emergency': 'Purtați EIP recomandat. Ventilați zona. Fără flăcări deschise, fără scântei, fumatul interzis.',
'personnel_emergency': 'Eliminați toate sursele de aprindere. Evacuați personalul neesențial.',
'safe_handling': 'A se păstra departe de căldură, suprafețe fierbinți, scântei, flăcări deschise și alte surse de aprindere. Fumatul interzis. Legați la pământ/ conectați echipamentul. Utilizați numai unelte care nu produc scântei. Luați măsuri de precauție împotriva descărcărilor electrostatice. A se utiliza numai în aer liber sau în spații bine ventilate.',
'hygiene_text': 'Nu mâncați, nu beți și nu fumați în timpul utilizării produsului.',
'storage_text': 'A se depozita într-un loc bine ventilat. A se păstra la rece. A se păstra recipientul închis ermetic.',
'incomp_text': 'Căldură și surse de aprindere.',
'eng_controls': 'Asigurați o ventilație adecvată.',
'hand_text': 'Mănuși de protecție.',
'eye_text': 'Ochelari de protecție.',
'resp_text': 'În caz de ventilare insuficientă, purtați echipament de protecție respiratorie.',
'env_text': 'Evitați eliberarea în mediu.',
}
# ─── Load CLP translations ───
CLP_PATH = '/home/bachko/msds-eu-translations/clp_statements_multilingual.json'
with open(CLP_PATH, encoding='utf-8') as f:
clp = json.load(f)
def clp_trans(code, lang):
"""Get a CLP statement translation."""
for cat in ('h_statements', 'euh_statements', 'p_statements'):
if code in clp.get(cat, {}):
return clp[cat][code].get(lang, code)
return code
# ─── Build HTML for each language ───
def build_html(lang_code):
t = TR[lang_code]
clp_lang = 'RO' if lang_code == 'RO' else 'BG'
# CLP translations
h225 = t['h225'] if lang_code == 'BG' else 'Lichid și vapori foarte inflamabili.'
h319 = t['h319'] if lang_code == 'BG' else 'Provoacă o iritare gravă a ochilor.'
h336 = t['h336'] if lang_code == 'BG' else 'Poate provoca somnolență sau amețeală.'
euh066 = t['euh066'] if lang_code == 'BG' else 'Expunerea repetată poate provoca uscarea sau crăparea pielii.'
p210 = t['p210'] if lang_code == 'BG' else 'A se păstra departe de surse de căldură/scântei/flăcări deschise/suprafețe încinse. – Fumatul interzis.'
p280 = t['p280'] if lang_code == 'BG' else 'Purtați mănuși de protecție/îmbrăcăminte de protecție/echipament de protecție a ochilor/echipament de protecție a feței.'
if lang_code != 'BG':
p304_p340 = 'ÎN CAZ DE INHALARE: transportați persoana la aer liber și mențineți-o într-o poziție confortabilă pentru respirație.'
p305_p351_p338 = 'ÎN CAZ DE CONTACT CU OCHII: Clătiți cu atenție cu apă timp de mai multe minute. Scoateți lentilele de contact, dacă este cazul și dacă acest lucru se poate face cu ușurință. Continuați să clătiți.'
p337_p313 = 'Dacă iritarea ochilor persistă: consultați medicul.'
p403_p233 = 'A se depozita într-un spațiu bine ventilat. Păstrați recipientul închis etanș.'
else:
p304_p340 = t['p304_p340']
p305_p351_p338 = t['p305_p351_p338']
p337_p313 = t['p337_p313']
p403_p233 = t['p403_p233']
# Abbreviations that shouldn't be translated
abbr_rows = {
'ADR': (lang_code == 'BG' and 'Европейско споразумение за международен превоз на опасни товари по шосе') or 'Acordul european referitor la transportul internațional al mărfurilor periculoase pe șosele',
'CAS': (lang_code == 'BG' and 'Химичен реферативен номер (Chemical Abstract Service)') or 'Număr Chemical Abstract Service',
'CLP': (lang_code == 'BG' and 'Класифициране, етикетиране и опаковане — Регламент (ЕО) Nr. 1272/2008') or 'Clasificare, etichetare și ambalare — Regulamentul (CE) nr. 1272/2008',
'DNEL': (lang_code == 'BG' and 'Изведено ниво без ефект') or 'Nivel derivat fără efect',
'PBT': (lang_code == 'BG' and 'Устойчив, биоакумулиращ, токсичен') or 'Persistent, bioacumulabil, toxic',
'PNEC': (lang_code == 'BG' and 'Предвидена концентрация без ефект') or 'Concentrație previzibilă fără efect',
'REACH': (lang_code == 'BG' and 'Регламент (ЕО) Nr. 1907/2006') or 'Regulamentul (CE) nr. 1907/2006',
'STOT': (lang_code == 'BG' and 'Специфична токсичност за определени органи') or 'Toxicitate specifică asupra organelor țintă',
'vPvB': (lang_code == 'BG' and 'Много устойчив и много биоакумулиращ') or 'Foarte persistent și foarte bioacumulabil',
'WGK': (lang_code == 'BG' and 'Клас на опасност за водата (Германия)') or 'Clasă de pericol pentru apă (Germania)',
}
html = f"""<!DOCTYPE html>
<html lang="{t['lang']}">
<head>
<meta charset="UTF-8">
<style>
@page {{
size: A4;
margin: 2.6cm 1.9cm 2.1cm 1.9cm;
@top-center {{
content: element(header);
}}
@bottom-center {{
content: element(footer);
}}
}}
html, body {{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}}
body {{
font-family: Calibri, Carlito, Arial, sans-serif;
font-size: 10pt;
color: {SECONDARY};
line-height: 1.2;
}}
.running-header {{
position: running(header);
width: 17.2cm;
}}
.hdr-table {{ width: 100%; border-collapse: collapse; }}
.hdr-logo {{ width: 130px; text-align: left; vertical-align: middle; }}
.hdr-logo img {{ height: 1.0cm; }}
.hdr-iso {{ width: 55px; text-align: right; vertical-align: middle; }}
.hdr-iso img {{ height: 1.22cm; }}
.hdr-title {{ vertical-align: middle; text-align: right; }}
.hdr-title .t1 {{ font-size: 9pt; font-weight: bold; color: {PRIMARY}; }}
.hdr-title .t2 {{ font-size: 7.5pt; color: {SECONDARY}; }}
.hdr-title .t3 {{ font-size: 6.5pt; color: {MUTED}; }}
.hdr-rule {{ border: none; border-top: 1pt solid {PRIMARY}; margin: 2px 0 0 0; }}
.running-footer {{
position: running(footer);
width: 17.2cm;
}}
.ftr-rule {{ border: none; border-top: 0.5pt solid {BORDER}; margin: 0 0 2px 0; }}
.ftr-line {{ font-size: 6.5pt; color: {MUTED}; text-align: center; margin: 1px 0; }}
.ftr-line-sm {{ font-size: 6pt; color: {MUTED}; text-align: center; font-style: italic; margin: 1px 0; }}
.ftr-pagenum {{ font-size: 6.5pt; color: {MUTED}; text-align: center; margin: 1px 0 0 0; }}
.ftr-pagenum::after {{ content: "Page " counter(page) " of " counter(pages); }}
h1.doc-title {{
font-size: 16pt; font-weight: bold; color: {PRIMARY};
border-bottom: 2pt solid {PRIMARY}; padding-bottom: 3px; margin: 0 0 8pt 0;
}}
h2.section {{
font-size: 12pt; font-weight: bold; color: {SECONDARY};
border-left: 4pt solid {ACCENT}; padding-left: 6px; margin: 8pt 0 4pt 0;
}}
p {{ margin: 3px 0; }}
table.data {{ width: 100%; border-collapse: collapse; margin: 4px 0; font-size: 9pt; }}
table.data th {{ background-color: {PRIMARY}; color: {WHITE}; font-weight: bold; padding: 3pt 5pt; text-align: left; border: 0.5pt solid {BORDER}; font-size: 9pt; }}
table.data td {{ padding: 3pt 5pt; border: 0.5pt solid {BORDER}; }}
table.data tr:nth-child(even) td {{ background-color: {HIGHLIGHT}; }}
table.data tr:nth-child(odd) td {{ background-color: {WHITE}; }}
table.data td:first-child {{ font-weight: bold; color: {SECONDARY}; }}
table.data thead {{ display: table-header-group; }}
table.layout {{ width: 100%; border-collapse: collapse; margin: 2px 0; }}
table.layout td {{ border: none; padding: 1px 5px 1px 0; vertical-align: top; }}
table.layout td:first-child {{ width: 30%; font-weight: bold; }}
.alert-warning {{ color: {WARNING_AMBER}; font-weight: bold; }}
.meta-line {{ font-size: 7.5pt; color: {MUTED}; text-align: right; border-bottom: 1px solid {BORDER}; padding-bottom: 3px; margin-bottom: 6px; }}
</style>
</head>
<body>
<div class="running-header">
<table class="hdr-table">
<tr>
<td class="hdr-logo"><img src="{logo_b64}" alt="Synthesia"></td>
<td class="hdr-title">
<div class="t1">{t['hdr_title']}</div>
<div class="t2">{t['hdr_sub']}</div>
<div class="t3">{t['hdr_ref']}</div>
</td>
<td class="hdr-iso">{'<img src="' + iso_b64 + '" alt="TÜV Rheinland">' if lang_code == 'BG' else ''}</td>
</tr>
</table>
<hr class="hdr-rule">
</div>
<div class="running-footer">
<hr class="ftr-rule">
<div class="ftr-line">{t['footer_contact']}</div>
{f'<div class="ftr-line-sm">{t["footer_cert"]}</div>' if t['footer_cert'] else ''}
<div class="ftr-pagenum"></div>
</div>
<h1 class="doc-title">{t['sds_title']}<br><span style="font-size:11pt;color:{SECONDARY};">{t['product_name']}</span></h1>
<p class="meta-line">{t['reg_line']}</p>
<h2 class="section">{t['sec1']}</h2>
<h3 class="subsection">{t['sec1_1']}</h3>
<table class="data">
<tr><th>{t['property']}</th><th>{t['value']}</th></tr>
<tr><td>{t['product_form']}</td><td>{t['substance']}</td></tr>
<tr><td>{t['chem_name']}</td><td>Ethyl acetate</td></tr>
<tr><td>{t['index_no']}</td><td>607-022-00-5</td></tr>
<tr><td>{t['ec_no']}</td><td>205-500-4</td></tr>
<tr><td>{t['cas_no']}</td><td>141-78-6</td></tr>
<tr><td>{t['reach_no']}</td><td>01-2119475103-46-XXXX</td></tr>
<tr><td>{t['mol_formula']}</td><td>C₄H₈O₂</td></tr>
</table>
<h3 class="subsection">{t['sec1_2']}</h3>
<table class="layout"><tr><td>{t['use_substance']}</td><td>{t['industrial']}</td></tr>
<tr><td>{t['restrictions']}</td><td>{t['no_data']}</td></tr></table>
<h3 class="subsection">{t['sec1_3']}</h3>
<table class="data">
<tr><th>{t['field']}</th><th>{t['details']}</th></tr>
<tr><td>{t['company']}</td><td>{'Синтезия ООД' if lang_code == 'BG' else 'Synthesia Grup SRL'}</td></tr>
<tr><td>{'Адрес' if lang_code == 'BG' else 'Adresa'}</td><td>{'Тодор Радунчев 9, Кривина 1588, България' if lang_code == 'BG' else 'Șos. Dudesti-Pantelimon, 19, București-Sector 3, București, 033091, România'}</td></tr>
<tr><td>{'ДДС No' if lang_code == 'BG' else 'TVA'}</td><td>{'BG121306542' if lang_code == 'BG' else 'RO15163170'}</td></tr>
<tr><td>{'Телефон' if lang_code == 'BG' else 'Telefon'}</td><td>{'+359 2 974 4968' if lang_code == 'BG' else '+40 21 255 66 65'}</td></tr>
<tr><td>{'Имейл' if lang_code == 'BG' else 'Email'}</td><td>{'office@synthesia.bg' if lang_code == 'BG' else 'office@synthesia.ro'}</td></tr>
</table>
<h3 class="subsection">{t['sec1_4']}</h3>
<table class="layout"><tr><td>{t['emergency']}</td><td>112</td></tr></table>
<h2 class="section">{t['sec2']}</h2>
<h3 class="subsection">{t['sec2_1']}</h3>
<p><b>{t['classification']}</b></p>
<table class="data">
<tr><th>{t['hazard_class']}</th><th>{t['category']}</th><th>{t['hazard_statement']}</th></tr>
<tr><td>{'Запалими течности' if lang_code == 'BG' else 'Lichide inflamabile'}</td><td>{'Категория 2' if lang_code == 'BG' else 'Categoria 2'}</td><td>H225 — {h225}</td></tr>
<tr><td>{'Сериозно увреждане на очите/дразнене на очите' if lang_code == 'BG' else 'Leziuni oculare grave/iritare oculară'}</td><td>{'Категория 2' if lang_code == 'BG' else 'Categoria 2'}</td><td>H319 — {h319}</td></tr>
<tr><td>{'СТОО — еднократна експозиция' if lang_code == 'BG' else 'STOT — expunere unică'}</td><td>{'Категория 3 (Наркоза)' if lang_code == 'BG' else 'Categoria 3 (Narcoză)'}</td><td>H336 — {h336}</td></tr>
</table>
<p>{t['full_h_text']}</p>
<h3 class="subsection">{t['sec2_2']}</h3>
<table class="data">
<tr><th>{t['element']}</th><th>{t['details']}</th></tr>
<tr><td>{t['pictograms']}</td><td>GHS02 (Flame) · GHS07 (Exclamation mark)</td></tr>
<tr><td>{t['signal_word']}</td><td><span class="alert-warning">{t['danger']}</span></td></tr>
<tr><td>{t['hazard_statements']}</td><td>H225 — {h225}<br>H319 — {h319}<br>H336 — {h336}</td></tr>
<tr><td>{t['precautions']}</td><td>{p210}<br>{p280}<br>{p304_p340}<br>{p305_p351_p338}<br>{p337_p313}<br>{p403_p233}</td></tr>
<tr><td>{t['euh_statements']}</td><td>{euh066}</td></tr>
</table>
<h3 class="subsection">{t['sec2_3']}</h3>
<p>{'Не съдържа PBT, vPvB, PMT или vPvM. Не се класифицира като ED. Парите могат да образуват експлозивна смес с въздуха.' if lang_code == 'BG' else 'Nu conține PBT, vPvB, PMT sau vPvM. Nu este clasificat ca disruptor endocrin (ED). Vaporii pot forma amestec exploziv cu aerul.'}</p>
<h2 class="section">{t['sec3']}</h2>
<h3 class="subsection">{t['sec3_1']}</h3>
<table class="data">
<tr><th>{t['component']}</th><th>CAS-No.</th><th>EC-No.</th><th>Index-No.</th><th>Classification</th><th>{t['concentration']}</th></tr>
<tr><td>Ethyl acetate</td><td>141-78-6</td><td>205-500-4</td><td>607-022-00-5</td><td>Flam. Liq. 2; Eye Irrit. 2; STOT SE 3</td><td>&gt; 99.8%</td></tr>
</table>
<p>{t['mw_formula'].format('88.11', 'C₄H₈O₂')}</p>
<h3 class="subsection">{t['sec3_2']}</h3>
<p>{t['not_applicable']}</p>
<h2 class="section">{t['sec4']}</h2>
<h3 class="subsection">{t['sec4_1']}</h3>
<table class="data">
<tr><th>{t['route']}</th><th>{t['measures']}</th></tr>
<tr><td>{t['general']}</td><td>{t['fa_general']}</td></tr>
<tr><td>{t['inhalation']}</td><td>{t['fa_inhalation']}</td></tr>
<tr><td>{t['skin_contact']}</td><td>{t['fa_skin']}</td></tr>
<tr><td>{t['eye_contact']}</td><td>{t['fa_eye']}</td></tr>
<tr><td>{t['ingestion']}</td><td>{t['fa_ingestion']}</td></tr>
</table>
<h3 class="subsection">{t['sec4_2']}</h3>
<table class="data">
<tr><th>{t['symptoms']}</th><th>{t['description']}</th></tr>
<tr><td>{t['general']}</td><td>{t['sym_general']}</td></tr>
<tr><td>{t['skin_contact']}</td><td>{t['sym_skin']}</td></tr>
<tr><td>{t['eye_contact']}</td><td>{t['sym_eye']}</td></tr>
</table>
<h3 class="subsection">{t['sec4_3']}</h3>
<p>{t['medical']}</p>
<h2 class="section">{t['sec5']}</h2>
<h3 class="subsection">{t['sec5_1']}</h3>
<table class="layout"><tr><td>{t['suitable_media']}</td><td>{'Воден спрей. Сух прах. Пяна. Въглероден диоксид.' if lang_code == 'BG' else 'Apă pulverizată. Pulbere uscată. Spumă. Dioxid de carbon.'}</td></tr>
<tr><td>{t['unsuitable_media']}</td><td>{'Водна струя под високо налягане.' if lang_code == 'BG' else 'Jet de apă de mare volum.'}</td></tr></table>
<h3 class="subsection">{t['sec5_2']}</h3>
<table class="layout"><tr><td>{t['fire_hazard']}</td><td>{h225}</td></tr>
<tr><td>{t['decomp_products']}</td><td>{'Токсични димни газове. Въглеродни оксиди.' if lang_code == 'BG' else 'Gaze toxice. Oxizi de carbon.'}</td></tr></table>
<h3 class="subsection">{t['sec5_3']}</h3>
<p>{t['firefighters']}</p>
<h2 class="section">{t['sec6']}</h2>
<h3 class="subsection">{t['sec6_1']}</h3>
<table class="data">
<tr><th>{t['personnel']}</th><th>{t['measures']}</th></tr>
<tr><td>{t['non_emergency']}</td><td>{t['personnel_non_emergency']}</td></tr>
<tr><td>{t['emergency_responders']}</td><td>{t['personnel_emergency']}</td></tr>
</table>
<h3 class="subsection">{t['sec6_2']}</h3>
<p>{t['env_precautions']}</p>
<h3 class="subsection">{t['sec6_3']}</h3>
<table class="layout"><tr><td>{t['cleaning_methods']}</td><td>{'Поемете разлива в абсорбиращ материал.' if lang_code == 'BG' else 'Absorbiți scurgerea în material inert.'}</td></tr>
<tr><td>{t['other_info']}</td><td>{'Изхвърлете остатъците на оторизирано място.' if lang_code == 'BG' else 'Eliminați reziduurile la un site autorizat.'}</td></tr></table>
<h3 class="subsection">{t['sec6_4']}</h3>
<p>{t['ref_sections']}</p>
<h2 class="section">{t['sec7']}</h2>
<h3 class="subsection">{t['sec7_1']}</h3>
<p>{t['safe_handling']}</p>
<p><b>{t['hygiene']}</b> {t['hygiene_text']}</p>
<h3 class="subsection">{t['sec7_2']}</h3>
<table class="layout">
<tr><td>{t['storage_conditions']}</td><td>{t['storage_text']}</td></tr>
<tr><td>{t['incompatibilities']}</td><td>{t['incomp_text']}</td></tr>
</table>
<h3 class="subsection">{t['sec7_3']}</h3>
<p>{t['no_additional']}</p>
<h2 class="section">{t['sec8']}</h2>
<h3 class="subsection">{t['sec8_1']}</h3>
<table class="data"><tr><th colspan="2">{'Граници на професионална експозиция (IOELV)' if lang_code == 'BG' else 'Limite de expunere profesională UE (IOELV)'} — Ethyl acetate</th></tr>
<tr><td>IOELV TWA</td><td>734 mg/m³ (200 ppm)</td></tr>
<tr><td>IOELV STEL</td><td>1,468 mg/m³ (400 ppm)</td></tr>
<tr><td>{'Препратка' if lang_code == 'BG' else 'Referință'}</td><td>{'Директива (ЕС) 2017/164' if lang_code == 'BG' else 'Directiva (UE) 2017/164'}</td></tr></table>
<table class="data"><tr><th colspan="2">DNEL/DMEL — Workers</th></tr>
<tr><td>{'Acute - inhalation' if lang_code == 'BG' else 'Acute - inhalation'}</td><td>1,468 mg/m³</td></tr>
<tr><td>{'Long-term - dermal' if lang_code == 'BG' else 'Long-term - dermal'}</td><td>63 mg/kg bw/day</td></tr>
<tr><td>{'Long-term - inhalation' if lang_code == 'BG' else 'Long-term - inhalation'}</td><td>734 mg/m³</td></tr></table>
<table class="data"><tr><th colspan="2">DNEL/DMEL — General population</th></tr>
<tr><td>{'Acute - inhalation' if lang_code == 'BG' else 'Acute - inhalation'}</td><td>734 mg/m³</td></tr>
<tr><td>{'Long-term - oral' if lang_code == 'BG' else 'Long-term - oral'}</td><td>4.5 mg/kg bw/day</td></tr>
<tr><td>{'Long-term - inhalation' if lang_code == 'BG' else 'Long-term - inhalation'}</td><td>367 mg/m³</td></tr>
<tr><td>{'Long-term - dermal' if lang_code == 'BG' else 'Long-term - dermal'}</td><td>37 mg/kg bw/day</td></tr></table>
<table class="data"><tr><th colspan="2">PNEC</th></tr>
<tr><td>{'Пресна вода' if lang_code == 'BG' else 'Apă dulce'}</td><td>0.24 mg/l</td></tr>
<tr><td>{'Морска вода' if lang_code == 'BG' else 'Apă marină'}</td><td>0.024 mg/l</td></tr>
<tr><td>{'Почва' if lang_code == 'BG' else 'Sol'}</td><td>0.148 mg/kg dwt</td></tr>
<tr><td>{'ПСОВ' if lang_code == 'BG' else 'STP (stație epurare)'}</td><td>650 mg/l</td></tr></table>
<h3 class="subsection">{t['sec8_2']}</h3>
<table class="data">
<tr><th>{t['control_type']}</th><th>{t['measures']}</th></tr>
<tr><td>{t['engineering']}</td><td>{t['eng_controls']}</td></tr>
<tr><td>{t['hand_protection']}</td><td>{t['hand_text']}</td></tr>
<tr><td>{t['eye_protection']}</td><td>{t['eye_text']}</td></tr>
<tr><td>{t['respiratory']}</td><td>{t['resp_text']}</td></tr>
<tr><td>{t['env_exposure']}</td><td>{t['env_text']}</td></tr>
</table>
<h2 class="section">{t['sec9']}</h2>
<h3 class="subsection">{t['sec9_1']}</h3>
<table class="data">
<tr><th>{t['property']}</th><th>{t['value']}</th></tr>
<tr><td>{'Състояние' if lang_code == 'BG' else 'Stare fizică'}</td><td>{'Прозрачна течност' if lang_code == 'BG' else 'Lichid limpede'}</td></tr>
<tr><td>{'Цвят / Мирис' if lang_code == 'BG' else 'Culoare / Miros'}</td><td>{'Безцветен / Плодов' if lang_code == 'BG' else 'Incolor / Fructat'}</td></tr>
<tr><td>{'Точка на топене' if lang_code == 'BG' else 'Punct de topire'}</td><td>-84 °C</td></tr>
<tr><td>{'Точка на кипене' if lang_code == 'BG' else 'Punct de fierbere'}</td><td>76.5 – 77.5 °C</td></tr>
<tr><td>{'Точка на запалване' if lang_code == 'BG' else 'Punct de aprindere'}</td><td>-4 °C</td></tr>
<tr><td>{'Самозапалване' if lang_code == 'BG' else 'Auto-aprindere'}</td><td>426 °C</td></tr>
<tr><td>{'Граници на запалимост' if lang_code == 'BG' else 'Limite de inflamabilitate'}</td><td>2 – 11.5 vol %</td></tr>
<tr><td>{'Налягане на парите' if lang_code == 'BG' else 'Presiune de vapori'}</td><td>73 mm Hg (20 °C)</td></tr>
<tr><td>{'Плътност на парите' if lang_code == 'BG' else 'Densitate de vapori'}</td><td>3.04 (Air = 1)</td></tr>
<tr><td>{'Плътност' if lang_code == 'BG' else 'Densitate'}</td><td>0.902 g/cm³ (20 °C)</td></tr>
<tr><td>{'Разтворимост (вода)' if lang_code == 'BG' else 'Solubilitate (apă)'}</td><td>8 g/100 ml (25 °C)</td></tr>
<tr><td>{'Log Pow' if lang_code == 'BG' else 'Log Pow'}</td><td>0.73</td></tr>
<tr><td>{'Вискозитет' if lang_code == 'BG' else 'Vâscozitate'}</td><td>0.45 mPa·s (20 °C)</td></tr>
</table>
<h2 class="section">{t['sec10']}</h2>
<h3 class="subsection">{'10.1 Реактивоспособност' if lang_code == 'BG' else '10.1 Reactivitate'}</h3><p>{h225}</p>
<h3 class="subsection">{'10.2 Химична стабилност' if lang_code == 'BG' else '10.2 Stabilitate chimică'}</h3><p>{'Стабилен при нормални условия.' if lang_code == 'BG' else 'Stabil în condiții normale.'}</p>
<h3 class="subsection">{'10.3 Опасни реакции' if lang_code == 'BG' else '10.3 Reacții periculoase'}</h3><p>{'Няма известни опасни реакции.' if lang_code == 'BG' else 'Nu se cunosc reacții periculoase.'}</p>
<h3 class="subsection">{'10.4 Условия, които трябва да се избягват' if lang_code == 'BG' else '10.4 Condiții de evitat'}</h3><p>{'Избягвайте контакт с горещи повърхности. Без пламъци, без искри.' if lang_code == 'BG' else 'Evitați contactul cu suprafețe fierbinți. Fără flăcări, fără scântei.'}</p>
<h3 class="subsection">{'10.5 Несъвместими материали' if lang_code == 'BG' else '10.5 Materiale incompatibile'}</h3><p>{t['no_additional']}</p>
<h3 class="subsection">{'10.6 Опасни продукти на разпадане' if lang_code == 'BG' else '10.6 Produși de descompunere periculoși'}</h3><p>{'Не се образуват при нормални условия.' if lang_code == 'BG' else 'Nu se produc în condiții normale.'}</p>
<h2 class="section">{t['sec11']}</h2>
<h3 class="subsection">{t['sec11_1']}</h3>
<table class="data">
<tr><th>{'Крайна точка' if lang_code == 'BG' else 'Punct final'}</th><th>{'Класификация' if lang_code == 'BG' else 'Clasificare'}</th><th>Data</th></tr>
<tr><td>{'Остра токсичност' if lang_code == 'BG' else 'Toxicitate acută'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td>LD50 oral: 5,620 mg/kg bw (rabbit)</td></tr>
<tr><td>{'Корозия/дразнене на кожата' if lang_code == 'BG' else 'Corodarea/iritarea pielii'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td></td></tr>
<tr><td>{'Сериозно увреждане/дразнене на очите' if lang_code == 'BG' else 'Leziuni oculare grave/iritare oculară'}</td><td><b>{h319}</b></td><td></td></tr>
<tr><td>{'Респираторна или кожна сенсибилизация' if lang_code == 'BG' else 'Sensibilizare respiratorie/cutanată'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td></td></tr>
<tr><td>{'Мутагенност на зародишни клетки' if lang_code == 'BG' else 'Mutagenitate asupra celulelor germinale'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td></td></tr>
<tr><td>{'Канцерогенност' if lang_code == 'BG' else 'Cancerigenitate'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td></td></tr>
<tr><td>{'Токсичност за репродукцията' if lang_code == 'BG' else 'Toxicitate pentru reproducere'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td></td></tr>
<tr><td>{'СТОО — еднократна експозиция' if lang_code == 'BG' else 'STOT — expunere unică'}</td><td>{'Категория 3 (Наркоза)' if lang_code == 'BG' else 'Categoria 3 (Narcoză)'}</td><td>{h336}</td></tr>
<tr><td>{'СТОО — многократна експозиция' if lang_code == 'BG' else 'STOT — expunere repetată'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td>NOAEL 900 mg/kg bw (90d rat)</td></tr>
<tr><td>{'Опасност при аспирация' if lang_code == 'BG' else 'Pericol prin aspirare'}</td><td>{'Не се класифицира' if lang_code == 'BG' else 'Neclasificat'}</td><td></td></tr>
</table>
<h3 class="subsection">{t['sec11_2']}</h3>
<p>{'Не се класифицира като ендокринен нарушител (ED).' if lang_code == 'BG' else 'Nu este clasificat ca disruptor endocrin (ED).'}</p>
<h2 class="section">{t['sec12']}</h2>
<h3 class="subsection">{'12.1 Токсичност' if lang_code == 'BG' else '12.1 Toxicitate'}</h3>
<p>{'Продуктът не се счита за вреден за водните организми.' if lang_code == 'BG' else 'Produsul nu este considerat periculos pentru organismele acvatice.'}</p>
<table class="data">
<tr><th>Endpoint</th><th>{'Стойност' if lang_code == 'BG' else 'Valoare'}</th><th>{'Вид' if lang_code == 'BG' else 'Specie'}</th></tr>
<tr><td>LC50 (fish, 96h)</td><td>230 mg/l</td><td>Pimephales promelas</td></tr>
<tr><td>EC50 (daphnia, 48h)</td><td>720 mg/l</td><td>Daphnia magna</td></tr>
<tr><td>EC50 (algae, 72h)</td><td>3,300 mg/l</td><td></td></tr>
</table>
<h3 class="subsection">{'12.2 Устойчивост и разградимост' if lang_code == 'BG' else '12.2 Persistență și degradabilitate'}</h3><p>{'Лесно биоразградим — 100% след 28 дни.' if lang_code == 'BG' else 'Ușor biodegradabil — 100% după 28 de zile.'}</p>
<h3 class="subsection">{'12.3 Биоакумулиращ потенциал' if lang_code == 'BG' else '12.3 Potențial de bioacumulare'}</h3><table class="layout"><tr><td>{'Log Pow' if lang_code == 'BG' else 'Log Pow'}</td><td>0.73 {'(нисък)' if lang_code == 'BG' else '(scăzut)'}</td></tr></table>
<h3 class="subsection">{'12.4 Мобилност в почвата' if lang_code == 'BG' else '12.4 Mobilitate în sol'}</h3><p>{'Ниска мобилност.' if lang_code == 'BG' else 'Mobilitate scăzută.'}</p>
<h3 class="subsection">{'12.5 PBT и vPvB оценка' if lang_code == 'BG' else '12.5 Evaluare PBT și vPvB'}</h3><p>{'Не се класифицира като PBT или vPvB.' if lang_code == 'BG' else 'Nu este clasificat ca PBT sau vPvB.'}</p>
<h3 class="subsection">{'12.6 Ендокринно нарушаващи свойства' if lang_code == 'BG' else '12.6 Proprietăți de disruptor endocrin'}</h3><p>{'Не се класифицира като ED.' if lang_code == 'BG' else 'Nu este clasificat ca disruptor endocrin.'}</p>
<h3 class="subsection">{'12.7 Други неблагоприятни ефекти' if lang_code == 'BG' else '12.7 Alte efecte adverse'}</h3><p>{t['no_additional']}</p>
<h2 class="section">{t['sec13']}</h2>
<h3 class="subsection">{t['sec13_1']}</h3>
<table class="layout">
<tr><td>{t['cleaning_methods']}</td><td>{'Изхвърлете съгласно инструкциите на лицензиран събирач.' if lang_code == 'BG' else 'Eliminați conform instrucțiunilor colectorului autorizat.'}</td></tr>
<tr><td>{'Обезвреждане на опаковките' if lang_code == 'BG' else 'Eliminarea ambalajelor'}</td><td>{'Изхвърлете в пункт за опасни отпадъци.' if lang_code == 'BG' else 'Eliminați la un punct de colectare a deșeurilor periculoase.'}</td></tr>
<tr><td>{t['other_info']}</td><td>{'Не използвайте повторно празни съдове.' if lang_code == 'BG' else 'Nu reutilizați recipientele goale.'}</td></tr>
</table>
<h2 class="section">{t['sec14']}</h2>
<p>{t['transport_note']}</p>
<table class="data">
<tr><th>{t['transport_mode']}</th><th>{t['un_no']}</th><th>{t['shipping_name']}</th><th>{t['class']}</th><th>{t['pg']}</th><th>{t['env']}</th></tr>
<tr><td>ADR (road)</td><td>1173</td><td>ETHYL ACETATE, 3, II, (D/E)</td><td>3</td><td>II</td><td>{'Не' if lang_code == 'BG' else 'Nu'}</td></tr>
<tr><td>IMDG (sea)</td><td>1173</td><td>ETHYL ACETATE, 3, II</td><td>3</td><td>II</td><td>{'Не' if lang_code == 'BG' else 'Nu'}</td></tr>
<tr><td>IATA (air)</td><td>1173</td><td>Ethyl acetate, 3, II</td><td>3</td><td>II</td><td>{'Не' if lang_code == 'BG' else 'Nu'}</td></tr>
</table>
<table class="data">
<tr><th colspan="2">{t['adr_details']}</th></tr>
<tr><td>{t['class_code']}</td><td>F1</td></tr>
<tr><td>{t['ltd_qty']}</td><td>1 L</td></tr>
<tr><td>{t['exc_qty']}</td><td>E2</td></tr>
<tr><td>{t['tunnel']}</td><td>D/E</td></tr>
<tr><td>{t['kemler']}</td><td>33</td></tr>
<tr><td>{t['transp_cat']}</td><td>2</td></tr>
</table>
<h3 class="subsection">14.7 {t['transport_bulk']}</h3>
<p>{t['not_applicable_transport']}</p>
<h2 class="section">{t['sec15']}</h2>
<h3 class="subsection">{t['sec15_1']}</h3>
<h3 class="subsection">{t['eu_regs']}</h3>
<ul>
<li>{t['no_annex']}</li>
<li>{t['not_svhc']}</li>
<li>{t['not_annex']}</li>
<li>{t['not_pic']}</li>
<li>{t['not_pop']}</li>
</ul>
<h3 class="subsection">{t['national_regs']}</h3>
<table class="data">
<tr><th>{t['country']}</th><th>{t['regulation']}</th><th>{t['status']}</th></tr>
<tr><td>Germany</td><td>{'Клас на опасност за водата (WGK)' if lang_code == 'BG' else 'Clasă de pericol pentru apă (WGK)'}</td><td>WGK 1</td></tr>
</table>
<h3 class="subsection">{t['sec15_2']}</h3>
<p>{t['no_csa']}</p>
<h2 class="section">{t['sec16']}</h2>
<h3 class="subsection">{t['abbr']}</h3>
<table class="data">
<tr><th>{t['abbreviation']}</th><th>{t['full_form']}</th></tr>
"""
for abbr, full in abbr_rows.items():
html += f" <tr><td>{abbr}</td><td>{full}</td></tr>\n"
html += f"""</table>
<h3 class="subsection">{t['full_h_text_title']}</h3>
<table class="data">
<tr><th>{t['code']}</th><th>{t['text']}</th></tr>
<tr><td>H225</td><td>{h225}</td></tr>
<tr><td>H319</td><td>{h319}</td></tr>
<tr><td>H336</td><td>{h336}</td></tr>
<tr><td>EUH066</td><td>{euh066}</td></tr>
</table>
<br>
<p style="font-size: 8pt; color: {MUTED}; border-top: 1pt solid {BORDER}; padding-top: 5pt;">
<b>{t['disclaimer']}</b>
</p>
</body>
</html>"""
return html
# ─── Add thead/tbody via regex ───
def add_thead_tbody(html_str):
table_pattern = re.compile(r'(<table class="data">)(.*?)(</table>)', re.DOTALL)
def process_table(match):
open_tag, body, close_tag = match.group(1), match.group(2), match.group(3)
rows = re.findall(r'<tr>.*?</tr>', body, re.DOTALL)
if not rows:
return match.group(0)
header_rows = []
data_rows = []
for row in rows:
if '<th' in row and not data_rows:
header_rows.append(row)
else:
data_rows.append(row)
if not header_rows:
return match.group(0)
new_body = '<thead>' + ''.join(header_rows) + '</thead><tbody>' + ''.join(data_rows) + '</tbody>'
return open_tag + new_body + close_tag
return table_pattern.sub(process_table, html_str)
# ─── Generate both languages ───
OUT_DIR = '/home/bachko/msds-tds/output'
os.makedirs(OUT_DIR, exist_ok=True)
for lang, suffix in [('BG', 'BG'), ('RO', 'RO')]:
raw_html = build_html(lang)
final_html = add_thead_tbody(raw_html)
html_path = os.path.join(OUT_DIR, f'sds-ethyl-acetate-{suffix.lower()}.html')
pdf_path = os.path.join(OUT_DIR, f'SDS_Ethyl_Acetate_REV1_{suffix}.pdf')
with open(html_path, 'w', encoding='utf-8') as f:
f.write(final_html)
HTML(string=final_html).write_pdf(pdf_path)
print(f"✅ {suffix}: {pdf_path}")