83

Working on a rails 3 app where I want to check if a translation exists before outputting it, and if it doesn't exist fall back to some static text. I could do something like:

if I18n.t("some_translation.key").to_s.index("translation missing")

But I feel like there should be a better way than that. What if rails in the future changes the "translation missing" to "translation not found". Or what if for some weird reason the text contains "translation missing". Any ideas?

agmcleod
  • 13,321
  • 13
  • 57
  • 96

9 Answers9

145

Based on what you've described, this should work:

I18n.t("some_translation.key", :default => "fallback text")

See the documentation for details.

Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82
85

You can also use

I18n.exists?(key, locale)
I18n.exists?('do_i_exist', :en)
albandiguer
  • 2,327
  • 1
  • 18
  • 14
  • 1
    This is actually working. The method is not documented though, just mentioned here: http://www.rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/Base#exists%3F-instance_method – Cristian Nov 19 '15 at 09:18
  • 1
    `I18n.exists?('key')` seems like the core evaluation. I've used it in helper_methods for fallback actions if no key value is set, e.g. `title = I18n.exists?('page_title.default') ? t('page_title.default') : "Fallback title..."` – Robert Travis Pierce May 28 '17 at 01:24
  • https://rdoc.info/github/ruby-i18n/i18n/I18n/Base#exists%3F-instance_method – Alex Aug 06 '22 at 18:02
  • This is a nice solution, but won't work if you have `config.i18n.fallbacks` in your project. Will cause non-existing keys to return true, I guess because it falls back to another locale and there it finds the requested key. – Tashows Apr 25 '23 at 14:46
36

:default is not always a solution. Use this for more advanced cases:

helpers/application.rb:

def i18n_set? key
  I18n.t key, :raise => true rescue false
end

any ERB template:

<% if i18n_set? "home.#{name}.quote" %>
  <div class="quote">
    <blockquote><%= t "home.#{name}.quote" %></blockquote>
    <cite><%= t "home.#{name}.cite" %></cite>
  </div>
<% end %>
Nowaker
  • 12,154
  • 4
  • 56
  • 62
21

What about this ?

I18n.t('some_translation.key', :default => '').empty?

I just think it feels better, more like there is no translation

Caveat: doesn't work if you intentionally have an empty string as translation value.

Jeremy F.
  • 1,346
  • 12
  • 30
12

use :default param:

I18n.t("some_translation.key", :default => 'some text')
sumskyi
  • 1,827
  • 13
  • 13
4

sometimes you want to do more things on translations fails

v = "doesnt_exist"
begin
  puts I18n.t "langs.#{v}", raise: true
rescue
  ...
  puts "Nooo #{v} has no Translation!"
end
Fer Padron
  • 189
  • 2
  • 3
2

This is a trick but I think it may be useful sometimes...

Assuming you have this in your i18n file:

en:
  key:
    special_value: "Special value"
    default_value: "Default value"

You may do this:

if I18n.t('key').keys.include?(:special_value)
  I18n.t('key.special_value')
else
  I18n.t('key.default_value')
end
# => "Special value"

if I18n.t('key').keys.include?(:unknown_value)
  I18n.t('key.special_value')
else
  I18n.t('key.default_value')
end
# => "Default value"

NB: This only works if you're testing anything but a root key since you're looking at the parent.

In fact, what's interesting is what you can get when requesting a parent key...

I18n.t('key')
# => {:special_value=>"Special value", :default_value=>"Default value"}
Romain Champourlier
  • 2,360
  • 24
  • 29
2

Rails 4

I was iterating over some urls of jury members. The max amount of urls were 2, and default_lang was "de". Here is the yaml that I used

de:
 jury:
  urls:
   url0: http://www.example.com
   name0: example.com
   url1:
   name1:

en:
 jury:
  urls:
   url0: 
   name0: 
   url1:
   name1:

Here is how I checked if there was a url given and if it did not exist for another language, it would fallback to the I18n default_lang "de". I used answer of @albandiguer which worked great.

I Hope this helps someone:

    <% 2.times do |j| %>
        <% if I18n.exists?("jury.urls.url#{j}", "de") &&
           I18n.exists?("jury.urls.name#{j}", "de") %>
          <%= "<br/>".html_safe  if j == 1%>
          <a href="<%= t("jury.urls.url#{j}") %>" target="_blank">
            <%= t("jury.urls.name#{j}") %>
          </a>
        <% end %>
     <% end %>
mahatmanich
  • 10,791
  • 5
  • 63
  • 82
0

Some versions ago there is a easier way i18next documentation > API > t:

You can specify either one key as a String or multiple keys as an Array of String. The first one that resolves will be returned.

Example:

i18next.t ( ['unknown.key', 'my.key' ] ); // It will return value for 'my.key'

Also you can use Contexts. t if not found a key into a context returns the default value.

Gabrielizalo
  • 896
  • 1
  • 17
  • 29