Подтвердить что ты не робот

Эффективное развитие и поддержка широкомасштабного CSS для многоязычных сайтов

Рассмотрим этот сценарий: вы разрабатываете многоязычное веб-приложение. Если все языки, на которые вы ориентируетесь, являются либо LTR, либо RTL, вам не нужны правила CSS для языка. Однако, если ваши целевые языки представляют собой сочетание языков LTR и RTL, вам необходимо указать направление чтения страницы для каждого языка.

Если вы добавите dir='ltr' или dir='rtl' в элемент <body>, вы логически должны ожидать, что он должен сделать необходимую магию.

Однако вам действительно нужно переключить все настройки right и left в правилах, таких как text-direction и margin. Вам также необходимо изменить правила, такие как margin: 0 10px 0 20px; на margin: 0 20px 0 10px;

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

div.foo { margin-near: 100px; } 
/* This would be equivalent to margin-left in LTR, and margin-right in RTL */

div.bar { margin-far: 100px; } 
/* This would be equivalent to margin-right in LTR, and margin-left in RTL */

В сущности, во всех правилах/значениях, в которых вы можете в настоящее время ввести слово с привязкой left или right, вместо этого вы можете написать near или far.

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

4b9b3361

Ответ 1

Спустя примерно четыре года после публикации этого вопроса, эта потребность, наконец, будет адресоваться w3. https://drafts.csswg.org/css-logical/

Свойства, которые принимают значения физического направленного ключевого слова (сверху, внизу, влево или вправо) переопределены, чтобы также принять соответствующие поточно-относительные ключевые слова. В таких случаях относительный поток значения могут использоваться вместо соответствующих физических значений. Для свойства, которые принимают несколько ключевых слов, комбинации относительных потоков и физические значения не допускаются (если иное не указано в будущие спецификации).

Ответ 2

Так как вы изменили вопрос на предположение, а не на мысль.

Не совсем логично

Вы заявляете: "Если вы добавляете атрибут dir='rtl' или dir='ltr' к элементу <body> логически, вы ожидаете, что он совершит магию". Магия, по-видимому, заключается в преобразовании: "все right с left и все left с right в правилах, таких как text-direction и margin."

Однако я не согласен с тем, что во всех случаях то, что вы желаете, обязательно является логическим результатом. Существуют примеры использования text-direction и margin, которые не обязательно связаны с text-direction основного сайта. Для margin это кажется очевидным, так как много раз margin можно использовать для некоторой формы позиционирования элементов, совершенно не связанных с текстом. То, что text-direction не будет автоматически переворачиваться, может быть менее очевидным, но все же действительным. Предположим, у кого есть английский (LTR) сайт с цитатой из арабского языка (RTL). Теперь один преобразует основной язык на иврит (RTL), но все еще имеет цитату на арабском языке - это не должно автоматически переходить на LTR, поскольку это было бы неправильно.

Такие вещи, как плавающие элементы, абсолютно позиционированные элементы и т.д. (которые используют значения right и left), могут или не могут быть расположены так, как они есть из-за text-direction.

В основном, это сводится к тому, что, поскольку каждый разрабатывает сайт, который должен быть многоязычным, таким образом, который будет переворачиваться text-direction, на каждом этапе нужно продумать, что элемент должен делать на основе LTR или RTL.

Что это значит, на мой взгляд, CSS не имеет слабости. Любая слабость заключается в реализации дизайна.


Чистая человеческая мысль в дизайне

Таким образом, хорошим методом было бы выбрать ваше стандартное направление (скажем, LTR), и это будет ваш "базовый" план с прямым CSS.

Затем для элементов, которые вы хотите перевернуть из-за изменения RTL, вы кодируете дополнительный CSS для учета этого путем применения класса к <body> для таргетинга с помощью или с помощью селектора атрибутов типа body[dir=rtl]. Затем вы размышляете над каждым элементом, который вы производите, должен ли он быть затронут этим изменением, и если вы добавите css (с дополнительным указателем направления, добавляющим спецификацию для переопределения):

.someClass {
    color: red;
    margin: 0 10px 0 20px;
    float: right;
}

body[dir=rtl] .someClass {
    margin: 0 20px 0 10px;
    /* kept float as right */
}

.someOtherClass {
    border: 1px 10px 1px 1px;
    margin: 0 30px 0 50px;
    float: left;
}

body[dir=rtl] .someOtherClass {
    border: 1px 1px 1px 10px; /* changed border for text */
    margin: 0 50px 0 30px;
    float: right;
}

Здесь препроцессор, например LESS или SASS (SCSS ) (Дэйв упомянул LESS в своем ответе) может оказаться полезным (см. мое обновление ниже), но это все еще решение, которое требует предусмотрительности.

Если вы не хотите, чтобы код был пронизан избытком CSS

У вас может быть отдельная таблица стилей для RTL css, которая загружается в то время, когда сайт определен в этом конкретном направлении. Возможный недостаток этого заключается в том, что он отделяет "коммутационный" код от исходного кода, поэтому обслуживание может быть более сложным (хорошая документация комментариев об элементах, которые подвергнуты RTL-преобразованию в основном коде, может компенсировать это).


(ОБНОВЛЕНИЕ) Использование LESS для помощи?

Вот мысль о том, чтобы сделать процесс более кратким с помощью препроцессора, такого как LESS. В этом примере используются функции LESS 1.4 (в настоящее время в бета-версии).

Идея 1

  • Преимущество: сохраняет все значения, измененные на одно изменение селектора.
  • Недостаток: больше работы по кодированию значений в аргументах.

Создайте mixin, чтобы применить желаемый селектор к

.rtl(...) {
  //getting the number of arguments 
  //(weeding out nested commas in parenthesis to do it)
  //they are expected to be grouped in pairs of TWO, 
  //as (property, value, property, value, etc.)
  @mainArgs: @arguments;
  @numArgs: unit(`"@{mainArgs}".replace(/\([^)]*\)/g,"").split(',').length`);

  //keep everything in one selector
  body[dir=rtl] & {
     //start the loop at 1
    .rtlPropLoop(@numArgs);
  }
  //loop to change all properties
  .rtlPropLoop(@total; @index: 1; @prop: extract(@mainArgs, @index); @value: extract(@mainArgs, (@index + 1))) when (@index =< @total) {
      //need to define all properties that could be switched
      //I've done just four here

      .setProp(ML) { //margin left
        margin-left: @value;
      }
      .setProp(MR) { //margin right
        margin-right: @value;
      }
      .setProp(FL) { //float
        float: @value;
      }
      .setProp(TD) { //text direction
        text-direction: @value;
      }
     //... define more possible values to switch

      //call setProp
      .setProp(@prop);
      //continue loop
      .rtlPropLoop(@total, (@index + 2));
  }
  //end loop
  .rtlPropLoop(@total, @index) when (@index > @total)  {}
}

Затем используйте его по необходимости в других селекторах

.test {
  margin: 0 20px 0 10px;
  float: right;
  .rtl(ML, 20px, MR, 10px, FL, left);
}

.test2 a span {
  float: left;
  text-direction: rtl;
  .rtl(TD, ltr, FL, right);
}

Создание этого готового кода

.test {
  margin: 0 20px 0 10px;
  float: right;
}
body[dir=rtl] .test {
  margin-left: 20px;
  margin-right: 10px;
  float: left;
}
.test2 a span {
  float: left;
  text-direction: rtl;
}
body[dir=rtl] .test2 a span {
  text-direction: ltr;
  float: right;
}

Идея 2

  • Преимущество: позволяет использовать синтаксис, аналогичный тому, что вы хотите; может быть легко изменена для работы с LESS 1.3.3.
  • Недостаток: создает избыточный вывод css, если в одном селекторе изменяется несколько значений.

Создайте некоторые вспомогательные микшины с синтаксисом, как то, что вы ожидаете в CSS

//define global variable for opposite direction
@oppDir: rtl;

//generic helper mixins used inside other helpers
//to auto flip right/left values
.flipSides(left) {
  @newSide: right;
}
.flipSides(right) {
  @newSide: left;
}

//specific property helper mixins
.padding-near(@top, @right, @bottom, @left) {
  padding: @top @right @bottom @left;
  body[[email protected]{oppDir}] & {
    padding: @top @left @bottom @right;
  }
}
.margin-near(@top, @right, @bottom, @left) {
  margin: @top @right @bottom @left;
  body[[email protected]{oppDir}] & {
    margin: @top @left @bottom @right;
  }
}
.float-near(@side) {
  float: @side;
  .flipSides(@side);
  body[[email protected]{oppDir}] & {
    float: @newSide;
  }  
}

Используйте их для определения как ближнего, так и дальнего для каждого направления сразу

.test1 {
  .padding-near(10px, 30px, 2px, 40px);
  .margin-near(0, 10px, 0, 20px);
  .float-near(right);
}

.test2 {
  .float-near(left);
}

Создание этого готового кода (повторение примечания .test1 для противоположного направления)

.test1 {
  padding: 10px 30px 2px 40px;
  margin: 0 10px 0 20px;
  float: right;
}
body[dir=rtl] .test1 {
  padding: 10px 40px 2px 30px;
}
body[dir=rtl] .test1 {
  margin: 0 20px 0 10px;
}
body[dir=rtl] .test1 {
  float: left;
}
.test2 {
  float: left;
}
body[dir=rtl] .test2 {
  float: right;
}

Ответ 3

К сожалению, CSS работает над понятием левого и правого, и это правильное поведение. Есть инструменты, которые помогут вам с переносом CSS из LTR в RTL - тот, который я знаю, это CSS Janus, который будет переворачивать свойства -left/-right и больше.

Ответ 4

Я думаю, что если вы этого хотите, вы должны использовать что-то вроде lesscss.

В работе есть стандарт , но я не знаю о каких-либо браузерах, которые его поддерживают. Даже когда они это делают, скорее всего, он будет сдерживаться поддержкой старого браузера (но когда это не проблема?).

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

Ответ 5

Я использую таблицы стилей Closure, и этот материал так же прост, как флаг командной строки.

Я определяю все как LTR (используя direction:ltr, где необходимо), а затем используя --output-orientation=RTL во время компиляции, я получаю сгенерированный CSS-код для меня. Наконец, при определении языкового стандарта (на сервере) я также определяю CSS для ввода в мой шаблон.

Дополнительная информация о LR flipping in Closure находится в https://code.google.com/p/closure-stylesheets/#RTL_Flipping

Ответ 6

Для получения дополнительной информации об одном решении, которое попыталось преодолеть слабость с помощью SASS/LESS, проверьте http://anasnakawa.github.io/bi-app-sass/

Ответ 7

Через три года, задав этот вопрос, знаю, что я вижу тенденцию в использовании словарного логического направления вместо 4-направленных слов.

Логические свойства CSS теперь устраняют эту проблему. Модель Flex использует ключевые слова start/end Теперь Blink поддерживает ключевые слова start/end/before/after. e.i.

ul, menu, dir {
    -webkit-margin-before: 1em;
    -webkit-margin-after: 1em;
    -webkit-margin-start: 0px;
    -webkit-margin-end: 0px;
    -webkit-padding-start: 40px;
}