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

Перевод с арабского языка

Перевод с арабского — от 1 200 руб./стр., на арабский — от 1 250 руб./стр. MSA и диалекты 26 стран. RTL-вёрстка. Специализация: нефтегаз, финансы, торговля. Носители языка в штате.

+7 (926) 158-66-56
От 1 200₽/стр.
Нотариальное заверение
RTL-вёрстка
Ответим за 30 минут

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

Перевод с арабского языка

Стоимость

С арабского на русский
от 1 200₽

Перевод с арабского

С русского на арабский
от 1 250₽

Перевод на арабский

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

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

Перевод с арабского и на арабский в Москве

Перевод с арабского — от 1 200 руб./стр. Арабский — официальный язык в 26 странах с населением 420+ млн человек. Основные заказчики — нефтегазовые компании, банки, строительные холдинги, работающие с ОАЭ, Саудовской Аравией, Катаром, Египтом и другими арабскими государствами.

Специализация: нефтегаз, финансы, торговля

Для бизнеса

  • → Контракты нефтегазового сектора (ADNOC, Saudi Aramco, QatarEnergy)
  • → Банковская и финансовая документация
  • Юридические документы: учредительные, лицензии, доверенности
  • Техническая документация: нефтегаз, строительство, энергетика
  • → Торговые соглашения, тендерная документация

Для частных лиц

  • Личные документы: паспорта, свидетельства, дипломы
  • → Документы для посольств арабских стран
  • → Медицинские заключения, справки
  • → Доверенности с нотариальным заверением и апостилем
  • → Документы для работы и проживания в ОАЭ

Стоимость перевода с арабского

  • ✓ Стандартный перевод AR→RU / RU→AR — от 1 200₽ / 1 250₽ за страницу
  • ✓ Специализированный перевод (нефтегаз, юридический) — от 1 350₽/стр.
  • ✓ Срочный перевод (до 24 часов) — наценка 45%
  • ✓ Нотариальное заверение — 1 200₽/документ
  • ✓ Минимальный заказ — 1 500₽

Особенности перевода арабского языка

RTL-вёрстка и типографика

Арабский текст пишется справа налево (Right-to-Left). При переводе на арабский мы корректно оформляем: направление текста, выравнивание столбцов и таблиц, зеркальное расположение графических элементов. Для сложных макетов (буклеты, каталоги, технические чертежи) используем InDesign с арабскими шрифтами.

MSA (fusha)

Стандартный арабский. Используется в официальных документах, СМИ, деловой переписке всех арабских стран.

ОАЭ / Саудовская Аравия

Деловая лексика Персидского залива. Нефтегаз, финансы, строительство. Документы для DIFC, ADGM.

Египет / Магриб

Египетский и магрибский диалекты. Торговые и юридические документы. Марокко, Тунис, Алжир.

Преимущества работы с нами

8+

переводчиков AR↔RU. Носители языка для редактуры и стилистической правки

RTL

Корректная вёрстка справа налево. InDesign, Word, PDF с арабской типографикой

Договор

Закрывающие документы. Постоплата для постоянных клиентов

Смотрите также: все языки перевода · письменный перевод · устный перевод

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

Узнайте точную цену вашего заказа за 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