11

I get a I18n::InvalidLocale: "zh-CN" is not a valid locale exception that I want to avoid.

To solve it, I have heard of two hacks:

# meh
config.i18n.enforce_available_locales = false

# Ever heard of convention over configuration?
config.i18n.available_locales = [:fr, :en, "zh-CN", "zh-TW"]

None of them seem clean to me, because without touching those configuration variables, I already have a bunch of available locales which are automagically pre-filled:

My current available_locales are:

> I18n.available_locales
=> [:en, :fr]   (misses zh-CN and zh-TW)

In my config/locales folder, I have:

en.yml
fr.yml
zh-CH.yml (newly added, and unavailable)
zh-TW.yml (newly added, and unavailable)

In my config/application.rb, I have:

config.i18n.default_locale = :fr

I don't get how fr has automagically entered I18n.available_locales, when the zh-CN and zh-TW have not.

Yet, having fr enter it without me setting config.i18n.available_locales tells me that touching this configuration variable is not the clean way to go.

Do you have a hint at avoiding the I18n::InvalidLocale exception at the correct level?

Gwendal Roué
  • 3,949
  • 15
  • 34
  • Thanks huan, but it doesn't do the trick. – Gwendal Roué Sep 25 '15 at 08:44
  • José, what does `config.i18n.fallbacks = true` do? – Gwendal Roué Sep 25 '15 at 08:45
  • Sorry, I misunderstood your question. Try to put your configurations `config.i18n.default_locale` and `config.i18n.available_locales` in the environments files – José Morais Sep 25 '15 at 08:47
  • José, you first misunderstood because you did not read. Setting available_locales looks like a hack to me. Besides (I have to work so of course I tried it even if it looks like a dirty hack), I still get missing translations. – Gwendal Roué Sep 25 '15 at 08:49
  • http://www.rubydoc.info/docs/rails/2.3.8/I18n/Config#available_locales-instance_method It says I18n memoizes your locales. Since zh-CH and zh-TW are newly added, you need to inform I18n to look up for these locales, by setting `available_locales`. – José Morais Sep 25 '15 at 08:54
  • 1
    José, "memoizing" means "remembering in memory as long as the program is running". It's just a fancy name for "memory cache". It does not survive restarting the server, and has nothing to do with our topic. Last, I *know* that setting available_locales works. I *feel* that it is not the correct solution, hence this question. Thanks for your help, though. – Gwendal Roué Sep 25 '15 at 09:01
  • I think the cleanest solution is to _not_ set the locale to `:zh`. Where are you setting `I18n.locale=`? http://guides.rubyonrails.org/v5.0/i18n.html#managing-the-locale-across-requests Use `I18n.available_locales.index()` to verify it is valid before setting it. – Chloe Sep 23 '17 at 22:25

2 Answers2

5

The i18n library takes a pragmatic approach to locale keys , including using only the locale language part, like :en, :pl, and not the region part, like :en-US or :en-GB. If you want this type of definition check a few gems such as globalize.

Also check the following links:

And remove the config.i18n.default_locale = :fr

Because with default locales it will go through the same error which you mentioned so after removing the default locale, use: config.i18n.available_locales = [:fr, :en, "zh-CN", "zh-TW"]

fkoessler
  • 6,932
  • 11
  • 60
  • 92
Arvind
  • 2,671
  • 1
  • 18
  • 32
  • This was not really the question, but thanks. When I will eventualy face issues with Chinese translations, I'll remember to check your link. The *question du jour* is: how to feed I18n with its available locales without setting the available_locales global? – Gwendal Roué Sep 25 '15 at 09:04
  • if it is working then could you accept this answer :) – Arvind Sep 25 '15 at 12:28
  • Setting the available_locales global was enough to make it work. The question was asking for a way to avoid it. So I did not really learnt anything. The en-US / en-GB trouble you mention does not affect me, as long as I can see, so it is off topic as well. I can't accept your answer, I can only upvote it as a reward for your involvement. – Gwendal Roué Sep 25 '15 at 15:01
  • I'm still getting this exception every time someone visits the site from a new locale that is not in my `available_locales` list. How do I avoid the exception? `begin / rescue`? – Chloe Sep 23 '17 at 21:02
1

Don't set the locale to an invalid value.

class ApplicationController < ActionController::Base
  before_action :set_locale

  def set_locale
    [params[:locale], cookies[:locale], extract_locale, I18n.default_locale].each do |l|
      if l && I18n.available_locales.index(l.to_sym)
        I18n.locale = l
        break
      end
    end
    cookies[:locale] = params[:locale] if params[:locale]
  end

  def extract_locale
    request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first if request.env['HTTP_ACCEPT_LANGUAGE']
  end

Test to make sure the locale exists before setting it.

Chloe
  • 25,162
  • 40
  • 190
  • 357