Локализация 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
                                    Спасибо, буду знать.
                                  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»]

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

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

                                    Локализовать таким макаром контент страницы во-первых, довольно неудобно по ряду причин, а во-вторых, не имеет смысла. Дело в том, что меню на сайте на всех страницах +– одинаковое. Именно поэтому его имеет некоторый смысл кешировать через CSS-файл. Содержимое же страниц у нормального сайта уникально.
                                    +1
                                    а мне кажется, это охуенно
                                      –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 другого не дано, и не надо.

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

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