[RoR] internationalization & localization parte 2

9 nov 2011(há 13 anos)
DevelopmentRuby on Rails
#session#number_to_currency#localize#locale#link_to#i18n#humanize#human#en.yml#config.i18n.default_locale#before_filter#alias_method

No último post falamos um pouco de como funciona o I18n e nosso ultimo passo foi criar um arquivo chamado pt-BR.yml, não sei se vocês perceberam, mas no arquivo en.yml na segunda linha tem um link onde existem vários locales e o pt-BR é um deles, bem agora iremos fazer com que isso funcione no nosso projeto... let's rock.

Start

Vamos começar deixando nossa aplicação como pt-BR por default, abram o arquivo /config/application.rb e descomentem a linha

# config.i18n.default_locale = :de
# trocar por
config.i18n.default_locale = "pt-BR"

Bem, como falei na introdução deste post tem um link "https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/pt-BR.yml" que é a nossa tradução, vamos pegar o conteúdo dele e colar dentro do nosso pt-BR.yml, bom com isso boa parte dos helpers estarão traduzido, os relacionados com data, moeda, numeros entre outros, tais como mensagens de erros etc, etc, etc... Agora se você rodar um rails c e veja que ao invés de "can't be blank" vai retornar "não pode ficar em branco", veja esse e outros exemplo logo abaixo:

ruby-1.9.2-p180 :001 > I18n.translate "errors.messages.blank"
 => "não pode ficar em branco"
ruby-1.9.2-p180 :002 > helper.number_to_currency 10.17
 => "R$ 10,17"
ruby-1.9.2-p180 :003 > I18n.localize Time.now
 => "Terça, 08 de Novembro de 2011, 23:06 h"

Bom para testarmos, vou alterar um post qualquer em deixando title e permalink em branco:

Vejam que o parte dos erros foram traduzidos, vamos corrigir isso... Vamos começar com o en.yml:

# Sample localization file for English. Add more files in this directory for other locales.
# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.

en:
  empty: "We don't have any %{collection} yet."
  confirm: Are you sure?
  edit: Edit
  destroy: Destroy
  new: Create %{model}
  cancel: Cancel
  or: or

  admin:
    posts:
      new:
        title: New post
      edit:
        title: Editing post
      form:
        categories: Publish with these categories
        slug: Set a custom url
        author: "Post by:"

E agora adicione no inicio ou no fim do arquivo pt-BR.yml:

empty: "Não temos nenhum %{model} ainda."
  confirm: Tem certeza?
  edit: Editar
  destroy: Apagar
  cancel: Cancelar
  or: or
  new: Criar %{model}
  error_message_header: "%{count} erro(s) impediram este %{model} de ser gravado:"

  admin:
    posts:
      new:
        title: Novo post
      edit:
        title: Editando post
      form:
        categories: Publicar com estas categorias
        slug: Defina uma url
        author: "Post por:"

No application_controller.rb adicione as seguintes linhas:

  before_filter :change_locale

protected
  def change_locale
    session[:locale] = (params[:locale] || session[:locale] || :en)
    I18n.locale = session[:locale]
  end

E no views/admin/posts/index.html.erb:

<h2>Posts</h2>

<% if @posts.present? %>
<ul class="list">
  <% @posts.each do |post| %>
    <%= content_tag_for :li, post, :class => cycle(:odd, :even) do %>
      <%= link_to post.title.titleize, [:admin, post] %>

      <div class="right">
        <%= link_to_edit [:edit, :admin, post] %>,
        <%= link_to_destroy [:admin, post] %>
      </div>
    <% end %>
  <% end %>
</ul>
<% else %>
  <!-- t é um atalho para I18n.translate -->
  <p><%=t :empty, :collection => "posts" %></p>
<% end %>

<hr class="thick" />

<div class="bar">
  <div class="right">
    <%= link_to_new Post, new_admin_post_path, :class => "button" %>
  </div>
</div>

Bem, nosso próximo passo é views/admin/posts/new.html.erb

<h2><%=t ".title" %></h2>

<%= render 'form' %>

Próximo é views/admin/posts/edit.html.erb

<h2>
  <%=t ".title" %>
  <%= link_to 'Preview', [:admin, @post],
        :class => "button right", :target => "_blank" %>
</h2>

<%= render 'form' %>

Próximo é views/shared/_errors_messages.html.erb que na verdade, agora sim vamos traduzir aquela mensagem na imagem acima...

<% if resource.errors.any? %>
  <div id="error_explanation">
    <h2><%=t "activerecord.errors.template.header",
              :count => resource.errors.count,
              :model => resource.class.model_name.human  %></h2>

    <ul>
    <% resource.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

Agora novamente tentando editar um post sem titulo e sem permalink [caption id="attachment_906" align="alignnone" width="600" caption="Erro traduzido"]asdasdas[/caption] Bem nosso próximo passo vai ser no nosso form views/admin/posts/_form.html.erb

<%= form_for [:admin, @post] do |f| %>
   <%= error_messages_for @post %>

   <div id="body">
     <div class="field">
       <%= f.label :author_id, t(".author") %>
       <%= f.collection_select :author_id, @authors, :id, :full_name %>
     </div>

     <div class="field">
       <%= f.text_field :title, :placeholder => ta(Post, :title), :class => "title" %>
     </div>

     <div class="field">
       <%= f.text_area :excerpt, :placeholder => ta(Post, :excerpt), :rows => 5, :cols => 70 %>
     </div>

     <div class="field">
       <%= f.text_area :body, :placeholder => ta(Post, :body), :rows => 30, :cols => 70 %>
     </div>

     <div class="field">
       <%= f.check_box :draft %>
       <%= f.label :draft %>
     </div>

     <hr class="thick" />

     <p>
       <%= f.submit :class => "button" %>
       <%= t("or") %>
       <%= link_to t("cancel"), admin_posts_path %>
     </p>
   </div>

   <div id="sidebar">
     <%= section t(".categories") do %>
       <ul class="categories-field">
         <%- @categories.each do |c| -%>
           <li><%= check_box_tag "post[category_ids][]",
           c.id, @post.categories.include?(c) %>
           <%= c.name %></li>
         <%- end -%>
       </ul>
       <div class="bar">
         <%= link_to_new Category, new_admin_category_path, :class => "button right" %>
       </div>
       <br/>
     <% end %>

     <hr/>

     <%= section do %>
       <div class="field">
         <%= f.label :published_at %><br/>
         <%= f.date_select :published_at, :use_short_month => true %>
       </div>
     <% end %>

     <hr/>

     <%= section  do %>
       <div class="field">
         <%= f.label :slug, t(".slug") %><br/>
         <%= f.text_field :slug, :size => 27 %>
       </div>
     <% end %>
   </div>

 <% end %>

Só para finalizarmos nosso post adicione dois métodos no helpers/admin/admin_helper.rb

def link_to_new(model, url, html_options = {})
  link_to t("new", :model => model.model_name.human), url, html_options
end

def translate_attribute(model, attribute)
  model.human_attribute_name(attribute)
end
# apelido para o método acima definido
alias_method :ta, :translate_attribute

Conclusão

Bom, como sempre eu deixo o link de dowload aqui, dessa vez não vai ser diferente, mas antes... uma última dica, imagine que você precisa traduzir a http://localhost:3000/home que tem texto pra caramba, vai colocar tudo no .yml? Não,  quando se tem muito conteúdo estático é só criar um arquivo com o mesmo nome, mas só que adicionando pt-BR no nome ex: o arquivo pages/index.html.erb renomei-o para pages/index.en.html.erb e crie um arquivo pages/index.pt-BR.html.erb e os rails que se vire, para testar é só passar?locale=pt-BR para português e?locale=en para inglês no finalda url ex: http://localhost:3000/home?locale=pt-BR ... Como prometido o link de download e o link de teste online(pt-BR ou en), e no próximo post voltaremos com upload de arquivos... Até mais.