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

时间:2012-10-13 18:33:03

标签: css internationalization multilingual right-to-left

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

如果您将dir='ltr'dir='rtl'添加到<body>元素,那么您在逻辑上应该期望它应该做必要的魔术。

但是,您实际上需要在rightleft等规则中切换所有text-directionmargin设置。您还需要将margin: 0 10px 0 20px;等规则更改为margin: 0 20px 0 10px;

W3C标准可以通过为方向相关规则允许两个以上的值来避免此问题。换句话说,代替-right-left(如margin-rightmargin-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 */

从本质上讲,在您目前可以输入leftright基于方向的字词的所有规则/值中,您可以改写nearfar

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

7 个答案:

答案 0 :(得分:7)

因为你把问题改为事先考虑而不是事后考虑。

不太合乎逻辑

您声明,“如果您在逻辑上向dir='rtl'元素添加dir='ltr'<body>属性,那么您希望它能够发挥魔力。”显而易见的是,在rightleft等规则中,所有leftright以及所有text-directionmargin之间的转换都是神奇的。“< / p>

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

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

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

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


纯粹的人类预见设计

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

然后,对于因RTL更改而要翻转的元素,您可以通过将类应用于<body>以使用或使用{{1}之类的属性选择器来编写其他CSS来解释该元素。 }。然后你想一想你所做的每一个元素是否应该受到这个变化的影响,如果是你添加css(使用额外的方向选择器添加特异性来覆盖):

body[dir=rtl]

这就是像LESSSASS (SCSS)这样的预处理器(Dave在他的回答中提到LESS)可以证明有用(请参阅下面的更新),但这仍然是需要预先考虑的解决方案。

如果您不希望使用过多的CSS代码

您可以为确定该特定方向的站点时加载的RTL css创建单独的样式表。这样做的可能缺点是它将“切换”代码与原始代码分开,因此维护可能更具挑战性(关于受主代码中的RTL转换影响的元素的好评论文档可以弥补这一点)。 / p>


(更新)使用LESS帮助?

这是一个通过像LESS这样的预处理器使过程更简洁的想法。此示例使用的功能来自 LESS 1.4 (目前处于测试阶段)。

想法1

  • 优势:将所有值更改为一个选择器更改。
  • 缺点:在参数中对值进行编码需要做更多的工作。

构建一个mixin以将所需的选择器应用到

.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;
}

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

.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);
}

创意2

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

构建一些帮助mixins,其语法与CSS中的预期相似

.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;
}

使用它们一次定义每个方向的近距离和远距离

//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;
  }  
}

制作完成后的代码(注意反复方向重复.test1 { .padding-near(10px, 30px, 2px, 40px); .margin-near(0, 10px, 0, 20px); .float-near(right); } .test2 { .float-near(left); }

.test1

答案 1 :(得分:6)

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

答案 2 :(得分:4)

我想如果你想要这个,你必须使用像lesscss这样的东西。

有一个standard in the works可以解决这个问题,但我不知道有任何支持它的浏览器。即使他们这样做,也可能会受到遗留浏览器支持的阻碍(但没有这是一个问题?)。

除了所有的技术挑战,一旦完成,我想要很好地实现它,你仍然必须确保外部化每个左/右的引用然后使用类似于媒体查询的使用方式移动浏览器的响应式设计。

答案 3 :(得分:3)

我使用Closure样式表,这个东西就像命令行标志一样简单。

我将所有内容定义为LTR(必要时使用direction:ltr),然后在编译期间使用--output-orientation=RTL,我会为我生成翻转的CSS。最后,在确定区域设置(在服务器上)时,我还确定要注入我的模板的CSS。

更多信息LR翻转在关闭位于https://code.google.com/p/closure-stylesheets/#RTL_Flipping

答案 4 :(得分:0)

有关尝试使用SASS / LESS克服弱点的一个解决方案的其他背景信息,请查看http://anasnakawa.github.io/bi-app-sass/

答案 5 :(得分:0)

在问了这个问题三年后,知道我看到了使用逻辑方向词汇而不是四向词的趋势。

CSS Logical Properties现在解决了这个问题。 Flex模型使用$computers = gc C:\temp\computers.txt $count = $computers.count Do { foreach($computer in $computers){ $readCount = $computer.ReadCount gwmi win32_service -ComputerName $computer | where {$_.name -like "*was*"} | Restart-Service } } Until (($count - $readCount) -eq 1) / start个关键字 Blink现在支持end个关键字。 E.I。

start/end/before/after

答案 6 :(得分:0)

在发布这个问题大约四年后,这个需求最后将由w3解决。 https://drafts.csswg.org/css-logical/

  

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