有效开发和维护多语言网站的大规模CSS

PHP*_*Pst 19 css multilingual internationalization right-to-left

请考虑以下情形:您正在开发一个多语言Web应用程序.如果您要定位的所有语言都是LTR或者RTL,则不需要特定于语言的CSS规则.但是,如果您的目标语言是语言LTR和混合RTL语言,则需要为每种语言指定页面的阅读方向.

如果您添加dir='ltr'dir='rtl'<body>元素,你在逻辑上应该期望它应该做必要的魔法.

但是,您实际上需要切换规则中的所有rightleft设置,例如text-directionmargin.你还需要改变的规则一样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 */
Run Code Online (Sandbox Code Playgroud)

实质上,在您当前可以输入基于leftright基于方向的单词的所有规则/值中,您可以改为编写nearfar.

鉴于当前版本的CSS目前存在缺陷,我正在寻找一些建议来简化双向大型网络应用程序的创建维护.

Sco*_*ttS 7

既然你把问题改成了一个事先考虑而不是事后的想法.

不太合乎逻辑

你说,"如果你在逻辑上添加dir='rtl'dir='ltr'归属于<body>元素,那么你会期望它能够发挥作用." 魔术显然是要转换,"所有rightleft所有人left一起使用right的规则就像text-directionmargin."

但是,我并不同意在任何情况下你所希望的都是合乎逻辑的结果.有些实例text-directionmargin使用不一定与text-direction主站点有关.因为margin,这似乎是不言而喻的,因为很多时候margin可以用于某种形式的与文本完全无关的元素的定位.那text-direction不会自动翻转可能不太明显,但仍然有效.假设有一个英文(LTR)网站,其中包含阿拉伯语(RTL)的块引用.现在一个转换的主要语言希伯来语(RTL),但仍然有阿拉伯文的报价-这应该不是自动翻转到LTR,因为它是不正确的.

诸如浮动元素,绝对定位元素等(使用rightleft值)之类的东西可能会或可能不会因为它们而被定位text-direction.

基本上,它归结为这样一个事实:当一个人设计一个旨在以多种语言翻转的网站时text-direction,必须在每个阶段仔细考虑该元素应该基于LTR或RTL配置做什么.

这意味着,在我看来,CSS没有弱点.任何弱点都在于设计实施.


纯粹的人类在设计中的前瞻性

所以,最好的方法是选择你的标准方向(比如说LTR)并将其作为你的直接CSS的"基础"计划.

然后,对于因RTL更改而要翻转的元素,可以通过将类应用于<body>to to target或使用属性选择器来编写其他CSS来解释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;
}
Run Code Online (Sandbox Code Playgroud)

这是像LESSSASS(SCSS)这样的预处理器(Dave在他的回答中提到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)  {}
}
Run Code Online (Sandbox Code Playgroud)

然后根据需要在其他选择器中使用它

.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);
}
Run Code Online (Sandbox Code Playgroud)

生成这个完成的代码

.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;
}
Run Code Online (Sandbox Code Playgroud)

想法2

  • 优点:允许您使用类似于您想要的语法; 可以很容易地修改以与LESS 1.3.3一起使用.
  • 缺点:如果在一个选择器中更改了多个值,则会产生过多的输出css.

构建一些helper mixins,其语法与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[dir=@{oppDir}] & {
    padding: @top @left @bottom @right;
  }
}
.margin-near(@top, @right, @bottom, @left) {
  margin: @top @right @bottom @left;
  body[dir=@{oppDir}] & {
    margin: @top @left @bottom @right;
  }
}
.float-near(@side) {
  float: @side;
  .flipSides(@side);
  body[dir=@{oppDir}] & {
    float: @newSide;
  }  
}
Run Code Online (Sandbox Code Playgroud)

使用它们可以同时为每个方向定义近距离和远距离

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

.test2 {
  .float-near(left);
}
Run Code Online (Sandbox Code Playgroud)

生成这个完成的代码(注意.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;
}
Run Code Online (Sandbox Code Playgroud)


Jak*_*ski 6

不幸的是,CSS运用左和右的概念,这是正确的行为.有一些工具可以帮助您将CSS从LTR迁移到RTL - 我知道的是CSS Janus,它将翻转-left/-right属性等等.


PHP*_*Pst 0

在发布这个问题大约四年后,这个需求最终将由 w3 解决。https://drafts.c​​sswg.org/css-逻辑/

接受物理方向关键字值(上、下、左或右)的属性被重新定义为也接受适当的流相关方向关键字。在这种情况下,可以使用流量相对值来代替相应的物理值。对于采用多个关键字的属性,不允许使用流相关值和物理值的组合(除非在未来的规范中另有规定)。