Локализация html-страницы средствами CSS

    Люди по-разному относятся к CSS. Кто-то ворчит, что раньше и таблицы были зеленее, кто-то горячится, мол, дайте мне ваши таблицы, уж я их озеленю. Лично я довольно давно воспринимаю CSS-файлы как совего рода конфиги для внешнего вида веб-страницы. По сути ведь так и есть. У хорошего верстальщика HTML используется для того, чтобы создать структуру документа, у которой затем с помощью CSS настраивается внешнее отображение.

    Обычно под внешним отображением понимаются всякие красоты вроде изображений, круглых уголков, градиентиков и прочей вебдванольности. Однако основным средством передачи информации в Интернете до сих пор является их величество текст. Текст применяется везде: и в навигации по сайту, и в основной информации.

    Сейчас, когда космические сайты бороздят просторы мировой паутины, все чаще возникает потребность делать их многоязычными. Способов существует много. Под разные платформы, фреймворки и шаблонизаторы. Способ, который хочу предложить я, использует в качестве основы CSS.

    Идея проста. Все верстальщики, работающие с CSS знают о таком свойстве как content:;, которое применяется к псевдоэлементам :after и :before. Чаще всего с помощью «волшебного» сочетания :after и content:; реализуют clear для «плавающих» блоков. Но вообще в content:; можно писать абсолютно любой текст. Без тегов, правда, но это разумное ограничение.

    Как это можно использовать? Нужно создать два CSS-файла. Допустим, «en.css» и «ru.css». Основные стили блоков (цвета и прочие красивости) пусть определяются в файле «main.css».

    <!-- HTML-код -->
    
    <ul class="b-menu">
        <li class="b-menu__item b-menu__item_name_main"><span class="b-menu__curr"></span></li>
        <li class="b-menu__item b-menu__item_name_portfolio"><a class="b-menu__link" href=""></a></li>
        <li class="b-menu__item b-menu__item_name_team"><a class="b-menu__link" href=""></a></li>
        <li class="b-menu__item b-menu__item_name_contacts"><a class="b-menu__link" href=""></a></li>
    </ul>
    


    /* Содержание файла «main.css» *//**/
    
    .b-menu:after
    {
        content: '';
        display: block;
        clear: both;
    }
    
    .b-menu__item
    {
        float: left;
    }
    


    /* Содержание файла «en.css» *//**/
    
    .b-menu__item_name_main .b-menu__curr:after,
    .b-menu__item_name_main .b-menu__link:after
    {
        content: 'Main Page';
    }
    
    .b-menu__item_name_portfolio .b-menu__curr:after,
    .b-menu__item_name_portfolio .b-menu__link:after
    {
        content: 'Portfolio';
    }
    
    .b-menu__item_name_team .b-menu__curr:after,
    .b-menu__item_name_team .b-menu__link:after
    {
        content: 'Team';
    }
    
    .b-menu__item_name_contacts .b-menu__curr:after,
    .b-menu__item_name_contacts .b-menu__link:after
    {
        content: 'Contacts';
    }
    


    /* Содержание файла «ru.css» *//**/
    
    .b-menu__item_name_main .b-menu__curr:after,
    .b-menu__item_name_main .b-menu__link:after
    {
        content: 'На главную';
    }
    
    .b-menu__item_name_portfolio .b-menu__curr:after,
    .b-menu__item_name_portfolio .b-menu__link:after
    {
        content: 'Портфолио';
    }
    
    .b-menu__item_name_team .b-menu__curr:after,
    .b-menu__item_name_team .b-menu__link:after
    {
        content: 'Команда';
    }
    
    .b-menu__item_name_contacts .b-menu__curr:after,
    .b-menu__item_name_contacts .b-menu__link:after
    {
        content: 'Контакты';
    }
    


    Дальше нужно просто подключить файлы в таком порядке: main.css, en.css, ru.css. Ну, или сначала ru.css, а en.css — потом. В зависимости от того, какой язык является основным. В принципе, ничто не мешает CSS-свойства по умолчанию запихнуть в main.css, а подключать только файл языка, выбранного пользователем. Я разбил на два файла исключительно для наглядности.

    Плюсы:

    + Данный способ поддерживается всеми современными браузерами, включая IE восьмой и девятой версии, в том числе мобильными браузерами под iPhone и Android;

    + CSS-файл кешируется браузером, а это значит, что будучи скачанным однажды, он будет храниться у пользователя локально довольно долго (фактически пока с сервера не придет заголовок, сигнализирующий о необходимости обновить кеш);

    + Не нужно перегружать страницу, чтобы применить требуюемую локаль. Достаточно просто яваскриптом изменить href у тега <link>. Или создать новый тег <link> с нужным href.

    Минусы (их, к сожалению, больше):

    – ИЕ до восьмой версии не понимает свойство content:;, как и некоторые мобильные браузеры;

    – Поисковые движки вряд ли проиндексируют тексты, записанные таким образом;

    – Есть ряд ограничений к содержимого CSS-свойства content;

    – Чтобы упорядочить названия классов для плейсхолдеров при более-менее сложном лэйауте, придется делать их довольно длинными (даже если не использовать BEM-названия);

    – Невозможность сохранять длинные тексты с форматированием и изображениями.

    P.S:

    На новизну идеи совершенно не претендую.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 60
    • +16
      Весьма оригинальный подход, но
      Поисковые движки вряд ли проиндексируют тексты, записанные таким образом
      — весомый минус.
      • +1
        ну почему-же? может наоборот стоит таким способом скрывать меню и другие не важные для контента вещи от поисковиков? тогда и по основным словам в статье будет находиться лучше.
        • +3
          Достойно отдельной статьи «прячем меню от поисковика». Даже если поисковик захочет сканировать пустые теги ссылок, то, чтобы отобразить при выдаче краткий список разделов, ему придется хорошенько постараться.
          • 0
            Зачем только меню? Напишите «прячем ссылки от поисковиков» и тогда их грязные железные ножки не наследят в дебрях сайта, где не ступала нога браузера.
          • +1
            Боюсь, что это один из наиболее весомых минусов.
            • +1
              присковики и js не могли долгое время сканировать, и pdf не читали итп.
              Если применять технику активно, поисковики первые, кто подтянется. Точнее первым будет гугл, а остальные тут же схавают технику.
              • +1
                вопрос, захочется ли именно вам (или вашему клиенту) быть первым
            • НЛО прилетело и опубликовало эту надпись здесь
              • +16
                Только отбились от оформления в HTML, так теперь норовят сам контент в CSS засунуть. Вот скажите, зачем забивать гвозди микроскопом? content предназначен для автоматических счётчиков и всяких разных меток, для оформления наконец. Никакого основного контента там быть не должно!
                • –1
                  Основной контент в него запихнуть и не получится. Хотя бы из-за разметки (болд, италик). А вот некоторые навигационные элементы… почему бы и нет? Если, например, названия классов сделать сокращенными, то вполне можно таким макаром сверстать какой-нибудь мобильный интерфейс в целях экономии траффика. Насколько мне известно, и мобильный Сафари, и мобильный Хром умеют кешировать CSS-файлы.
                  • +8
                    Италик не проблема. Проблема в том, что это неправильно. Точно так же, как и применение классов типа .bold .float-left и т.п.
                    • +1
                      Я предпочитаю оценивать правильность или неправильность конкретного решения исходя из условий поставленной задачи.
                      • +1
                        Довольно странно отдавать мобильному браузеру английский html и русский css вместо русского html. Какая-то неправильная экономия.
                        • 0
                          Что такое «русский хтмл»?
                          • +1
                            Русский текст в html.

                            А, я упустил из виду, что html-то пустой будет. Тогда да, трафик экономится. Но и проблемы с доступностью возникают. Наверняка не все мобильные браузеры поддерживают content.

                            И ещё возникает проблема поддержки. Редактировать html (визуально) может любой. Для редактирования css нужен уже более подготовленный человек.
                            • 0
                              Старые мобильные браузеры действительно могут не поддерживать content. Я это упомянул среди минусов. Мобильные Хром и Сафари точно поддерживают. Насчет браузера, встроенного в Мобильную Винду не знаю. Не было пока возможности проверить.

                              Что до редактирования, если бы я всерьез озаботился подобным методом, то сделал бы редактирование полей через админку, чтобы цсс-файлы генерировались по шаблону автоматически. Но в целом с замечанием согласен.
                              • 0
                                А у Оперы Мини как с этим дела?

                                Это опять же создаст проблемы и для разработчика, и для редактора. Научить человека делать что-то сверх того, чем он занимается постоянно, бывает весьма сложно. Панельки в Ворде и то не все умеют настраивать :(
                                • 0
                                  На iPhone Opera Mini свойство content поддерживает. Вряд ли на других платформах с этим браузером ситуация обстоит иначе.
                              • 0
                                мобильный хром?
                                • +2
                                  Я так зову браузер, встроенный по умолчанию в Андроид.
                      • –7
                        А почему вы считаете не правильным применение таких классов? Создав класс .red весьма удобно его применять везде, где надо сделать текст красным, и не плодя при этом дополнительные классы.
                        • +6
                          Во-первых, на все цвета и случаи классов не напасешься.

                          Во-вторых, за пять лет работы с большими проектами я убедился, что удобнее все-таки мыслить блоками, а не свойствами элемента. Удобнее с точки зрения дальнейшей поддержки кода.

                          Использование подобных классов будет относительно оправдано на небольших проектах с небольшим количеством блоков и сущностей. Как мне кажется, возможно, я ошибаюсь.
                          • +2
                            А потом окажется, что кое-где надо красный сделать зелёным.
                            Вы полезете в вёрстку? Или .red{color:green} напишите?

                            Правильно — когда классы означают природу объекта.
                            .error .message .breadcrumb .front .row .node .node-product — правильно
                            .row-odd .row-even .last .first — костыльно, но допустимо, псевдоклассы ещё не все изобрели.
                            .right-corner и .left-corner — совсем костыльно, это, как правило, исключительно для оформления контейнеры, они хоть и означают то, чем являются, но в структуре документа совсем лишние сущности
                            .red .green .float — совсем неправильно.
                            • –1
                              >.row-odd .row-even .last .first — костыльно, но допустимо, псевдоклассы ещё не все изобрели
                              Вообще-то изобрели, но поддерживаются они не везде.
                              • 0
                                Если кто-то мне не верит, сильно рекомендую ознакомиться с селекторами CSS3. Там есть возможность выбирать и чётные, и нечётные, и первые, и последние элементы.
                    • +4
                      Зачем контент страницы хранить в CSS файлах 0_о
                      • –2
                        Например, в целях экономии трафика для мобильных интерфейсов. Один из вариантов.
                      • 0
                        Есть ещё один весомый плюс — частичное кеширование контента на стороне браузера!

                        И ещё отвечу сразу многим выше написавшим, что не надо мешать контент и оформление:
                        А вы положите этот каскадник отдельно от оформления — и не смешивайте их. Положите его в каталог locales, назовите его russian.css, если это для русских, а оформление храните отдельно. Раз не надо мешать — так и не мешайте =)
                        А индексировать поисковикам навигацию, например, и так не надо — они и сами пытаются её фильтровать. А таким образом локализовывать, допустим, статьи целиком — конечно не самый лучший вариант.
                        • +3
                          Можно еще чуть проще сделать и стопицот кроссбраузерно:

                          [style] .lang {display: none} body.ru lang.en, body.ru lang.ru {display: block} [/style]
                          [body class=«ru»]
                          [div class=«menuitem»]
                          [span class=«lang en»]Menu[/span][span class=«lang ru»]Меню[/span]
                          [div/]

                          зы: Но все-таки микроскоп надо беречь :)
                          • +1
                            html[lang=«ru»]

                            Старик Резо говорил, что лишних сущностей не стоит плодить.
                        • +6
                          Милостивый Аполлон, сжалься и ослепи меня своими стрелами.
                          • +3
                            А как насчет локализации с помощью DTD?
                            • 0
                              Можно пример?
                              • +6
                                Извольте:) Для этого достаточно открыть в FF страницу about:mozilla и посмотреть, как она устроена.

                                Кстати, в этом варианте нет проблемы с <em/>.
                                • 0
                                  Хм. Занятно, спасибо за наводку.
                            • +1
                              Подход интересный, но имеет очень ограниченное применение. Локализация — это не только меню, но и все тексты на сайте. А они часто берутся из БД. В этом случае CSS для перевода не помощник.
                              • 0
                                Конечно. Данный способ с моей точки зрения подходит (если вообще подходит) лишь для локализации элементов дизайна. Меню, вспомогательные ссылки.

                                Локализовать таким макаром контент страницы во-первых, довольно неудобно по ряду причин, а во-вторых, не имеет смысла. Дело в том, что меню на сайте на всех страницах +– одинаковое. Именно поэтому его имеет некоторый смысл кешировать через CSS-файл. Содержимое же страниц у нормального сайта уникально.
                              • +1
                                а мне кажется, это охуенно
                              • +1
                                Вы скорее всего перепутали XSLT (eXtensible Stylesheet Language Transformations), созданный для преобразования содержимого с CSS (Cascading Style Sheets), созданный для оформления содержимого.
                                • –1
                                  С точки зрения оптимизации файлы css, которые нельзя склеить — зло. Хотя есть альтернативные link и прочее, лучше работать через класс для body и иметь классы в соответствующих «локалях»:

                                  body.lang_en .b-menu__item_name_main .b-menu__curr:after,
                                  body.lang_en .b-menu__item_name_main .b-menu__link:after
                                  {
                                      content: 'Main Page';
                                  }
                                  
                                  body.lang_ru .b-menu__item_name_main .b-menu__curr:after,
                                  body.lang_ru .b-menu__item_name_main .b-menu__link:after
                                  {
                                      content: 'На главную';
                                  }
                                  


                                  Но это все равно фигня, поскольку как уже сказали локализация меняется вместе с контентом и менюшки в нем — ничтожная доля и не стоят отдельной работы и поддержки.
                                  • 0
                                    Можно и склеивать оба файла в «main.css» по принципу: впереди идет язык по умолчанию, затем подклеивается кастомный язык. Тогда файл будет один (соответственно, будет и один запрос).
                                    • –1
                                      lol, и как это прокэшировать? :)
                                      • 0
                                        Учитывая, что на выходе получится обычный css-файл, суть вопроса мне не очень понятна.
                                        • –1
                                          Разные пользователи, разные установки, разные файлы.
                                          Один main.css тут просто не получиться — его содержимое будет случайным :)

                                          Я молчу что зависимость от последовательности склейки — самое то по-геморроиться.
                                          • 0
                                            Создаем несколько «склеек»: main.ru.css, main.en.css, main.ua.css. Способов это сделать автоматически — вагон.

                                            Далее остается только получить из куки (ее все равно придется использовать) или из какого-либо иного источника две буковки, обозначающие язык. И соорудить с помощью используемого шаблонизатора конструкцию <link href="/css/main.{% lang %}.css"/>.

                                            Тот файл, который получится, будет закеширован браузером пользователя.
                                            • –1
                                              Ага и получаем несколько разных сборок css, конечно же столько же вариантов html на один запрос и получаем кэш разбухший в несколько раз и вследствие этого в несколько раз больше нагрузку на сервер :)

                                              Продолжайте наступать на чужие грабли. Учиться исключительно на своем — это национальный спорт!
                                              • 0
                                                Чего я никогда не мог понять в людях, так это подобных язвительных пожеланий. Ну, да и ладно.
                                  • +4
                                    Идея весьма интересная, но есть же принцип: «представление — html, оформление — css, поведение — javascript», который в данном случае нарушается.

                                    Но за поиск нестандартных решений автор топика явно заслужил похвал :)
                                    • +1
                                      Добавлю от себя по одному пункту к плюсам и минусам:
                                      — плюс (на мой взгляд): созданный средствами css текст — не «выделябельный», удобно копирастам, беспокоящимся за лёгкое копирование текста, не нужно городить скрипты для запрета выделения текста
                                      — минус: консольные браузера не понимают эти стилевые правила, отображается пустота.
                                      • 0
                                        — плюс (на мой взгляд): созданный средствами css текст — не «выделябельный», удобно копирастам, беспокоящимся за лёгкое копирование текста, не нужно городить скрипты для запрета выделения текста

                                        Он «выделябельный», если начинать выделять не с него, к тому же в IE и Opera он прекрасно копируется (в Opera к тому же это совсем обычный текст).
                                      • +1
                                        За оригинальность, несомненно, пятерка.
                                        Для статичных страниц может быть и можно применить, особенно если это страница-визитка верстальшика.
                                        Для динамических страниц малопригодно. Как, например, можно на css локализовать фразу «Осталось %d элементов» с учетом того, что на английском порядок слов будет другой? А если еще и параметр будет меняться скриптом на лету…
                                        Ну и переводить css придется руками, удобных инструментов для облегчения жизни еще нет.
                                        • 0
                                          >Ну и переводить css придется руками, удобных инструментов для облегчения жизни еще нет.

                                          конвертер из PO файлов — как два пальца.
                                        • 0
                                          а я такое полгода назад даже хотел сделать (для профилей на exp.io), но мне вовремя дали по рукам.

                                          основной профит от такого извращения в том, что некоторые страницы можно было вообще не рендерить, а отдавать готовый кеш из базы, который достается одним key-value запросом, если бы не чертова локализация менюшек.
                                          • +1
                                            • 0
                                              бессмыслица какая-то
                                              уж лучше XSLT применять, в т.ч. на стороне клиента
                                              • 0
                                                Боролись, боролись с таблицами. И тут на тебе, весь html в css… :-)
                                                • 0
                                                  Это бессмыслено, мы экономим каплю воды в океане, нежели думать о реальных экономиях. Ну и что мы тут съэкономим? Для вывода теста есть HTML, а для обрамления CSS другого не дано, и не надо.

                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                  Самое читаемое