Search code examples
internationalizationruby-on-rails-2

locale information in database


I am new to ruby on rails trying to figure out a way of setting the locale based on the country selected by each user.

I stored the locale tags (like :en) on the database but when I tried to set it to I18n.locale, it gets recognized as string and gives ":en" is not a valid locale error. How can I convert the string to R18n.locale object?


Solution

  • Have you had a look at the docs?

    Quoted from there:

    2.2.1 Setting the Locale from the Domain Name

    One option you have is to set the locale from the domain name where your application runs. For example, we want www.example.com to load the English (or default) locale, and www.example.es to load the Spanish locale. Thus the top-level domain name is used for locale setting. This has several advantages:

    The locale is an obvious part of the URL. People intuitively grasp in which language the content will be displayed. It is very trivial to implement in Rails. Search engines seem to like that content in different languages lives at different, inter-linked domains.

    You can implement it like this in your ApplicationController:

    before_action :set_locale
    
    def set_locale
      I18n.locale = extract_locale_from_tld || I18n.default_locale
    end
    
    # Get locale from top-level domain or return +nil+ if such locale is not available
    # You have to put something like:
    #   127.0.0.1 application.com
    #   127.0.0.1 application.it
    #   127.0.0.1 application.pl
    # in your /etc/hosts file to try this out locally
    
    def extract_locale_from_tld
      parsed_locale = request.host.split('.').last
      I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
    end
    

    You have not stated where you are deriving the language from. If you were trying to use the URL than the docs have answered your question. If you are using some other method than this line may still be of use:

    I18n.available_locales.map(&:to_s).include?(my_locale) ? my_locale : nil

    Where my_locale is the locale you are trying to use.

    Let me know if this helps!

    EDIT:

    It seems that the locales are stored as "en" or "uk" so make sure your string will match that. I tested the following code and it worked for me

    def set_locale
      I18n.locale = current_user.try(get_locale(<current_user.locale>) || I18n.default_locale
    end
    
    def get_locale(my_loc)
        I18n.available_locales.each do |loc|
            if loc.to_s == my_loc
                return loc
            end
        end
        nil
    end