Пн-Пт: 9:00-19:00 | Сб-Вс: 10:00-18:00 | Заявки принимаем онлайн круглосуточно

Перевод деклараций

Перевод таможенных, налоговых деклараций и деклараций о соответствии от 600 руб./стр. Китайские, арабские, турецкие, английские и другие декларации — носители языка в штате. Специализация — ВЭД, международная торговля, техническое регулирование. Нотариальное заверение за 2 часа. Договор.

+7 (926) 158-66-56
Китайский и арабский
От 600₽/стр.
Нотариус рядом с метро
Все виды деклараций
Готово за 3 часа
Ответим за 30 минут

Нажимая кнопку, вы соглашаетесь с политикой конфиденциальности

Перевод деклараций

Стоимость

Английский / Немецкий
от 600₽

ДТ, CMR, налоговые декларации

Французский / Испанский
от 850₽

Таможенные декларации

Китайский
от 1 200₽

Декларации из КНР, Тайваня, Гонконга

Арабский
от 1 200₽

ОАЭ, Саудовская Аравия, Египет

Турецкий
от 950₽

Таможенные декларации из Турции

+ Нотариальное заверение
от +1200₽

За документ, заверяем в офисе

Преимущества

  • Бесплатная курьерская доставка по Москве
  • Перевод выполняет человек, а не нейросеть
  • Фиксированная цена — без доплат по ходу работы

Что входит в перевод деклараций

Перевод деклараций — передача содержания таможенных, налоговых или технических документов на иностранный язык с полным сохранением структуры, кодов, ссылок на нормативные акты и числовых данных. Переводчики знают формат ДТ (декларация на товары), коды ТН ВЭД ЕАЭС, терминологию таможенного регулирования, международные стандарты (HS codes, Customs Tariff).

Виды деклараций для перевода

Работаем со всеми типами деклараций, востребованными в ВЭД и корпоративной практике:

  • Таможенные декларации (ДТ) — декларация на товары, транзитная декларация, статистическая форма
  • CMR, TIR, коносаменты — транспортные документы для международных перевозок
  • Налоговые декларации — 3-НДФЛ, декларации по НДС, налогу на прибыль, имущественные декларации
  • Декларации о соответствии (ТР ТС / ТР ЕАЭС) — техническое регулирование
  • Декларации таможенной стоимости (ДТС-1, ДТС-2) — определение стоимости товаров
  • Декларации происхождения товара — сертификат СТ-1, EUR.1, Form A
  • Декларации о доходах — для банков, консульств, финансовых регуляторов

Перевод китайских деклараций

Китай — крупнейший торговый партнёр России. Ежедневно переводим десятки китайских таможенных деклараций для импортёров. Типичные документы:

  • 报关单 (Бао гуань дань) — таможенная декларация КНР. Содержит HS-коды, стоимость, условия поставки. Переводим с сохранением иероглифов и латинских обозначений
  • Декларации соответствия CCC (China Compulsory Certification) — сертификаты обязательной сертификации китайских товаров
  • Инвойсы и упаковочные листы на китайском — сопроводительные документы к декларациям
  • Декларации происхождения товара — Form A, Form E (АСЕАН), сертификаты для льготных таможенных ставок
  • Санитарные и фитосанитарные декларации — для продовольствия, косметики, медицинских изделий из КНР

В штате — переводчики-носители китайского языка с опытом работы в таможенном оформлении. Знают специфику упрощённых и традиционных иероглифов, используют терминологические базы ВЭД Китай–Россия. Стоимость — от 1200₽/стр.

Перевод арабских деклараций

Торговля с ОАЭ, Саудовской Аравией, Египтом и другими арабскими странами растёт. Переводим арабские таможенные и коммерческие декларации:

  • البيان الجمركي (Аль-баян аль-джумруки) — таможенная декларация. В арабских странах особый формат: вязь справа налево, числа — арабскими и индийскими цифрами
  • Декларации соответствия SASO / ESMA — стандарты Саудовской Аравии и ОАЭ для импорта товаров
  • Сертификаты Халяль — для продовольственных товаров и косметики
  • Коммерческие инвойсы — с легализацией через посольство или ТПП
  • Налоговые декларации — VAT-декларации ОАЭ, Саудовской Аравии (Vision 2030)

Переводчики владеют Modern Standard Arabic и знают диалектные особенности документов из разных стран. Учитываем требования арабских таможенных служб к оформлению. Стоимость — от 1200₽/стр.

Другие популярные языковые направления

Турецкие декларации

Gümrük beyannamesi — турецкие таможенные декларации. Турция — один из ведущих торговых партнёров РФ: текстиль, продовольствие, строительные материалы, автозапчасти. Переводим ДТ, инвойсы, A.TR (преференциальный сертификат), EUR.1. От 950₽/стр.

Английские декларации

Customs Declaration, Bill of Entry, Single Administrative Document (SAD). Переводим таможенные декларации из Великобритании, США, Австралии, Индии. Знаем различия в форматах и терминологии. От 600₽/стр.

Немецкие декларации

Zollanmeldung, Einfuhranmeldung — немецкие таможенные декларации. Германия — ключевой партнёр в ЕС: оборудование, автомобили, химия. Переводим ДТ, EUR.1, T1/T2 (транзит). От 600₽/стр.

Корейские и японские

수입신고서 (корейская ДТ), 輸入申告書 (японская ДТ). Импорт электроники, автомобилей, оборудования. Иероглифические системы требуют специализированных переводчиков. Уточняйте стоимость.

Процесс работы с декларациями

Получаем скан декларации, определяем тип и языковую пару, назначаем переводчика с опытом в таможенном или налоговом праве. Работаем в SDL Trados с терминологическими базами ВЭД (коды ТН ВЭД, ИНКОТЕРМС, таможенная терминология). Для постоянных клиентов формируем TM-базу — повторяющиеся блоки переводятся автоматически, что ускоряет процесс и снижает стоимость.

Стоимость и сроки

Перевод деклараций: от 600₽/стр. (английский), от 600₽/стр. (немецкий), от 1200₽/стр. (китайский), от 1200₽/стр. (арабский). Одна декларация (2–4 стр.) готова за 2–4 часа. Пакеты от 10 деклараций — 1–2 рабочих дня. Скидки при регулярных заказах. Нотариальное заверение — +1200₽/документ.

Срочный перевод для таможни

Груз на таможне, а перевод декларации нужен срочно? Выполняем срочные переводы таможенных документов за 2–3 часа. Отправляем сканированную копию по email немедленно, оригинал — курьером. Работаем с таможенными брокерами и логистическими компаниями по всей России.

Закажите перевод деклараций в бюро «Универсал». Смежные услуги: юридический перевод, перевод сертификатов, перевод контрактов, перевод с китайского, перевод с арабского.

Рассчитайте стоимость перевода

Узнайте точную цену вашего заказа за 30 секунд

× 1800 знаков

1 страница = 1800 знаков с пробелами

Стоимость перевода:
1 500 ₽
Минимальный заказ: 1 500 ₽
Прикрепить файлы
Перевод 600 ₽
Итого 1 500 ₽

Расчёт знаков ведётся по переведённому тексту. Для более точного расчёта отправьте нам заявку.

Менеджер ответит вам в течение 30 минут.

Оформление заявки

Направление:
Объем перевода (в страницах)
Предварительная стоимость:
Я не робот
Нажимая кнопку, вы соглашаетесь с политикой конфиденциальности.
Заявка успешно отправлена!
В ближайшее время с вами свяжется наш менеджер для уточнения деталей заказа.
// в названии услуги или языка разорвала бы тег и открыла инъекцию. const pricesData = {"description":"Тарифы на переводы. Цены указаны за одну переводческую страницу (1800 знаков с пробелами)","currency":"RUB","currency_symbol":"₽","unit":"страница","unit_size":"1800 знаков с пробелами","min_order":1500,"languages":[{"id":"ru","name":"Русский","flag":"🇷🇺","group":0,"price_from_foreign":0,"price_to_foreign":0},{"id":"en","name":"Английский","flag":"🇺🇸","group":1,"price_from_foreign":600,"price_to_foreign":650},{"id":"de","name":"Немецкий","flag":"🇩🇪","group":1,"price_from_foreign":600,"price_to_foreign":650},{"id":"uk","name":"Украинский","flag":"🇺🇦","group":5,"price_from_foreign":550,"price_to_foreign":600},{"id":"be","name":"Белорусский","flag":"🇧🇾","group":5,"price_from_foreign":550,"price_to_foreign":600},{"id":"fr","name":"Французский","flag":"🇫🇷","group":2,"price_from_foreign":850,"price_to_foreign":900},{"id":"es","name":"Испанский","flag":"🇪🇸","group":2,"price_from_foreign":850,"price_to_foreign":900},{"id":"it","name":"Итальянский","flag":"🇮🇹","group":2,"price_from_foreign":850,"price_to_foreign":900},{"id":"pl","name":"Польский","flag":"🇵🇱","group":2,"price_from_foreign":850,"price_to_foreign":900},{"id":"el","name":"Греческий","flag":"🇬🇷","group":3,"price_from_foreign":850,"price_to_foreign":900},{"id":"pt","name":"Португальский","flag":"🇵🇹","group":3,"price_from_foreign":850,"price_to_foreign":900},{"id":"hu","name":"Венгерский","flag":"🇭🇺","group":3,"price_from_foreign":850,"price_to_foreign":900},{"id":"mo","name":"Молдавский","flag":"🇲🇩","group":3,"price_from_foreign":850,"price_to_foreign":900},{"id":"tk","name":"Туркменский","flag":"🇹🇲","group":3,"price_from_foreign":850,"price_to_foreign":900},{"id":"cs","name":"Чешский","flag":"🇨🇿","group":3,"price_from_foreign":850,"price_to_foreign":900},{"id":"ka","name":"Грузинский","flag":"🇬🇪","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"bg","name":"Болгарский","flag":"🇧🇬","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"lv","name":"Латышский","flag":"🇱🇻","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"lt","name":"Литовский","flag":"🇱🇹","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"no","name":"Норвежский","flag":"🇳🇴","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"nl","name":"Нидерландский","flag":"🇳🇱","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"sv","name":"Шведский","flag":"🇸🇪","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"ro","name":"Румынский","flag":"🇷🇴","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"sr","name":"Сербский","flag":"🇷🇸","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"sk","name":"Словацкий","flag":"🇸🇰","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"sl","name":"Словенский","flag":"🇸🇮","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"fi","name":"Финский","flag":"🇫🇮","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"az","name":"Азербайджанский","flag":"🇦🇿","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"hy","name":"Армянский","flag":"🇦🇲","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"da","name":"Датский","flag":"🇩🇰","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"kk","name":"Казахский","flag":"🇰🇿","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"ky","name":"Киргизский","flag":"🇰🇬","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"tg","name":"Таджикский","flag":"🇹🇯","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"tr","name":"Турецкий","flag":"🇹🇷","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"hr","name":"Хорватский","flag":"🇭🇷","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"uz","name":"Узбекский","flag":"🇺🇿","group":6,"price_from_foreign":950,"price_to_foreign":1000},{"id":"ar","name":"Арабский","flag":"🇸🇦","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"vi","name":"Вьетнамский","flag":"🇻🇳","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"he","name":"Иврит","flag":"🇮🇱","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"id","name":"Индонезийский","flag":"🇮🇩","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"th","name":"Тайский","flag":"🇹🇭","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"zh","name":"Китайский","flag":"🇨🇳","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"ko","name":"Корейский","flag":"🇰🇷","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"fa","name":"Персидский","flag":"🇮🇷","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"hi","name":"Хинди","flag":"🇮🇳","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"ja","name":"Японский","flag":"🇯🇵","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"et","name":"Эстонский","flag":"🇪🇪","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"sq","name":"Албанский","flag":"🇦🇱","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"mn","name":"Монгольский","flag":"🇲🇳","group":4,"price_from_foreign":950,"price_to_foreign":1000},{"id":"ms","name":"Малайский","flag":"🇲🇾","group":7,"price_from_foreign":1200,"price_to_foreign":1250},{"id":"ca","name":"Каталанский","flag":"🇪🇸","group":4,"price_from_foreign":950,"price_to_foreign":1000}],"notarial_services":[{"id":"notarial_translation","name":"Нотариальное заверение перевода","price":1200,"unit":"документ"},{"id":"notarial_copy","name":"Нотариальное заверение копии документа","price":350,"unit":"страница"},{"id":"identity_certification","name":"Удостоверение тождественности документа","price":800,"unit":"страница"},{"id":"translation_plus_identity","name":"Перевод + удостоверение тождественности","price":3000,"unit":"комплект"},{"id":"bureau_stamp","name":"Заверение печатью бюро","price":300,"unit":"документ"},{"id":"passport_notarial","name":"Перевод паспорта с нотариальным заверением","price":2500,"unit":"документ"},{"id":"passport_notarial_urgent","name":"Перевод паспорта с нотариальным заверением (срочно, день в день)","price":4000,"unit":"документ"},{"id":"consular_legalization","name":"Консульская легализация (МИД + консульство)","price":10000,"unit":"документ"},{"id":"tpp_certification","name":"Заверение в ТПП РФ","price":5000,"unit":"документ"},{"id":"mid_legalization","name":"Легализация в МИД РФ","price":5000,"unit":"документ"}],"oral_translation":[{"id":"consecutive_en_de","name":"Последовательный перевод (английский, немецкий)","price":5000,"unit":"час","min_hours":3},{"id":"consecutive_es_it_fr","name":"Последовательный перевод (испанский, итальянский, французский)","price":7000,"unit":"час","min_hours":3},{"id":"consecutive_zh_ar","name":"Последовательный перевод (китайский, арабский)","price":8000,"unit":"час","min_hours":3},{"id":"simultaneous","name":"Синхронный перевод","price":10000,"unit":"час","min_hours":4,"price_note":"от"}],"oral_online_discount":2000,"oral_per_person_discount":1000,"additional_services":[{"id":"translator_signature","name":"Заверение подписи переводчика + печать бюро переводов","price":300,"unit":"документ","description":"Заверение подписи переводчика и печать бюро переводов"},{"id":"notarial","name":"Нотариальное заверение","price":1200,"unit":"документ","description":"Заверение перевода у нотариуса"},{"id":"apostille","name":"Апостиль","price":5000,"unit":"документ","description":"Проставление апостиля, срок 7 дней"},{"id":"layout","name":"Верстка документа (сложная)","price":500,"unit":"полоса","description":"Сохранение форматирования, 1-2 дня"},{"id":"audio_video","name":"Перевод аудио\/видео","price":500,"unit":"минута","description":"Перевод аудио- и видеоматериалов"},{"id":"delivery_moscow","name":"Курьерская доставка (в пределах МКАД)","price":0,"unit":"заказ","description":"Бесплатная доставка в день готовности"}],"discounts":[{"from_pages":50,"to_pages":80,"percent":3},{"from_pages":80,"to_pages":100,"percent":5},{"from_pages":100,"to_pages":150,"percent":7},{"from_pages":150,"to_pages":null,"percent":10}],"notarial_bulk_discount":{"from_documents":8,"price_per_document":1000,"note":"При заверении от 8 документов"},"government_fees":{"apostille_gosposhlina":2500},"notes":["Цены действительны на текущий период","Минимальный заказ — 1 500 ₽","Точный расчет после анализа документа","Для постоянных клиентов действуют скидки","Цены могут отличаться для редких языков"]}; const minOrder = pricesData.min_order || 1500; // i18n строки для калькулятора const calcI18nUI = { submitText: '\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C\u0020\u0437\u0430\u044F\u0432\u043A\u0443', sending: '\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430...', errorGeneric: '\u041F\u0440\u043E\u0438\u0437\u043E\u0448\u043B\u0430\u0020\u043E\u0448\u0438\u0431\u043A\u0430\u0020\u043F\u0440\u0438\u0020\u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0435.\u0020\u041F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435\u0020\u043F\u043E\u0437\u0436\u0435\u0020\u0438\u043B\u0438\u0020\u043F\u043E\u0437\u0432\u043E\u043D\u0438\u0442\u0435\u0020\u043D\u0430\u043C.', errorNetwork: '\u041E\u0448\u0438\u0431\u043A\u0430\u0020\u0441\u0435\u0442\u0438.\u0020\u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435\u0020\u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u002D\u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435\u0020\u0438\u0020\u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435\u0020\u0441\u043D\u043E\u0432\u0430.', fileRequired: '', quoteLeadSubmit: "Отправить", quoteLeadInvalidEmail: "Укажите корректный email", rejectedTitle: "Заявка принята, но часть файлов не загрузилась (%d):", rejectedCta: "Пришлите их повторно в другом формате (PDF, DOCX, JPG) или на %s — менеджер уже видит вашу заявку.", tooManyFiles: "Можно прикрепить не более %d файлов за раз. Остальные пришлите отдельным сообщением или архивом (ZIP).", }; const calcI18n = { pages: '\u0441\u0442\u0440.', times: '\u00D7', discount: '\u0421\u043A\u0438\u0434\u043A\u0430', docs: '\u0434\u043E\u043A.', addons: { 'translator_signature': '\u0417\u0430\u0432\u0435\u0440\u0435\u043D\u0438\u0435\u0020\u043F\u043E\u0434\u043F\u0438\u0441\u0438\u0020\u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0447\u0438\u043A\u0430\u0020\u002B\u0020\u043F\u0435\u0447\u0430\u0442\u044C\u0020\u0431\u044E\u0440\u043E', 'notarial': '\u041D\u043E\u0442\u0430\u0440\u0438\u0430\u043B\u044C\u043D\u043E\u0435\u0020\u0437\u0430\u0432\u0435\u0440\u0435\u043D\u0438\u0435', 'apostille': '\u0410\u043F\u043E\u0441\u0442\u0438\u043B\u044C', 'layout': '\u0412\u0435\u0440\u0441\u0442\u043A\u0430\u0020\u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0020\u0028\u0441\u043B\u043E\u0436\u043D\u0430\u044F\u0029', 'audio_video': '\u041F\u0435\u0440\u0435\u0432\u043E\u0434\u0020\u0430\u0443\u0434\u0438\u043E\/\u0432\u0438\u0434\u0435\u043E', 'delivery_moscow': 'calculator.addon_delivery_moscow' }, langNames: { 'ru': '\u0420\u0443\u0441\u0441\u043A\u0438\u0439', 'en': '\u0410\u043D\u0433\u043B\u0438\u0439\u0441\u043A\u0438\u0439', 'de': '\u041D\u0435\u043C\u0435\u0446\u043A\u0438\u0439', 'uk': '\u0423\u043A\u0440\u0430\u0438\u043D\u0441\u043A\u0438\u0439', 'be': '\u0411\u0435\u043B\u043E\u0440\u0443\u0441\u0441\u043A\u0438\u0439', 'fr': '\u0424\u0440\u0430\u043D\u0446\u0443\u0437\u0441\u043A\u0438\u0439', 'es': '\u0418\u0441\u043F\u0430\u043D\u0441\u043A\u0438\u0439', 'it': '\u0418\u0442\u0430\u043B\u044C\u044F\u043D\u0441\u043A\u0438\u0439', 'pl': '\u041F\u043E\u043B\u044C\u0441\u043A\u0438\u0439', 'el': '\u0413\u0440\u0435\u0447\u0435\u0441\u043A\u0438\u0439', 'pt': '\u041F\u043E\u0440\u0442\u0443\u0433\u0430\u043B\u044C\u0441\u043A\u0438\u0439', 'hu': '\u0412\u0435\u043D\u0433\u0435\u0440\u0441\u043A\u0438\u0439', 'mo': '\u041C\u043E\u043B\u0434\u0430\u0432\u0441\u043A\u0438\u0439', 'tk': '\u0422\u0443\u0440\u043A\u043C\u0435\u043D\u0441\u043A\u0438\u0439', 'cs': '\u0427\u0435\u0448\u0441\u043A\u0438\u0439', 'ka': '\u0413\u0440\u0443\u0437\u0438\u043D\u0441\u043A\u0438\u0439', 'bg': '\u0411\u043E\u043B\u0433\u0430\u0440\u0441\u043A\u0438\u0439', 'lv': '\u041B\u0430\u0442\u044B\u0448\u0441\u043A\u0438\u0439', 'lt': '\u041B\u0438\u0442\u043E\u0432\u0441\u043A\u0438\u0439', 'no': '\u041D\u043E\u0440\u0432\u0435\u0436\u0441\u043A\u0438\u0439', 'nl': '\u041D\u0438\u0434\u0435\u0440\u043B\u0430\u043D\u0434\u0441\u043A\u0438\u0439', 'sv': '\u0428\u0432\u0435\u0434\u0441\u043A\u0438\u0439', 'ro': '\u0420\u0443\u043C\u044B\u043D\u0441\u043A\u0438\u0439', 'sr': '\u0421\u0435\u0440\u0431\u0441\u043A\u0438\u0439', 'sk': '\u0421\u043B\u043E\u0432\u0430\u0446\u043A\u0438\u0439', 'sl': '\u0421\u043B\u043E\u0432\u0435\u043D\u0441\u043A\u0438\u0439', 'fi': '\u0424\u0438\u043D\u0441\u043A\u0438\u0439', 'az': '\u0410\u0437\u0435\u0440\u0431\u0430\u0439\u0434\u0436\u0430\u043D\u0441\u043A\u0438\u0439', 'hy': '\u0410\u0440\u043C\u044F\u043D\u0441\u043A\u0438\u0439', 'da': '\u0414\u0430\u0442\u0441\u043A\u0438\u0439', 'kk': '\u041A\u0430\u0437\u0430\u0445\u0441\u043A\u0438\u0439', 'ky': '\u041A\u0438\u0440\u0433\u0438\u0437\u0441\u043A\u0438\u0439', 'tg': '\u0422\u0430\u0434\u0436\u0438\u043A\u0441\u043A\u0438\u0439', 'tr': '\u0422\u0443\u0440\u0435\u0446\u043A\u0438\u0439', 'hr': '\u0425\u043E\u0440\u0432\u0430\u0442\u0441\u043A\u0438\u0439', 'uz': '\u0423\u0437\u0431\u0435\u043A\u0441\u043A\u0438\u0439', 'ar': '\u0410\u0440\u0430\u0431\u0441\u043A\u0438\u0439', 'vi': '\u0412\u044C\u0435\u0442\u043D\u0430\u043C\u0441\u043A\u0438\u0439', 'he': '\u0418\u0432\u0440\u0438\u0442', 'id': '\u0418\u043D\u0434\u043E\u043D\u0435\u0437\u0438\u0439\u0441\u043A\u0438\u0439', 'th': '\u0422\u0430\u0439\u0441\u043A\u0438\u0439', 'zh': '\u041A\u0438\u0442\u0430\u0439\u0441\u043A\u0438\u0439', 'ko': '\u041A\u043E\u0440\u0435\u0439\u0441\u043A\u0438\u0439', 'fa': '\u041F\u0435\u0440\u0441\u0438\u0434\u0441\u043A\u0438\u0439', 'hi': '\u0425\u0438\u043D\u0434\u0438', 'ja': '\u042F\u043F\u043E\u043D\u0441\u043A\u0438\u0439', 'et': '\u042D\u0441\u0442\u043E\u043D\u0441\u043A\u0438\u0439', 'sq': '\u0410\u043B\u0431\u0430\u043D\u0441\u043A\u0438\u0439', 'mn': '\u041C\u043E\u043D\u0433\u043E\u043B\u044C\u0441\u043A\u0438\u0439', 'ms': '\u041C\u0430\u043B\u0430\u0439\u0441\u043A\u0438\u0439', 'ca': '\u041A\u0430\u0442\u0430\u043B\u0430\u043D\u0441\u043A\u0438\u0439' } }; // Маппинг флагов: id → emoji const langFlags = { 'ru': '🇷🇺', 'en': '\uD83C\uDDFA\uD83C\uDDF8', 'de': '\uD83C\uDDE9\uD83C\uDDEA', 'uk': '\uD83C\uDDFA\uD83C\uDDE6', 'be': '\uD83C\uDDE7\uD83C\uDDFE', 'fr': '\uD83C\uDDEB\uD83C\uDDF7', 'es': '\uD83C\uDDEA\uD83C\uDDF8', 'it': '\uD83C\uDDEE\uD83C\uDDF9', 'pl': '\uD83C\uDDF5\uD83C\uDDF1', 'el': '\uD83C\uDDEC\uD83C\uDDF7', 'pt': '\uD83C\uDDF5\uD83C\uDDF9', 'hu': '\uD83C\uDDED\uD83C\uDDFA', 'mo': '\uD83C\uDDF2\uD83C\uDDE9', 'tk': '\uD83C\uDDF9\uD83C\uDDF2', 'cs': '\uD83C\uDDE8\uD83C\uDDFF', 'ka': '\uD83C\uDDEC\uD83C\uDDEA', 'bg': '\uD83C\uDDE7\uD83C\uDDEC', 'lv': '\uD83C\uDDF1\uD83C\uDDFB', 'lt': '\uD83C\uDDF1\uD83C\uDDF9', 'no': '\uD83C\uDDF3\uD83C\uDDF4', 'nl': '\uD83C\uDDF3\uD83C\uDDF1', 'sv': '\uD83C\uDDF8\uD83C\uDDEA', 'ro': '\uD83C\uDDF7\uD83C\uDDF4', 'sr': '\uD83C\uDDF7\uD83C\uDDF8', 'sk': '\uD83C\uDDF8\uD83C\uDDF0', 'sl': '\uD83C\uDDF8\uD83C\uDDEE', 'fi': '\uD83C\uDDEB\uD83C\uDDEE', 'az': '\uD83C\uDDE6\uD83C\uDDFF', 'hy': '\uD83C\uDDE6\uD83C\uDDF2', 'da': '\uD83C\uDDE9\uD83C\uDDF0', 'kk': '\uD83C\uDDF0\uD83C\uDDFF', 'ky': '\uD83C\uDDF0\uD83C\uDDEC', 'tg': '\uD83C\uDDF9\uD83C\uDDEF', 'tr': '\uD83C\uDDF9\uD83C\uDDF7', 'hr': '\uD83C\uDDED\uD83C\uDDF7', 'uz': '\uD83C\uDDFA\uD83C\uDDFF', 'ar': '\uD83C\uDDF8\uD83C\uDDE6', 'vi': '\uD83C\uDDFB\uD83C\uDDF3', 'he': '\uD83C\uDDEE\uD83C\uDDF1', 'id': '\uD83C\uDDEE\uD83C\uDDE9', 'th': '\uD83C\uDDF9\uD83C\uDDED', 'zh': '\uD83C\uDDE8\uD83C\uDDF3', 'ko': '\uD83C\uDDF0\uD83C\uDDF7', 'fa': '\uD83C\uDDEE\uD83C\uDDF7', 'hi': '\uD83C\uDDEE\uD83C\uDDF3', 'ja': '\uD83C\uDDEF\uD83C\uDDF5', 'et': '\uD83C\uDDEA\uD83C\uDDEA', 'sq': '\uD83C\uDDE6\uD83C\uDDF1', 'mn': '\uD83C\uDDF2\uD83C\uDDF3', 'ms': '\uD83C\uDDF2\uD83C\uDDFE', 'ca': '\uD83C\uDDEA\uD83C\uDDF8' }; // Twemoji парсинг (SVG с CDN) const twemojiOpts = { folder: 'svg', ext: '.svg' }; function parseEmoji(el) { if (typeof twemoji !== 'undefined') twemoji.parse(el, twemojiOpts); } // --- Кастомные выпадающие списки --- function initCalcDropdown(wrapperId, inputId, flagId, nameId, includeRussian) { const wrapper = document.getElementById(wrapperId); if (!wrapper) return; const btn = wrapper.querySelector('.calc-dropdown-btn'); const panel = wrapper.querySelector('.calc-dropdown-panel'); const search = wrapper.querySelector('.calc-dropdown-search'); const list = wrapper.querySelector('.calc-dropdown-list'); const hiddenInput = document.getElementById(inputId); const flagEl = document.getElementById(flagId); const nameEl = document.getElementById(nameId); // Собираем языки и сортируем по алфавиту // ru из prices.languages фильтруем — иначе «Русский» дублируется (добавляется только вручную через includeRussian) let langs = []; if (includeRussian) { langs.push({ id: 'ru', flag: '🇷🇺', name: calcI18n.langNames['ru'] || 'Русский' }); } pricesData.languages.forEach(l => { if (l.id === 'ru') return; langs.push({ id: l.id, flag: l.flag, name: calcI18n.langNames[l.id] || l.name }); }); langs.sort((a, b) => a.name.localeCompare(b.name)); function renderOptions(filter) { list.innerHTML = ''; const q = (filter || '').toLowerCase(); langs.forEach(l => { if (q && !l.name.toLowerCase().includes(q) && !l.id.includes(q)) return; const div = document.createElement('div'); div.className = 'calc-dropdown-option' + (l.id === hiddenInput.value ? ' active' : ''); div.dataset.value = l.id; div.innerHTML = '' + l.flag + '' + l.name + ''; div.addEventListener('click', () => selectLang(l)); list.appendChild(div); }); // Парсим эмодзи через Twemoji parseEmoji(list); } function selectLang(l) { hiddenInput.value = l.id; flagEl.innerHTML = l.flag; nameEl.textContent = l.name; parseEmoji(flagEl); panel.classList.remove('open'); btn.setAttribute('aria-expanded', 'false'); search.value = ''; // Событие change hiddenInput.dispatchEvent(new Event('change')); } btn.addEventListener('click', (e) => { e.stopPropagation(); // Закрыть другие document.querySelectorAll('.calc-dropdown').forEach(w => { if (w !== wrapper) { w.querySelector('.calc-dropdown-panel').classList.remove('open'); w.querySelector('.calc-dropdown-btn').setAttribute('aria-expanded', 'false'); } }); panel.classList.toggle('open'); const isOpen = panel.classList.contains('open'); btn.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); if (isOpen) { renderOptions(''); setTimeout(() => search.focus(), 50); } }); search.addEventListener('input', () => renderOptions(search.value)); search.addEventListener('click', (e) => e.stopPropagation()); // Начальный парсинг флагов в кнопках parseEmoji(flagEl); } // Закрытие при клике вне document.addEventListener('click', () => { document.querySelectorAll('.calc-dropdown-panel.open').forEach(p => p.classList.remove('open')); document.querySelectorAll('.calc-dropdown-btn[aria-expanded="true"]').forEach(b => b.setAttribute('aria-expanded', 'false')); }); // Функция расчета стоимости function calculatePrice() { const fromLang = document.getElementById('calc-from-lang').value; const toLang = document.getElementById('calc-to-lang').value; const volume = Math.max(1, parseInt(document.getElementById('calc-volume').value, 10) || 1); // Одинаковые языки (например, ru → ru) — расчёт невозможен if (fromLang === toLang) { document.getElementById('calc-result').textContent = '—'; document.getElementById('calc-lang-pair').textContent = (calcI18n.langNames[fromLang] || fromLang) + ' → ' + (calcI18n.langNames[toLang] || toLang); document.getElementById('breakdown-translation-price').textContent = '—'; document.getElementById('breakdown-translation-label').textContent = ''; document.getElementById('breakdown-addons-container').innerHTML = ''; document.getElementById('breakdown-discount').classList.add('hidden'); document.getElementById('breakdown-total').textContent = '—'; return; } // Определяем направление и язык const isToRussian = (toLang === 'ru'); const langId = isToRussian ? fromLang : toLang; const language = pricesData.languages.find(l => l.id === langId); if (!language) { document.getElementById('calc-result').textContent = '—'; return; } // Цена за страницу зависит от направления let pricePerPage = isToRussian ? language.price_from_foreign : language.price_to_foreign; // Базовая стоимость перевода let translationPrice = pricePerPage * volume; // Проверяем скидку за объем // break на первом совпадении: на границе (80/100/150 стр.) скидочные диапазоны // в prices.json пересекаются; берём нижний диапазон, чтобы совпадать с таблицей цен. let discountPercent = 0; if (pricesData.discounts) { for (const d of pricesData.discounts) { if (volume >= d.from_pages && (d.to_pages === null || volume <= d.to_pages)) { discountPercent = d.percent; break; } } } let discountAmount = 0; if (discountPercent > 0) { discountAmount = Math.round(translationPrice * discountPercent / 100); } let translationAfterDiscount = translationPrice - discountAmount; // Дополнительные услуги (с учётом количества документов) let addonsTotal = 0; const addonDetails = []; const addons = document.querySelectorAll('.calc-addon:checked'); addons.forEach(addon => { let pricePerDoc = parseInt(addon.dataset.price); const id = addon.dataset.id; const service = pricesData.additional_services.find(s => s.id === id); const qtyInput = document.querySelector('.calc-addon-qty-input[data-id="' + id + '"]'); const qty = qtyInput ? (parseInt(qtyInput.value) || 1) : 1; // Нотариальное: скидка от 8 документов (1000₽ вместо 1200₽) if (id === 'notarial' && pricesData.notarial_bulk_discount && qty >= pricesData.notarial_bulk_discount.from_documents) { pricePerDoc = pricesData.notarial_bulk_discount.price_per_document; } if (service && pricePerDoc > 0) { const subtotal = pricePerDoc * qty; addonsTotal += subtotal; const label = (calcI18n.addons[id] || service.name) + (qty > 1 ? ' × ' + qty + ' ' + calcI18n.docs : ''); addonDetails.push({ name: label, price: subtotal, pricePerDoc: pricePerDoc, qty: qty }); // Подитог рядом с инпутом количества const subtotalEl = document.querySelector('.calc-addon-subtotal[data-id="' + id + '"]'); if (subtotalEl) subtotalEl.textContent = qty > 1 ? '= ' + subtotal.toLocaleString('ru-RU') + ' ₽' : ''; // Обновить цену за единицу при скидке нотариального const row = addon.closest('.calc-addon-row'); if (row) { const unitPriceEl = row.querySelector('.addon-unit-price'); if (unitPriceEl) unitPriceEl.textContent = pricePerDoc.toLocaleString('ru-RU') + ' ₽'; } } }); let totalPrice = translationAfterDiscount + addonsTotal; // Минимальный заказ if (totalPrice < minOrder && totalPrice > 0) { totalPrice = minOrder; } // Обновляем отображение const fromName = calcI18n.langNames[fromLang] || fromLang; const toName = calcI18n.langNames[toLang] || toLang; document.getElementById('calc-result').textContent = totalPrice.toLocaleString('ru-RU') + ' ₽'; document.getElementById('calc-lang-pair').textContent = fromName + ' → ' + toName; // Детализация document.getElementById('breakdown-translation-price').textContent = translationPrice.toLocaleString('ru-RU') + ' ₽'; document.getElementById('breakdown-translation-label').textContent = volume + ' ' + calcI18n.pages + ' ' + calcI18n.times + ' ' + pricePerPage.toLocaleString('ru-RU') + ' ₽'; // Скидка const discountEl = document.getElementById('breakdown-discount'); if (discountPercent > 0) { discountEl.classList.remove('hidden'); document.getElementById('breakdown-discount-label').textContent = calcI18n.discount + ' (' + discountPercent + '%)'; document.getElementById('breakdown-discount-price').textContent = '-' + discountAmount.toLocaleString('ru-RU') + ' ₽'; } else { discountEl.classList.add('hidden'); } // Допуслуги const addonsContainer = document.getElementById('breakdown-addons-container'); addonsContainer.innerHTML = ''; addonDetails.forEach(a => { const div = document.createElement('div'); div.className = 'flex justify-between'; div.innerHTML = '' + calcEscapeHtml(a.name) + '' + a.price.toLocaleString('ru-RU') + ' ₽'; addonsContainer.appendChild(div); }); // Итого document.getElementById('breakdown-total').textContent = totalPrice.toLocaleString('ru-RU') + ' ₽'; } // Собрать детализацию цен для отправки на сервер function calcGetPriceBreakdown() { if (!pricesData) return null; const fromLang = document.getElementById('calc-from-lang').value; const toLang = document.getElementById('calc-to-lang').value; const volume = Math.max(1, parseInt(document.getElementById('calc-volume').value, 10) || 1); if (fromLang === toLang) return null; const isToRussian = toLang === 'ru'; const language = pricesData.languages.find(l => l.id === (isToRussian ? fromLang : toLang)); if (!language) return null; const pricePerPage = isToRussian ? language.price_from_foreign : language.price_to_foreign; const translationPrice = pricePerPage * volume; // break на первом совпадении (границы 80/100/150 пересекаются — см. calculatePrice). let discountPercent = 0; if (pricesData.discounts) { for (const d of pricesData.discounts) { if (volume >= d.from_pages && (d.to_pages === null || volume <= d.to_pages)) { discountPercent = d.percent; break; } } } const discountAmount = discountPercent > 0 ? Math.round(translationPrice * discountPercent / 100) : 0; const items = []; items.push({ name: volume + ' стр. × ' + pricePerPage.toLocaleString('ru-RU') + ' ₽ — перевод', price: translationPrice }); if (discountAmount > 0) { items.push({ name: 'Скидка за объём (' + discountPercent + '%)', price: -discountAmount }); } document.querySelectorAll('.calc-addon:checked').forEach(addon => { let pricePerDoc = parseInt(addon.dataset.price); const id = addon.dataset.id; const service = pricesData.additional_services.find(s => s.id === id); const qtyInput = document.querySelector('.calc-addon-qty-input[data-id="' + id + '"]'); const qty = qtyInput ? (parseInt(qtyInput.value) || 1) : 1; if (id === 'notarial' && pricesData.notarial_bulk_discount && qty >= pricesData.notarial_bulk_discount.from_documents) { pricePerDoc = pricesData.notarial_bulk_discount.price_per_document; } if (service && pricePerDoc > 0) { const baseName = calcI18n.addons[id] || service.name; const label = qty > 1 ? baseName + ' × ' + qty + ' док. (' + pricePerDoc.toLocaleString('ru-RU') + ' ₽/док.)' : baseName + ' (' + pricePerDoc.toLocaleString('ru-RU') + ' ₽)'; items.push({ name: label, price: pricePerDoc * qty }); } }); return { items: items }; } // === ЛОГИКА ПРИКРЕПЛЕНИЯ ФАЙЛОВ === const calcAttachedFiles = []; const CALC_MAX_FILE_SIZE_MB = 50; const CALC_MAX_FILE_SIZE = CALC_MAX_FILE_SIZE_MB * 1024 * 1024; const CALC_ALLOWED_EXT = ['pdf','doc','docx','xls','xlsx','txt','jpg','jpeg','png','ppt','pptx','rtf','odt','zip','rar']; const CALC_MAX_FILES = 10; function calcFormatFileSize(bytes) { if (bytes < 1024) return bytes + ' B'; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; return (bytes / (1024 * 1024)).toFixed(1) + ' MB'; } function calcEscapeHtml(s) { const d = document.createElement('div'); d.textContent = s; return d.innerHTML.replace(/"/g, '"'); } function calcRenderFiles() { const list = document.getElementById('calc-files-list'); const btn = document.getElementById('calc-attach-btn'); if (calcAttachedFiles.length === 0) { list.classList.add('hidden'); list.innerHTML = ''; btn.classList.remove('has-files'); return; } btn.classList.add('has-files'); list.classList.remove('hidden'); const totalSize = calcAttachedFiles.reduce((sum, f) => sum + f.size, 0); list.innerHTML = calcAttachedFiles.map((f, i) => { const safeName = calcEscapeHtml(f.name); return '
' + '' + '' + safeName + '' + '' + calcFormatFileSize(f.size) + '' + '' + '' + '' + '
'; }).join(''); if (calcAttachedFiles.length > 1) { list.innerHTML += '
' + calcFormatFileSize(totalSize) + '
'; } } function calcRemoveFile(index) { calcAttachedFiles.splice(index, 1); calcRenderFiles(); } // === МОДАЛЬНОЕ ОКНО === function calcOpenModal() { const fromLang = document.getElementById('calc-from-lang').value; const toLang = document.getElementById('calc-to-lang').value; const volume = Math.max(1, parseInt(document.getElementById('calc-volume').value, 10) || 1); const fromName = calcI18n.langNames[fromLang] || fromLang; const toName = calcI18n.langNames[toLang] || toLang; const price = document.getElementById('calc-result').textContent; document.getElementById('modal-lang-pair').textContent = fromName + ' \u2192 ' + toName; document.getElementById('modal-volume').textContent = volume + ' ' + calcI18n.pages; document.getElementById('modal-price').textContent = price; // \u0424\u0430\u0439\u043b \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u0435\u043d: \u0435\u0441\u043b\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d \u2014 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0443. document.getElementById('modal-no-file-note').classList.toggle('hidden', calcAttachedFiles.length > 0); // Сброс ошибок document.querySelectorAll('.calc-modal-body input, .calc-modal-body textarea').forEach(el => { el.classList.remove('field-error'); }); document.querySelectorAll('.field-error-msg').forEach(el => el.classList.remove('visible')); const captchaBox = document.getElementById('calc-captcha-box'); captchaBox.classList.remove('checked', 'error'); captchaBox.querySelector('svg').classList.add('hidden'); document.getElementById('calc-modal-overlay').classList.add('open'); document.body.style.overflow = 'hidden'; setTimeout(() => document.getElementById('calc-modal-name').focus(), 100); } function calcCloseModal() { document.getElementById('calc-modal-overlay').classList.remove('open'); document.body.style.overflow = ''; } // Предупреждение об отклонённых сервером вложениях. Заказ при этом сохранён — // показываем внутри окна успеха, а не как ошибку. function calcShowRejectedFiles(rejected) { const box = document.getElementById('calc-success-rejected'); if (!box) return; box.textContent = ''; if (!rejected || !rejected.length) { box.classList.remove('open'); return; } const title = document.createElement('strong'); title.textContent = calcI18nUI.rejectedTitle.replace('%d', rejected.length); box.appendChild(title); const list = document.createElement('ul'); rejected.forEach(function (rf) { const li = document.createElement('li'); // textContent — имя файла приходит от пользователя, не вставлять как HTML li.textContent = (rf && rf.name ? rf.name : '—') + ' — ' + (rf && rf.reason ? rf.reason : ''); list.appendChild(li); }); box.appendChild(list); const cta = document.createElement('div'); cta.className = 'calc-rejected-cta'; cta.textContent = calcI18nUI.rejectedCta.replace('%s', box.dataset.email || ''); box.appendChild(cta); box.classList.add('open'); } // === ВАЛИДАЦИЯ === function calcValidateEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } function calcValidatePhone(phone) { var cleaned = phone.replace(/\D/g, ''); // На EN/ZH-версиях допускаем международные номера: достаточно ≥10 цифр if (!(document.documentElement.lang || '').toLowerCase().startsWith('ru')) { return cleaned.length >= 10; } return cleaned.length === 11 && cleaned[0] === '7'; } function calcValidateModal() { let valid = true; // Имя const name = document.getElementById('calc-modal-name'); const nameErr = document.getElementById('calc-modal-name-error'); if (!name.value.trim()) { name.classList.add('field-error'); nameErr.classList.add('visible'); valid = false; } else { name.classList.remove('field-error'); nameErr.classList.remove('visible'); } // Телефон const phone = document.getElementById('calc-modal-phone'); const phoneErr = document.getElementById('calc-modal-phone-error'); if (!phone.value.trim() || !calcValidatePhone(phone.value)) { phone.classList.add('field-error'); phoneErr.classList.add('visible'); phoneErr.textContent = '!'; valid = false; } else { phone.classList.remove('field-error'); phoneErr.classList.remove('visible'); } // Email const email = document.getElementById('calc-modal-email'); const emailErr = document.getElementById('calc-modal-email-error'); if (!email.value.trim() || !calcValidateEmail(email.value)) { email.classList.add('field-error'); emailErr.classList.add('visible'); emailErr.textContent = '!'; valid = false; } else { email.classList.remove('field-error'); emailErr.classList.remove('visible'); } // Капча const captchaBox = document.getElementById('calc-captcha-box'); const captchaErr = document.getElementById('calc-captcha-error'); if (!captchaBox.classList.contains('checked')) { captchaBox.classList.add('error'); captchaErr.classList.add('visible'); valid = false; } else { captchaBox.classList.remove('error'); captchaErr.classList.remove('visible'); } return valid; } // === ОТПРАВКА ЗАЯВКИ === async function calcSubmitOrder() { if (!calcValidateModal()) return; const submitBtn = document.getElementById('calc-modal-submit'); const submitText = document.getElementById('calc-modal-submit-text'); const spinner = document.getElementById('calc-modal-spinner'); submitBtn.disabled = true; submitText.textContent = calcI18nUI.sending; spinner.classList.remove('hidden'); try { const formData = new FormData(); formData.append('source', 'calculator'); if (window.UCCsrf) formData.append('csrf', window.UCCsrf.token()); formData.append('name', document.getElementById('calc-modal-name').value.trim()); formData.append('phone', document.getElementById('calc-modal-phone').value.trim()); formData.append('email', document.getElementById('calc-modal-email').value.trim()); formData.append('message', document.getElementById('calc-modal-comment').value.trim()); formData.append('lang_from', calcI18n.langNames[document.getElementById('calc-from-lang').value] || document.getElementById('calc-from-lang').value); formData.append('lang_to', calcI18n.langNames[document.getElementById('calc-to-lang').value] || document.getElementById('calc-to-lang').value); formData.append('volume', document.getElementById('calc-volume').value); formData.append('estimated_price', document.getElementById('calc-result').textContent); // Информация о клиенте (браузер, экран, язык, таймзона) formData.append('user_agent', navigator.userAgent); formData.append('screen_resolution', screen.width + '×' + screen.height); formData.append('viewport', window.innerWidth + '×' + window.innerHeight); formData.append('browser_lang', navigator.language || navigator.userLanguage || ''); formData.append('timezone', Intl.DateTimeFormat().resolvedOptions().timeZone || ''); formData.append('referrer', document.referrer || ''); formData.append('page_url', window.location.href); try { formData.append('lead_attribution', JSON.stringify(window.getLeadAttribution ? window.getLeadAttribution() : {})); } catch(e){} // Допуслуги (с количеством) const addonNames = []; document.querySelectorAll('.calc-addon:checked').forEach(cb => { const id = cb.dataset.id; const qtyInput = document.querySelector('.calc-addon-qty-input[data-id="' + id + '"]'); const qty = qtyInput ? (parseInt(qtyInput.value) || 1) : 1; const label = calcI18n.addons[id] || id; addonNames.push(qty > 1 ? label + ' × ' + qty : label); }); formData.append('addons', addonNames.join(', ')); // Детализация цен для письма менеджеру const breakdown = calcGetPriceBreakdown(); if (breakdown) { formData.append('price_breakdown', JSON.stringify(breakdown)); } // Файлы calcAttachedFiles.forEach((file, i) => { formData.append('files[]', file); }); // Сколько файлов клиент реально приложил. Если PHP примет меньше // (max_file_uploads), сервер сообщит о разнице в rejected_files. formData.append('expected_files_count', String(calcAttachedFiles.length)); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 120000); console.log('[calculator] Sending request...'); const response = await fetch('/api/calculator-order.php', { method: 'POST', body: formData, signal: controller.signal }); clearTimeout(timeoutId); console.log('[calculator] Response status:', response.status); const data = await response.json(); if (data.success) { calcCloseModal(); // Показать окно успеха document.getElementById('calc-success-overlay').classList.add('open'); document.body.style.overflow = 'hidden'; // Часть файлов могла быть отклонена (формат/размер/сбой загрузки). // Заказ сохранён, но клиент должен знать, что вложение не дошло. calcShowRejectedFiles(data.rejected_files); // Сброс формы document.getElementById('calc-modal-name').value = ''; document.getElementById('calc-modal-phone').value = ''; document.getElementById('calc-modal-email').value = ''; document.getElementById('calc-modal-comment').value = ''; calcAttachedFiles.length = 0; calcRenderFiles(); // Аналитика if (typeof ym !== 'undefined' && window.YANDEX_METRIKA_ID) { ym(window.YANDEX_METRIKA_ID, 'reachGoal', 'calculator_order'); } if (typeof gtag !== 'undefined') { gtag('event', 'submit', { event_category: 'Calculator', event_label: 'Order' }); } } else { alert(data.message || calcI18nUI.errorGeneric); } } catch (err) { console.error('Calculator submit error:', err); if (err.name === 'AbortError') { alert(calcI18nUI.errorNetwork); } else { alert(calcI18nUI.errorGeneric); } } finally { submitBtn.disabled = false; submitText.textContent = calcI18nUI.submitText; spinner.classList.add('hidden'); } } function calcCloseSuccess() { document.getElementById('calc-success-overlay').classList.remove('open'); document.body.style.overflow = ''; } // Обработчики изменений document.addEventListener('DOMContentLoaded', () => { // Инициализация кастомных дропдаунов (ru добавляется вручную, в списках prices.languages он отфильтрован) initCalcDropdown('from-lang-dropdown', 'calc-from-lang', 'from-lang-flag', 'from-lang-name', true); initCalcDropdown('to-lang-dropdown', 'calc-to-lang', 'to-lang-flag', 'to-lang-name', true); ['calc-from-lang', 'calc-to-lang', 'calc-volume'].forEach(id => { const el = document.getElementById(id); if (el) { el.addEventListener('change', calculatePrice); el.addEventListener('input', calculatePrice); } }); document.querySelectorAll('.calc-addon').forEach(cb => { cb.addEventListener('change', function() { const id = this.dataset.id; const qtyDiv = this.closest('.calc-addon-row').querySelector('.calc-addon-qty'); if (qtyDiv) { if (this.checked) { qtyDiv.classList.remove('hidden'); } else { qtyDiv.classList.add('hidden'); // Сброс количества при отключении const qtyInput = qtyDiv.querySelector('.calc-addon-qty-input'); if (qtyInput) qtyInput.value = 1; const subtotalEl = qtyDiv.querySelector('.calc-addon-subtotal'); if (subtotalEl) subtotalEl.textContent = ''; } } calculatePrice(); }); }); // Изменение количества документов → пересчёт document.querySelectorAll('.calc-addon-qty-input').forEach(input => { input.addEventListener('input', calculatePrice); }); // Синхронизация: один из языков должен быть русским document.getElementById('calc-from-lang').addEventListener('change', function() { if (this.value !== 'ru' && document.getElementById('calc-to-lang').value !== 'ru') { document.getElementById('calc-to-lang').value = 'ru'; document.getElementById('to-lang-flag').innerHTML = '🇷🇺'; document.getElementById('to-lang-name').textContent = calcI18n.langNames['ru']; parseEmoji(document.getElementById('to-lang-flag')); } calculatePrice(); }); document.getElementById('calc-to-lang').addEventListener('change', function() { if (this.value !== 'ru' && document.getElementById('calc-from-lang').value !== 'ru') { document.getElementById('calc-from-lang').value = 'ru'; document.getElementById('from-lang-flag').innerHTML = '🇷🇺'; document.getElementById('from-lang-name').textContent = calcI18n.langNames['ru']; parseEmoji(document.getElementById('from-lang-flag')); } calculatePrice(); }); calculatePrice(); // --- Файловые аттачменты --- const attachBtn = document.getElementById('calc-attach-btn'); const fileInput = document.getElementById('calc-file-input'); attachBtn.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', (e) => { for (const file of e.target.files) { // Лимит PHP max_file_uploads: файлы сверх него сервер молча отбрасывает, // поэтому не даём добавить их в список вообще. if (calcAttachedFiles.length >= CALC_MAX_FILES) { alert(calcI18nUI.tooManyFiles.replace('%d', CALC_MAX_FILES)); break; } const ext = file.name.split('.').pop().toLowerCase(); if (!CALC_ALLOWED_EXT.includes(ext)) { alert(file.name + ' — invalid format'); continue; } if (file.size > CALC_MAX_FILE_SIZE) { alert(file.name + ' — max ' + CALC_MAX_FILE_SIZE_MB + ' MB'); continue; } calcAttachedFiles.push(file); } calcRenderFiles(); fileInput.value = ''; // Сброс, чтобы можно было выбрать тот же файл повторно // Сбрасываем ошибку «файл обязателен» при добавлении файлов if (calcAttachedFiles.length > 0) { var attachBtn = document.getElementById('calc-attach-btn'); var fileErr = document.getElementById('calc-file-error'); attachBtn.classList.remove('error'); attachBtn.style.borderColor = ''; fileErr.classList.add('hidden'); } }); // --- Кнопка «Отправить заявку» → открыть модал --- // Файл НЕ обязателен: можно отправить заявку без документа (он будет прислан позже). document.getElementById('calc-submit-btn').addEventListener('click', function() { // Одинаковые языки — заказ не имеет смысла, расчёт показывает «—» if (document.getElementById('calc-from-lang').value === document.getElementById('calc-to-lang').value) { return; } calcOpenModal(); }); // --- Закрытие модалки --- document.getElementById('calc-modal-close').addEventListener('click', calcCloseModal); // --- Капча --- const captchaBox = document.getElementById('calc-captcha-box'); captchaBox.addEventListener('click', () => { captchaBox.classList.toggle('checked'); const svg = captchaBox.querySelector('.captcha-checkbox svg'); if (captchaBox.classList.contains('checked')) { svg.classList.remove('hidden'); captchaBox.classList.remove('error'); document.getElementById('calc-captcha-error').classList.remove('visible'); } else { svg.classList.add('hidden'); } }); // --- Отправка --- document.getElementById('calc-modal-submit').addEventListener('click', calcSubmitOrder); // --- Закрытие окна успеха --- document.getElementById('calc-success-close').addEventListener('click', calcCloseSuccess); // --- Реалтайм-валидация: убрать красное при вводе --- ['calc-modal-name', 'calc-modal-phone', 'calc-modal-email'].forEach(id => { const el = document.getElementById(id); if (el) { el.addEventListener('input', () => { el.classList.remove('field-error'); const errEl = document.getElementById(id + '-error'); if (errEl) errEl.classList.remove('visible'); }); } }); // --- Маска телефона (+7 только на русской версии; на EN/ZH свободный ввод международных номеров) --- const phoneInput = document.getElementById('calc-modal-phone'); if ((document.documentElement.lang || '').toLowerCase().startsWith('ru')) { phoneInput.addEventListener('input', function() { let val = this.value.replace(/\D/g, ''); if (val.length > 0 && val[0] === '8') val = '7' + val.slice(1); if (val.length > 11) val = val.slice(0, 11); if (val.length === 0) { this.value = ''; return; } let formatted = '+' + val[0]; if (val.length > 1) formatted += ' (' + val.slice(1, 4); if (val.length > 4) formatted += ') ' + val.slice(4, 7); if (val.length > 7) formatted += '-' + val.slice(7, 9); if (val.length > 9) formatted += '-' + val.slice(9, 11); this.value = formatted; }); } // --- Кнопка «Сформировать КП» --- // Контекст последнего сформированного КП — для лёгкого захвата контакта (email). let quoteLeadContext = null; const quoteBtn = document.getElementById('calc-quote-btn'); if (quoteBtn) { quoteBtn.addEventListener('click', function() { const breakdown = calcGetPriceBreakdown(); if (!breakdown || !breakdown.items.length) return; const fromLang = document.getElementById('calc-from-lang').value; const toLang = document.getElementById('calc-to-lang').value; const volume = document.getElementById('calc-volume').value; const totalPrice = document.getElementById('calc-result').textContent; const fromName = calcI18n.langNames[fromLang] || fromLang; const toName = calcI18n.langNames[toLang] || toLang; // Собираем допуслуги const addonNames = []; document.querySelectorAll('.calc-addon:checked').forEach(cb => { const id = cb.dataset.id; const qtyInput = document.querySelector('.calc-addon-qty-input[data-id="' + id + '"]'); const qty = qtyInput ? (parseInt(qtyInput.value) || 1) : 1; const label = calcI18n.addons[id] || id; addonNames.push(qty > 1 ? label + ' \u00d7 ' + qty : label); }); // Формируем URL с параметрами const params = new URLSearchParams({ lang: 'ru', from: fromName, to: toName, volume: volume, total: totalPrice, breakdown: JSON.stringify(breakdown.items), addons: addonNames.join(', ') }); window.open('/api/generate-quote.php?' + params.toString(), '_blank'); // КП уже открыт — предлагаем (необязательно) отправить его на email. quoteLeadContext = { fromName, toName, volume, totalPrice, addons: addonNames.join(', ') }; const leadBlock = document.getElementById('quote-lead-block'); if (leadBlock) { leadBlock.classList.remove('hidden'); document.getElementById('quote-lead-success').classList.add('hidden'); } }); } // --- Отправка КП на email (лёгкий захват лида, не блокирует КП) --- const leadSubmitBtn = document.getElementById('quote-lead-submit'); if (leadSubmitBtn) { leadSubmitBtn.addEventListener('click', async function() { const emailEl = document.getElementById('quote-lead-email'); const nameEl = document.getElementById('quote-lead-name'); const hp = document.getElementById('quote-lead-website'); const successEl = document.getElementById('quote-lead-success'); // Honeypot if (hp && hp.value) return; const email = emailEl.value.trim(); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { emailEl.classList.add('border-red-500'); emailEl.focus(); alert(calcI18nUI.quoteLeadInvalidEmail); return; } emailEl.classList.remove('border-red-500'); leadSubmitBtn.disabled = true; leadSubmitBtn.textContent = '...'; try { const ctx = quoteLeadContext || {}; const formData = new FormData(); formData.append('source', 'quote_lead'); // Honeypot уезжает на сервер: клиентской проверки hp.value мало — бот, // бьющий прямо в /api/contact.php, обходил её, а серверная проверка // (!empty($_POST['website'])) без этого поля не срабатывала никогда. formData.append('website', hp ? hp.value : ''); if (window.UCCsrf) formData.append('csrf', window.UCCsrf.token()); formData.append('name', nameEl.value.trim()); formData.append('email', email); formData.append('lang_from', ctx.fromName || ''); formData.append('lang_to', ctx.toName || ''); formData.append('message', [ctx.volume ? ctx.volume + ' ' + calcI18n.pages : '', ctx.totalPrice ? '— ' + ctx.totalPrice : '', ctx.addons || ''].filter(Boolean).join(' ')); formData.append('user_agent', navigator.userAgent); formData.append('screen_resolution', screen.width + '×' + screen.height); formData.append('viewport', window.innerWidth + '×' + window.innerHeight); formData.append('browser_lang', navigator.language || navigator.userLanguage || ''); formData.append('timezone', Intl.DateTimeFormat().resolvedOptions().timeZone || ''); formData.append('referrer', document.referrer || ''); formData.append('page_url', window.location.href); try { formData.append('lead_attribution', JSON.stringify(window.getLeadAttribution ? window.getLeadAttribution() : {})); } catch(e){} const response = await fetch('/api/contact.php', { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { successEl.classList.remove('hidden'); emailEl.value = ''; nameEl.value = ''; if (typeof ym !== 'undefined' && window.YANDEX_METRIKA_ID) { ym(window.YANDEX_METRIKA_ID, 'reachGoal', 'quote_lead'); } if (typeof gtag !== 'undefined') { gtag('event', 'submit', { event_category: 'Calculator', event_label: 'Quote Lead' }); } } else { alert(data.message || calcI18nUI.errorGeneric); } } catch (err) { alert(calcI18nUI.errorGeneric); } finally { leadSubmitBtn.disabled = false; leadSubmitBtn.textContent = calcI18nUI.quoteLeadSubmit; } }); } });

Как мы работаем

1

Отправьте заявку

Заполните форму на сайте, позвоните или напишите в мессенджер. Отправьте документы для расчёта.

2

Получите расчёт

Менеджер рассчитает точную стоимость и сроки в течение 30 минут. Без скрытых платежей.

3

Мы переводим

Профильный переводчик выполняет перевод. Редактор проверяет качество. Нотариус заверяет (если нужно).

4

Получите перевод

Курьер бесплатно доставит по Москве или отправим email. Оплата при получении.

Для юридических лиц

Работаем с компаниями любого масштаба — от стартапов до корпораций. Официальный договор, полный документооборот, выделенный менеджер.

Договор и NDA

Официальный договор на переводческие услуги. NDA для защиты коммерческой тайны.

Оплата по безналу

Безналичная оплата, постоплата для постоянных клиентов. БЕЗ НДС (УСН).

Закрывающие документы

Акт выполненных работ, счёт — полный пакет для бухгалтерии.

Скидки от объёма 3–10%

От 50 стр. — скидка 3%. От 100 стр. — 5%. От 300 стр. — до 10%.

Персональный менеджер

Один контакт для всех проектов. Контроль сроков, качества и бюджета.

CAT-системы, экономия до 40%

SDL Trados, memoQ — память переводов снижает стоимость повторяющихся текстов.

Частые вопросы

Готовы заказать Перевод деклараций?

Отправьте заявку сейчас и получите расчет стоимости в течение 30 минут

Позвонить сейчас

Читайте полезные статьи о переводах, CAT-системах и стандартах качества в нашем Блог →

Позвонить Max Max