rails i18n - translating text with links inside

后端 未结 9 731
名媛妹妹
名媛妹妹 2020-11-30 21:05

I\'d like to i18n a text that looks like this:

Already signed up? Log in!

Note that there is a link on the text. On this example

相关标签:
9条回答
  • 2020-11-30 21:28

    I think a simple way to do this is by simply doing :

    <%= link_to some_path do %>
    <%= t '.some_locale_key' %>
    <% end %>
    
    0 讨论(0)
  • 2020-11-30 21:31

    Why not use the first way, but splitting it up like

    log_in_message: Already signed up?
    log_in_link_text: Log in!
    

    And then

    <p> <%= t('log_in_message') %> <%= link_to t('log_in_link_text'), login_path %> </p>
    
    0 讨论(0)
  • 2020-11-30 21:34

    I took hollis solution and made a gem called it out of it. Let's look at an example:

    log_in_message: "Already signed up? %{login:Log in!}"
    

    And then

    <p><%=t_link "log_in_message", :login => login_path %></p>
    

    For more details, see https://github.com/iGEL/it.

    0 讨论(0)
  • 2020-11-30 21:35

    We had the following:

    module I18nHelpers
      def translate key, options={}, &block
        s = super key, options  # Default translation
        if block_given?
          String.new(ERB::Util.html_escape(s)).gsub(/%\|([^\|]*)\|/){
            capture($1, &block)  # Pass in what's between the markers
          }.html_safe
        else
          s
        end
      end
      alias :t :translate
    end
    

    or more explicitly:

    module I18nHelpers
    
      # Allows an I18n to include the special %|something| marker.
      # "something" will then be passed in to the given block, which
      # can generate whatever HTML is needed.
      #
      # Normal and _html keys are supported.
      #
      # Multiples are ok
      #
      #     mykey:  "Click %|here| and %|there|"
      #
      # Nesting should work too.
      #
      def translate key, options={}, &block
    
        s = super key, options  # Default translation
    
        if block_given?
    
          # Escape if not already raw HTML (html_escape won't escape if already html_safe)
          s = ERB::Util.html_escape(s)
    
          # ActiveSupport::SafeBuffer#gsub broken, so convert to String.
          # See https://github.com/rails/rails/issues/1555
          s = String.new(s)
    
          # Find the %|| pattern to substitute, then replace it with the block capture
          s = s.gsub /%\|([^\|]*)\|/ do
            capture($1, &block)  # Pass in what's between the markers
          end
    
          # Mark as html_safe going out
          s = s.html_safe
        end
    
        s
      end
      alias :t :translate
    
    
    end
    

    then in ApplicationController.rb just

    class ApplicationController < ActionController::Base
      helper I18nHelpers
    

    Given a key in the en.yml file like

    mykey: "Click %|here|!"
    

    can be used in ERB as

    <%= t '.mykey' do |text| %>
      <%= link_to text, 'http://foo.com' %>
    <% end %>
    

    should generate

    Click <a href="http://foo.com">here</a>!
    
    0 讨论(0)
  • 2020-11-30 21:40

    Thank you very much, holli, for sharing this approach. It works like a charm for me. Would vote you up if I could, but this is my first post so I'm lacking the proper reputation ... As an additional piece to the puzzle: The problem I realized with your approach is that it still won't work from inside the controller. I did some research and combined your approach with the one from Glenn on rubypond.

    Here is what I came up with:

    View helper, e.g. application_helper.rb

      def render_flash_messages
        messages = flash.collect do |key, value|
          content_tag(:div, flash_message_with_link(key, value), :class => "flash #{key}") unless key.to_s =~ /_link$/i
        end
        messages.join.html_safe
      end
    
      def flash_message_with_link(key, value)
        link = flash["#{key}_link".to_sym]
        link.nil? ? value : string_with_link(value, link).html_safe
      end
    
      # Converts
      # "string with __link__ in the middle." to
      # "string with #{link_to('link', link_url, link_options)} in the middle."
      # --> see http://stackoverflow.com/questions/2543936/rails-i18n-translating-text-with-links-inside (holli)
      def string_with_link(str, link_url, link_options = {})
        match = str.match(/__([^_]{2,30})__/)
        if !match.blank?
          $` + link_to($1, link_url, link_options) + $'
        else
          raise "string_with_link: No place for __link__ given in #{str}" if Rails.env.test?
          nil
        end
      end
    

    In the controller:

    flash.now[:alert] = t("path.to.translation")
    flash.now[:alert_link] = here_comes_the_link_path # or _url
    

    In the locale.yml:

    path:
      to:
        translation: "string with __link__ in the middle"
    

    In the view:

    <%= render_flash_messages %>
    

    Hope this post earns me the reputation to vote you up, holli :) Any feedback is welcome.

    0 讨论(0)
  • 2020-11-30 21:44

    en.yml

    log_in_message_html: "This is a text, with a %{href} inside."
    log_in_href: "link"
    

    login.html.erb

    <p> <%= t("log_in_message_html", href: link_to(t("log_in_href"), login_path)) %> </p>
    
    0 讨论(0)
提交回复
热议问题