What is the convention in Rails (with asset pipeline) for internationalization inside CSS?

孤街浪徒 提交于 2019-12-07 01:53:57

问题


I know CSS isn't supposed to have content, but it does, like this nice box (below) extracted from the Twitter Bootstrap documentation CSS:

/* Echo out a label for the example */
.bs-docs-example:after {
  content: "Example";
}

I don't care for "Example", I use something like that as a mixin:

.box (@legend) {
  /* Echo out a label for the example */
  &:after {
    content: @legend;
  }
}

Then I don't need really dynamic CSS, I can easily include the mixin in a class, but instead of passing "Observation" I need to pass t 'box.observation':

.observation {
  .box("<%= t 'box.observation' =>");
}

Rails is supposed to follow Conventions over Configuration, it is very easy to just add a static CSS/LESS/SCSS and it is already included in all pages in a single minified CSS. What is the convention for internationalized CSS? For example, where I am supposed to put declarations like that of .observation?


回答1:


You don't need to generate a new CSS file for each locale - that borders on madness. Why does your CSS care about the text content of your website?

I think your best bet would be to use a data-attribute to grab the value...

<div class='bs-docs-example' data-before-content='<%= t.css_example %>'>
  <!-- html here -->
</div>

And then in your css:

.bs-docs-example:after {
  content: attr(data-before-content);
}

You could probably find a way to extract this into a partial (or helper), so that your erb file ends up like this:

<%= docs_example do %>
  <!-- html here -->
<% end %>

And a helper method:

def docs_example
  content_tag(:div, class: "bs-docs-example", "data-before-content" => t.css_example) do
    yield
  end
end



回答2:


I could generate one CSS per locale as suggested in this answer, but since the CSS is the same except by the I18n bits, I would have either of:

  1. A folder with a multitude of static CSS/LESS with the locale inlined, e.g.:

    /* en */
    .observation {
      .box("Observation");
    }
    
  2. Lots of exactly identical dynamic CSS's, e.g.

    /* en */
    html[lang=en] {
      .observation {
        .box("Observation")
      }
    }
    

Instead I choose to create a CSS and ERB view and deliver using using page caching with the locale code in the URL, this way there is no duplication. See code below.

config/routes.rb

X::Application.routes.draw do
  get 'index.:locale.:format' => 'css#index',
    constraints: { locale: /[a-z]{2}(-[A-Z]{2})?/,
                   format: 'css' }
end

app/controllers/css_controller.rb

class CssController < ActionController::Base
  caches_page :index
  def index
    @locale = params[:locale]
  end
end

app/views/css/index.css.less.erb

@import "mixins";
.observation {
  .box("<%= t 'box.observation', locale: @locale %>");
}

app/assets/stylesheets/mixins.less

.box (@legend) {
  /* Echo out a label for the example */
  &:after {
    content: @legend;
  }
}

This example would work as is if it was a simple ERB view, but since it is using Less, I have to parse the ERB and LESS manually as of rails 4:

class CssController < ActionController::Base
  caches_page :index

  def index
    @locale = params[:locale]
    erb_source  = find_template.source
    less_source = Tilt::ERBTemplate.new { erb_source }.render(self)
    css_source  = Less::Parser.new(paths: Rails.application.config.less.paths).parse(less_source).to_css
    render text: css_source
  end

  private

  def find_template(_action_name = action_name)
    lookup_context.disable_cache { lookup_context.find_template(_action_name, lookup_context.prefixes) }
  end
end


来源:https://stackoverflow.com/questions/16245330/what-is-the-convention-in-rails-with-asset-pipeline-for-internationalization-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!