Opencart 1.5.x (catalog): как в каталоге добавить вывод атрибута к описанию товара

- Posted in Uncategorized by

В комментариях к статье об изменении длины описаний в каталоге Opencart 1.5 спросили, можно ли сделать так,

чтобы вместо описания товара в каталоге выводился определённый атрибут товара (краткое описание товара). Интересует для OpenCart 1.5.1

Это несложно, изменения в двух файлах приведены ниже.

Как можно заметить, в файле catalog/controller/product/category.php я добавил текст атрибута к описанию. Не совсем то, что просили, но если надо выводить только атрибут -- думаю, несложно догадаться, как это сделать (заменить строчку на $descr_plaintext = $result['attribute_text'];), а несколько предыдущих строк там могут быть убраны. В общем, при наличии минимальных познаний или аккуратно методом тыка это будет несложно сделать, поэтому не описываю.

Изменения базируются на моём коде, а не чистом OpenCart v1.5: в этом месте была правка, но она задокументирована в упомянутой статье и минимальна. Поэтому, думаю, проблем с нахождением места и внесением изменений не возникнет.

Требуется заменить переменную $attr_id_to_descr = 0; на идентификатор своего атрибута, который должен выводиться. Его можно найти в админ-части магазина, внимательно изучив ссылку редактирования нужного нам атрибута: в адресе после токена (token=...) присутствует переменная ...&attribute_id=9 (например). Вот этот идентификатор и надо указать вместо нуля.

diff --git a/public_html/catalog/controller/product/category.php b/public_html/catalog/controller/product/category.php
index 54ad9bc..f94cc43 100644
--- a/public_html/catalog/controller/product/category.php
+++ b/public_html/catalog/controller/product/category.php
@@ -185,6 +185,8 @@ class ControllerProductCategory extends Controller {
                                {
                                        $descr_plaintext = mb_substr($descr_plaintext, 0, $cut_descr_symbols, 'UTF-8') . ' …';
                                }
+                               if( !empty($result['attribute_text']) )
+                                       $descr_plaintext .= '<hr />' . $result['attribute_text'];
                                $this->data['products'][] = array(
                                        'product_id'  => $result['product_id'],
                                        'thumb'       => $image,
diff --git a/public_html/catalog/model/catalog/product.php b/public_html/catalog/model/catalog/product.php
index 595bfc6..2b19a72 100644
--- a/public_html/catalog/model/catalog/product.php
+++ b/public_html/catalog/model/catalog/product.php
@@ -11,13 +11,40 @@ class ModelCatalogProduct extends Model {
            $customer_group_id = $this->config->get('config_customer_group_id');
        }   
                
-       $query = $this->db->query("SELECT DISTINCT *, pd.name AS name, p.image, m.name AS manufacturer, (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$customer_group_id . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$customer_group_id . "' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special, (SELECT points FROM " . DB_PREFIX . "product_reward pr WHERE pr.product_id = p.product_id AND customer_group_id = '" . (int)$customer_group_id . "') AS reward, (SELECT ss.name FROM " . DB_PREFIX . "stock_status ss WHERE ss.stock_status_id = p.stock_status_id AND ss.language_id = '" . (int)$this->config->get('config_language_id') . "') AS stock_status, (SELECT wcd.unit FROM " . DB_PREFIX . "weight_class_description wcd WHERE p.weight_class_id = wcd.weight_class_id AND wcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS weight_class, (SELECT lcd.unit FROM " . DB_PREFIX . "length_class_description lcd WHERE p.length_class_id = lcd.length_class_id AND lcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS length_class, (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT COUNT(*) AS total FROM " . DB_PREFIX . "review r2 WHERE r2.product_id = p.product_id AND r2.status = '1' GROUP BY r2.product_id) AS reviews FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) LEFT JOIN " . DB_PREFIX . "manufacturer m ON (p.manufacturer_id = m.manufacturer_id) WHERE p.product_id = '" . (int)$product_id . "' AND pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'");
-       
+       $attr_id_to_descr = 0;
+       if( 0 != $attr_id_to_descr )
+       {
+           $sql_attr1 = " p.product_id AS product_id, pa.text as attribute_text, ";
+           $sql_attr2 = " LEFT JOIN " . DB_PREFIX . "product_attribute pa ON (p.product_id = pa.product_id AND pa.attribute_id=" . $attr_id_to_descr .')';
+       }
+       else
+       {
+           $sql_attr1 = "";
+           $sql_attr2 = "";
+       }
+       $query = $this->db->query("SELECT DISTINCT *, pd.name AS name, p.image, m.name AS manufacturer,". $sql_attr1
+           ." (SELECT price FROM " . DB_PREFIX . "product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '" . (int)$customer_group_id . "' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount,"
+           ." (SELECT price FROM " . DB_PREFIX . "product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '" . (int)$customer_group_id . "' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special,"
+           ." (SELECT points FROM " . DB_PREFIX . "product_reward pr WHERE pr.product_id = p.product_id AND customer_group_id = '" . (int)$customer_group_id . "') AS reward,"
+           ." (SELECT ss.name FROM " . DB_PREFIX . "stock_status ss WHERE ss.stock_status_id = p.stock_status_id AND ss.language_id = '" . (int)$this->config->get('config_language_id') . "') AS stock_status,"
+           ." (SELECT wcd.unit FROM " . DB_PREFIX . "weight_class_description wcd WHERE p.weight_class_id = wcd.weight_class_id AND wcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS weight_class,"
+           ." (SELECT lcd.unit FROM " . DB_PREFIX . "length_class_description lcd WHERE p.length_class_id = lcd.length_class_id AND lcd.language_id = '" . (int)$this->config->get('config_language_id') . "') AS length_class,"
+           ." (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating,"
+           ." (SELECT COUNT(*) AS total FROM " . DB_PREFIX . "review r2 WHERE r2.product_id = p.product_id AND r2.status = '1' GROUP BY r2.product_id) AS reviews"
+           ." FROM " . DB_PREFIX . "product p"
+           ." LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)"
+           ." LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)"
+           ." LEFT JOIN " . DB_PREFIX . "manufacturer m ON (p.manufacturer_id = m.manufacturer_id)"
+           . $sql_attr2
+           ." WHERE p.product_id = '" . (int)$product_id . "' AND pd.language_id = '" . (int)$this->config->get('config_language_id')
+           ."' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'");
+
        if ($query->num_rows) {
            return array(
                'product_id'       => $query->row['product_id'],
                'name'             => $query->row['name'],
                'description'      => $query->row['description'],
+               'attribute_text'   => ( (0 == $attr_id_to_descr) ? '' : $query->row['attribute_text'] ),
                'meta_description' => $query->row['meta_description'],
                'meta_keyword'     => $query->row['meta_keyword'],
                'model'            => $query->row['model'],

Opencart 1.5.x: (catalog) Как добавить сортировку по производителю в каталоге товаров

- Posted in Uncategorized by

Примечание: вообще-то пока сделал сортировку не по имени, а по ID производителей: нам этого сейчас хватает. Чтобы сделать именно по названию, нужно небольшое дополнение. Возможно, добавлю его позже.

Изменяемые файлы:

catalog/controller/product/category.php

catalog/language/russian/product/category.php

catalog/model/catalog/product.php

Изменения (diff):

diff --git a/public_html/catalog/controller/product/category.php b/public_html/catalog/controller/product/category.php
index 9ef6331..54ad9bc 100644
--- a/public_html/catalog/controller/product/category.php
+++ b/public_html/catalog/controller/product/category.php
@@ -260,6 +260,19 @@ class ControllerProductCategory extends Controller {
                'value' => 'p.model-DESC',
                'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.model&order=DESC' . $url)
            );
+
+           $this->data['sorts'][] = array(
+               'text'  => $this->language->get('text_manufacturer_asc'),
+               'value' => 'p.manufacturer_id-ASC',
+               'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.manufacturer_id&order=ASC' . $url)
+           );
+
+           $this->data['sorts'][] = array(
+               'text'  => $this->language->get('text_manufacturer_desc'),
+               'value' => 'p.manufacturer_id-DESC',
+               'href'  => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=p.manufacturer_id&order=DESC' . $url)
+           );
+
            
            $url = '';
    
diff --git a/public_html/catalog/language/russian/product/category.php b/public_html/catalog/language/russian/product/category.php
index 4e28d8c..762c91e 100644
--- a/public_html/catalog/language/russian/product/category.php
+++ b/public_html/catalog/language/russian/product/category.php
@@ -1,5 +1,5 @@
-<?php
-// Text
+<?php
+// Text
 $_['text_refine']       = 'Уточнение поиска';
 $_['text_product']      = 'Товары';
 $_['text_error']        = 'Категория не найдена!';
@@ -25,5 +25,7 @@ $_['text_rating_asc']   = 'Рейтинг (начиная с низкого)';
 $_['text_rating_desc']  = 'Рейтинг (начиная с высокого)';
 $_['text_model_asc']    = 'Модель (А- Я)';
 $_['text_model_desc']   = 'Модель (Я - А)';
+$_['text_manufacturer_asc']    = 'Производитель (А- Я)';
+$_['text_manufacturer_desc']   = 'Производитель (Я - А)';
 $_['text_limit']        = 'Показать:';
 ?>
\ No newline at end of file
diff --git a/public_html/catalog/model/catalog/product.php b/public_html/catalog/model/catalog/product.php
index c963f3e..8d90fc6 100644
--- a/public_html/catalog/model/catalog/product.php
+++ b/public_html/catalog/model/catalog/product.php
@@ -68,7 +68,7 @@ class ModelCatalogProduct extends Model {
        $product_data = $this->cache->get('product.' . $cache . '.' . $customer_group_id);
        
        if (!$product_data) {
-           $sql = "SELECT p.product_id, (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'"; 
+           $sql = "SELECT p.product_id, p.manufacturer_id, (SELECT AVG(rating) AS total FROM " . DB_PREFIX . "review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'"; 
            
            if (isset($data['filter_name']) && $data['filter_name']) {
                if (isset($data['filter_description']) && $data['filter_description']) {
@@ -113,7 +113,8 @@ class ModelCatalogProduct extends Model {
                'p.price',
                'rating',
                'p.sort_order',
-               'p.date_added'
+               'p.date_added',
+               'p.manufacturer_id'
            );  
            
            if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {

Eclipse PDT и Ubuntu

- Posted in Uncategorized by

Eclipse - монстрообразинко. Шевелится неторопливо, интерфейс разлапистый и на любителя. Сперва поставил полный (sudo apt-get install eclipse), а из него - последний доступный PDT (3.x.x) через Help - Install new software. Получил постоянные ошибки при попытках открыть PHP файлы, доустановил какой-то WST (на него были намёки в сообщениях об ошибках). Никаких изменений в лучшую сторону.

Вчера не выдержал, удалил всё и попробовал ограничиться малым: оставил только минимум эклипса (sudo apt-get remove eclipse && sudo apt-get autoremove && sudo apt-get install eclipse-platform), а PDT взял с Galileo репозитория (там только 2.x.x какая-то версия доступна, слово Galileo присутствовало на заставке Эклипса при запуске, хотя второй репозиторий не сам же собой появился). Наконец-то после всех его рестартов увидел Эклипс в работоспособном состоянии. Хотя на некоторых PHP файлах его всё равно плющит (например, он не может открыть index.php из приложения Yii фреймворка).

Поживёт пока. Знакомство с Yii Framework пока только добавляет плюсов к впечатлениям о CodeIgniter. С Eclipse пользоваться и изучать Yii и всю его перенавороченную иерархию странностей будет полегче, надеюсь.

chive - MySQL database management tool

- Posted in Webdev by

Chive, alternative to PHPMyAdmin : World Gone Web

chive - MySQL database management tool: http://www.chive-project.com/

Chive is a next generation MySQL database management tool. The web-based user interface supports most of the common operations needed by software developers and database admins (databases, tables, indices, keys, triggers, views, routines, privileges management, import/export).

Chive aims to be an alternative to phpMyAdmin.

Бекап, контроль изменений и откат на стабильные конфигурации &quot;/etc&quot; в Linux&apos;е с помощью Git

- Posted in Uncategorized by

Как говорят, если вас посетила гениальная мысль -- в линукс-сообществе это уже давно реализовано или создаётся.

Решил добавить /etc в Git-репозиторий, чтобы получить все плюшки контроля версий. И, разумеется, оказалось, что я не слишком оригинален :)

Более подробно для интересующихся и сомневающихся это уже подробно описано ранее Антоном Чернышовым в статье Управление каталогом /etc с использованием tar и git.

<

p>См. также:

Распробовал Git

- Posted in Uncategorized by

Распробовал Git: он действительно оказался во многом гораздо удобнее, чем SVN. В первый день мне не очень понравилась большая, чем в Subversion, атомарность действий и необходимость каждый раз добавлять изменённые файлы в коммит. Я понимал, что это сулит и чем может быть полезно, но сперва показалось неудобным: ты машина — ты и следи/добавляй, раз всё известно, зачем мне лишняя рутина? Позже у коммита обнаружился ключ -a вдобавок к "git add .", так что по этому поводу ворчать стало некуда. Ну а потом всё-таки понравился этот мелочный контроль (можно некоторые файлы держать у себя изменёнными для экспериментов и не пускать их в репозиторий).

Что нравится и заметно в первую очередь в Git после SVN, так это:

  1. деление на оффлайн и онлайн работу: здесь можно комфортно коммитить сколько угодно локально, затем слить всё пачкой из дома или из офиса. Мне как любителю работать с ноутбуком и нелюбителю зря переплачивать за мобильный трафик это очень удобно (хотя основная причина скорее быстрая разрядка батарей телефона при постоянном или частом использовании GPRS/EDGE/3G). См. также пункт 5 этого списка;
  2. служебных папок нет по всему дереву каталогов (как в SVN), есть только одна в корне проекта (репозитория). При работе с SVN приходилось перед массовой заливкой на сервер не забывать очищать дерево каталогов от этих .svn -- и места занимают прилично, да и не дело их на сервере держать. А если и держать, то надо не забывать блокировать через .htaccess. См. также пункт 5;
    • в SVN локальная рабочая копия очень жёстко привязана к абсолютному пути на диске, поэтому любая попытка скопировать или перенести папки внутри копии обычными средствами, а не командами SVN, гарантируют массу приключений и неприятных открытий;
  3. branch и merge устроены гораздо проще и логичней -- пользоваться ими хочется сразу же. В SVN они вроде бы тоже есть, но столько лишнего надо в голове держать, что писать километровые пути просто сил никаких нет. В итоге при работе в командах до десятка человек мы работали только с транком и пользовались буквально 3 командами: checkout первый раз и update/commit в процессе. Хватало. Но git branch -- это очень даже. Концепция и сценарии работы очень понравились, они гораздо удобней и при самостоятельной работе, и для 2 человек. Не говоря уже про более обширные команды;
  4. простота и удобство создания репозиториев: буквально зашёл в папку с проектом, git init && git add . && git commit -m 'initial commit' -- и вот у нас уже новый репозиторий. Не связанный пока никак с онлайн, но зато уже сразу можно работать с кодом, удобно следить за изменениями и пользоваться ветками. Процесс заведения репозиториев в SVN у меня был гораздо дольше, ну и онлайн в случае SVN обязателен, что для меня далеко не всегда плюс: иногда это здорово мешает. Так что я очень доволен этой разницей.
  5. служебные файлы SVN занимают столько же места, сколько и отслеживаемые, удваивая таким образом объём папки проекта (было 100 мегабайт - стало 200). Что с ветками - не знаю, не пользовался ими под SVN. Репозиторий Git'а раза в 2 с хвостиком МЕНЬШЕ отслеживаемого проекта. Из очень приятного: этот репозиторий (папку .git в корне проекта) очень легко сбекапить или перенести на другой компьютер, где его можно восстановить даже в глухой деревне без онлайна (git checkout master -- и из пустоты рядом с .git мгновенно возникает весь проект). См. также пункты 1 и 2.

Есть и существенный недостаток. При использовании Git каждый человек держит у себя всю копию репозитория. У нас при работе в Proxistep была актуальна проблема больших графических файлов. С ними в команде работал обычно один, от силы два человека: художник-дизайнер и верстальщик. И верстальщику в итоге нужна, условно говоря, всего одна картинка после всех согласований с клиентом. А дизайнеру совершенно не нужен код. А остальным разработчикам (3-4 человека) -- дизайн. Наблюдать и выкачивать все эти изменения и версии дизайна было неудобно и тяжело. Это тормозило и было большинству команды совершенно неинтересно, отнимало время, а в некоторых проектах - весьма заметное место на диске. К тому же обычным состоянием разработчика являлось участие в нескольких текущих проектах и часть недавних проектов тоже лежала в состоянии быстрой готовности.

Сейчас, конечно, полегче - скорости доступа к интернет заметно выросли и объёмы HDD растут год от года. Но иногда это может стать проблемой.

SVN в принципе способен частично решить эту проблему: в нём, в отличие от Git, можно делать checkout-ы и commit-ы отдельных папок репозитория, поэтому на первый взгляд достаточно всего лишь разумно разделить по каталогам работу. Проблема лишь в том, что некоторым ролям нужны разные наборы каталогов, и если кто-то оказался "на стыке", сделать одним коммитом изменения в 2 разных каталогах уже не получится: придётся видеть в общем репозитории 2 коммита вместо одного. Проблема на самом деле мелкая и скорее эстетическая, но на всякий случай стоит иметь в виду.

Для повседневной работы мне хватает с головой командной строки git'а и Meld для сравнения, но на всякий случай скажу про знакомые мне GUI инструменты для работы с Git:

  • RabbitVCS поддерживает и SVN, и Git;
  • Giggle гораздо приятнее глазу, чем gitk.

Полезные материалы для начинающих знакомство с Git:

  • Git - SVN Crash Course — для тех, кто мигрирует с SVN на Git; таблицы соответствия для быстрого старта и укладывания в голове аналогий
  • http://progit.org/book/ru/ — хороший перевод об устройстве и логике работы Git; кратко, последовательно и понятно, без "воды" и лирических отступлений
  • http://habrahabr.ru/blogs/development/68341/ — одна из самых понятных и кратких статей о правильной организации коллективной работы над проектами с использованием Git
  • http://help.github.com/git-cheat-sheets/
  • Git-SVN Comparison

И не забудьте про git-svn! Этот пакет даёт нам в распоряжение такую замечательную команду, как git svn clone <SVN_repo_URL> /path/to/git/repo, которая позволит создать Git-репозиторий из SVN-репо, сохранив всю историю коммитов. Безусловно полезная при миграции вещь.

Знакомлюсь с Git и Yii Framework

- Posted in Uncategorized by

Пригласили в проект, где используется Git VCS и Yii Framework. Поэтому на некоторое время объявляю себя потерянным для мира, но открытым для полезной информации по этим темам. Советуйте, если есть что-то полезное на ваш взгляд.

Yii обещает прям какую-то гигантскую производительность. Пока ничего такого не заметил: имеющаяся минимальная заготовка проекта на Yii на глаз шевелится медленней моих CodeIgniter проектов, местами более нагруженных неоптимальными запросами (о которых я знаю и в планах стоит поправить логику в нескольких местах, но и без этого работает замечательно. Даже у хостера, который пока отказывается включть mod_deflate у апача).

См. также: Первые впечатления о Git в сравнении с SVN.

PayPal?! Но у меня нет PayPal! Как заплатить?!

- Posted in Uncategorized by

Через Paypal можно заплатить человеку, даже если у вас самих нет счёта в PayPal. Достаточно всего лишь пластиковой карты, которой можно расплачиваться в интернет. А это есть наверное у каждого в наше время.

К сожалению, платёжный интерфейс пайпэла не очень-то очевиден и удобен, поэтому немного опишу процесс. Кнопку Donate можно использовать для перечисления любой удобной вам суммы. Если нажать на неё, удерживая при этом на клавиатуре Shift, то окно Paypal откроется в новом окне: возможно, так вам будет удобнее изучить, что к чему.

  1. Первую же страницу, которая появляется после нажатия кнопки Donate, надо прокрутить вверх: в расположенной там форме надо просто ввести сумму (Donation Amount), которую хотите перевести человеку (что за человек - более-менее понятно по его ID в левом верхнем углу: в моём случае это адрес почты на GMail) и нажать кнопку Update Totals.
  2. Теперь в левой части страницы более чётко видны эмблемы популярных платёжных карт. Нам именно туда и надо: рядом с ними находится надпись на английском, перевод которой звучит так: "У Вас нет счёта в PayPal? Используйте кредитную/дебетовую карту или банковский перевод (там, где он доступен)". Дело в том, что для разных стран доступны разные варианты осуществления платежа, но пластиковая карта как наиболее распространённый способ обычно доступен повсеместно. Так вот, самая главная ссылка расположена здесь и является наверное самой незаметной на странице: нажимаем на Continue.
  3. Попадаем на более знакомо выглядящую страницу. Осталось выбрать вашу страну...
  4. И вот наконец-то можно выбрать более удобный язык интерфейса (в правом верхнем углу)
  5. Ну а дальше всё более-менее очевидно и понятно

Думаю, дальше пояснения не требуются. Если вы просто экспериментировали и всё стало понятно, можно закрыть страшную страницу. Или перечислить мне мешок денег :)