Как носитель арабского языка, я работал на многоязычных веб-сайтах ранее, некоторые уже существовали с поддержкой CSS LTR (слева направо), и мне тогда пришлось бы добавить поддержку RTL (справа налево), а некоторые проекты начались с нуля. До того, как я начал использовать Sass и Grunt, поддержка обоих направлений была кошмаром и трата времени с большим количеством повторений кода.
При работе над многоязычными проектами, использующими оба направления, важно написать CSS, который бы поддерживал RTL и LTR эффективным, автоматизированным и динамичным способом, чтобы нам не приходилось повторять или переопределять CSS.
Разница между этими двумя направлениями в целом и в большинстве случаев заключается в направлении перемещения, выравнивании текста, заполнении и значениях полей.
Проблема
Давайте посмотрим, как поддержка RTL и LTR в одном проекте может быть немного громоздкой на практике, и как мы можем решить эту проблему. В некоторых случаях, перед добавлением поддержки направления, мы добавляем новый CSS-файл в заголовок и начинаем переопределять и повторять код снова и снова, чтобы изменить некоторые свойства CSS, такие как floats
, padding-left
или text-align
для разных компонентов.
Допустим, это код для языкового шаблона RTL, мы добавили атрибут lang="ar"
для языковой поддержки, значение этого атрибута, вероятно, будет динамически изменяться в зависимости от определения языка на стороне сервера.
<!DOCTYPE html> <html lang="ar"> <head> <link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/rtl-app.css"> </head> <body> <main>Main contant</main> <aside>Sidebar</aside> </body> </html>
в<!DOCTYPE html> <html lang="ar"> <head> <link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/rtl-app.css"> </head> <body> <main>Main contant</main> <aside>Sidebar</aside> </body> </html>
Компоновка требует, чтобы в нормальном направлении (LTR) main
раздел был перемещен влево, а в aside
— вправо.
/* app.css */ main { float: left; } aside { float: right; }
Теперь для направления RTL мы должны сделать то же самое выше, но в противоположном направлении или для зеркального отображения макета, это будет код для переопределения исходного стиля в том же файле.
/* app.css */ [lang='ar'] main { float: right; } [lang='ar'] aside { float: left; }
или в новом CSS-файле, добавленном в заголовок (как в примере выше), мы можем сделать это так.
/* rtl-app.css */ main { float: right; } aside { float: left; }
Проблема здесь в том, что мы пишем больше кода для переопределения исходного кода, загружая более одного файла CSS. Это не очень хорошая практика и отнимает много времени.
Теперь, как мы можем улучшить этот рабочий процесс, решение, которое я использовал, заключается в использовании препроцессора CSS, такого как Sass, и обработчика задач JavaScript, такого как Grunt, для автоматизации и улучшения рабочего процесса.
Настройка Grunt
Используя Grunt и Sass, мы можем автоматизировать и решать имеющиеся у нас проблемы. Теория здесь заключается в том, чтобы записать наши стили в один основной файл, а затем сгенерировать два других файла для каждого направления, а затем включить каждый файл в заголовок на основе используемого языка.
Задача Grunt, используемая для компиляции Sass в CSS, является grunt-sass .
{ "name": "rtl-sass-grunt", "version": "0.1.0", "devDependencies": { "grunt": "^0.4.5", "grunt-sass": "^0.16.1" } }
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), sass: { dist: { files: { 'css/ltr-app.css': 'scss/ltr-app.scss', 'css/rtl-app.css': 'scss/rtl-app.scss' } } } }); grunt.loadNpmTasks('grunt-sass'); grunt.registerTask('default', ['sass']); };
Задача Sass берет два файла, один для ltr-app.scss
и rtl-app.scss
затем генерирует из них файлы CSS. В обоих файлах мы определим некоторые переменные для поплавков и направлений, а затем импортируем основной файл Sass в конце.
файл ltr-app.scss
// LTR languages directions. $default-float: left; $opposite-float: right; $default-direction: ltr; $opposite-direction: rtl; // Import the main style @import 'style';
И rtl-app.scss
// RTL languages directions. $default-float: right; $opposite-float: left; $default-direction: rtl; $opposite-direction: ltr; // Import the main style @import 'style';
Мы можем включить эти переменные во внешние файлы, но это только для того, чтобы сделать вещи более понятными и дать вам основную идею.
style.scss
будет включать все наши CSS или другие файлы проекта. Этот файл будет импортирован как в ltr-app.scss
и в rtl-app.scss
.
И это пример того, как выглядит style.scss
.
body { direction: $default-direction; } .media { float: $default-float; padding-#{$opposite-float}: 10px; } .button { background-image: url("images/arror-#{default-float}.png"); }
Мы использовали переменные Sass, такие как $default-float
и Sass интерполяция в padding-#{$opposite-float}
, тогда Grunt может позаботиться об этом и сгенерировать два файла:
/* ltr-app.css */ body { direction: ltr; } .media { float: left; padding-right: 10px; } .button { background-image: url(images/arror-left.png); }
/* rtl-app.css */ body { direction: rtl; } .media { float: right; padding-left: 10px; } .button { background-image: url(images/arror-right.png); }
Хороший трюк, с которым я сталкивался ранее, это как добавить изображение с определенным направлением в качестве фона CSS, мы можем создать два изображения arror-left.png
и arror-right.png
и в коде Sass выше переменная будет меняться между left
и right
Настройка на стороне сервера
Для большей гибкости при работе над многоязычными проектами будет важно настроить серверную часть для предоставления некоторых переменных для использования.
Что нам нужно от серверной части, так это определить аналогичные переменные, как мы это делали с Sass, но на этот раз мы будем использовать их внутри шаблонов или представлений. Каждое внутреннее решение должно быть в состоянии предоставить способ создавать эти переменные и передавать их в представлениях. Переменные, такие как def-float
и def-direction
.
Настройка внутренней конфигурации позволит нам переключаться между сгенерированными файлами CSS для обнаруженного направления.
<!DOCTYPE html> <html lang="lang"> <head> <%= if def-direction is ltr %> <link rel="stylesheet" href="css/ltr-app.css"> <%= else %> <link rel="stylesheet" href="css/rtl-app.css"> <%= end %> </head> <body> <main>Main contant</main> <aside>Sidebar</aside> </body> </html>
в<!DOCTYPE html> <html lang="lang"> <head> <%= if def-direction is ltr %> <link rel="stylesheet" href="css/ltr-app.css"> <%= else %> <link rel="stylesheet" href="css/rtl-app.css"> <%= end %> </head> <body> <main>Main contant</main> <aside>Sidebar</aside> </body> </html>
Или мы можем использовать переменную внутри самого имени файла CSS.
<link rel="stylesheet" href="css/#{def-direction}-app.css">
Выражение if и переменная имени файла — это просто псевдокод, и он будет зависеть от вашего механизма шаблонов и конфигурации на стороне сервера.
Работа с вспомогательными классами и шаблонами
При работе с вспомогательными классами, смешанными с файлами шаблонов, такими как HTML, erb или любой другой механизм шаблонов, нам необходимо динамически изменять имена классов в зависимости от направления, давайте рассмотрим пример.
<div class="text-left"> <!-- content --> </div>
.text-left { text-align: left; } .text-right { text-align: right; }
Содержимое div
всегда будет выравнивать содержимое по левому краю, так как оно принимает класс text-left
, но нам нужен способ динамического изменения части -right
на -right
для RTL.
Мы можем решить эту проблему, используя одну из наших переменных шаблона.
<div class="text-#{default-float}"> <!-- content --> </div>
Sass Mixins
Мы уже использовали переменные и интерполяции Sass, еще один способ сделать это проще — создать еще один набор миксинов Sass.
@mixin float($dir) { @if $dir == left { float: $def-float; } @else if $dir == right { float: $opp-float; } @else { float: $dir; } } @mixin text-align($dir) { @if $dir == left { text-align: $def-float; } @else if $dir == right { text-align: $opp-float; } @else { text-align: $dir; } } @mixin padding-left($unit) { padding-#{$def-float}: $unit; } @mixin padding-right($unit) { padding-#{$opp-float}: $unit; }
Позже мы можем использовать эти миксины, как это
.media { @include float(left); @include padding-right(10px); @include text-align(left); }
Если вы хотите больше миксов для разных CSS, на которые влияет LTR / RTL, вы можете взглянуть на bi-app-sass .
Вывод
Здесь мы обсудили, как создание многоязычных сайтов не должно означать, что мы повторяем фрагменты кода. Мы узнали, как мы можем работать с языками RTL и LTR, используя Sass. Мы создали несколько миксов, чтобы продемонстрировать, как мы это делаем, и обсудили, как мы можем получить бэк-энд, чтобы сделать вещи еще проще.
Вы можете использовать любой другой инструмент, кроме Grunt и Sass, чтобы делать то же самое, основная идея заключается в том, чтобы получить представление об использовании переменных Sass для манипулирования направлениями и изменения переменных в файлах шаблонов. Я создал репозиторий Github для этой статьи. Вы можете проверить код, используемый в rtl-grunt-sass .