سؤال

I am using internationalization for english (en) and french (fr), I have used en.yml for limited use and most of the translations I am writing in fr.yml.

With locale as fr everything works good, but with en it shows me error as missing translation span.

For eg if I have got something like

<%= text_field_tag( "search", params[:search], :placeholder=>t("Search"), :class=>"search_input") %>

and i get output for en is:

<input class="search_input" id="search" name="search" placeholder="<span class=" translation_missing"="" title="translation missing: en.Search">

What I want is that it should turn off translation errors for english, since english is my default language, but for some cases I've used en.yml.

Or if this is not possible then whole error message should be removed.

Thanks

هل كانت مفيدة؟

المحلول

The implementation of HTML missing translation errors has been changed in Rails 4.1. Now instead of I18n library it is handled on the view helper layer. Namely, in "translate" helper method (see action_view/helpers/translation_helper.rb).

A clean way to do this now is to override the helper method and handle the exception yourself.

# app/helpers/i18n_helper.rb

module I18nHelper
  def translate(key, options={})
    super(key, options.merge(raise: true))
  rescue I18n::MissingTranslationData
    key
  end
  alias :t :translate
end

نصائح أخرى

At first sight the Rails I18n guide seem pretty good, and cover this pretty well (e.g. an example to declare a custom exception handler).

But according to this ticket it does not work in rails since 4.0.2 and up (but should be fixed in latest rails 4.1 release).

Apparently the behaviour has changed and the exception handler is ignored now.

Available options:

  • explicitly add option raise: true, which will force the exceptionhandler to be used. E.g. t('.missing', raise: true).
  • in the newest rails 4.1 release you can set the default behaviour back to raising an exception: config.action_view.raise_on_missing_translations = true (see merge ticket for more info)
  • or alternatively, explicitly add a default option: t('.missing', default: 'use this instead')

I18n library uses exception handler to decide what to do with missing translations. By default it returns "translation missing" message:

# i18n/exceptions.rb
class I18n::ExceptionHandler
  include Module.new {
    def call(exception, locale, key, options)
      if exception.is_a?(MissingTranslation)
        # Rails sets :rescue_format to :html in views
        # so that you will get span tag instead of just text message
        options[:rescue_format] == :html ? exception.html_message : exception.message
      elsif exception.is_a?(Exception)
        raise exception
      else
        throw :exception, exception
      end
    end
  }
end

You can extend the exception handler to just return translation key when the translation is missing:

# config/initializers/i18n.rb
module UseKeyForMissing
  def call(exception, locale, key, options)
    if exception.is_a?(I18n::MissingTranslation)
      key
    else
      super
    end
  end
end

I18n.exception_handler.extend UseKeyForMissing

Then assuming you have only french translations:

I18n.t("Search", :locale => :fr) #=> "Rechercher"
I18n.t("Search", :locale => :en) #=> "Search"

If you don't want to fill in translations for English, a possible solution here would be to have your translations fallback to French.

You can achieve this by adding the following code to an initializer (eg. config/initalizers/i18n.rb) :

require "i18n/backend/fallbacks" 
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)

If French is set up as your default locale, this should "Just Work".

Otherwise you may need to add a custom fallback rule to the initializer :

I18n.fallbacks.map(:en => :fr)

try this

<%= text_field_tag( "search", params[:search], :placeholder=>t(:search), :class=>"search_input") %>

and in your en.yml file write

search: 'Search'

Given below code is to remove missing translation for english, we monkey patch MissingTranslation module of I18n, by putting it in initializers.

DEFAULT_TEMPLATE_LANG = 'en'        
# Removing missing translation errors for english
module I18n
  class MissingTranslation
    def html_message
      if DEFAULT_TEMPLATE_LANG == keys[0].to_s
        keys[1].to_s
      else
        "missing translation: #{keys.join('.')}"
      end
    end
  end
end

In Rails 4.1, I wasn't able to get this to work with the I18n exception handler (there are some bugs, apparently, see nathanvda's answer.
Eventually I just overwrote the message function by adding this to config/initializers/i18n.rb

module I18n
  class MissingTranslation
    module Base
      def message
        keys[1..-1].join('.')
      end
    end
  end
end
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top