How to check if a localization exists? - ruby-on-rails

I am creating a little website which is currently being translated into different languages. I use Rails' out-of-the-box translation: l18n. To change the localization, a parameter called locale must be given, e.g.: http://localhost:3000/?locale=nl.
In ApplicationController this parameter is saved into a session variable and used as localization. How can I check if the locale actually exists? Are there any built in functions, or do I need to add an exists: "true" to every localization file to check it?

Rails will default to "en" as the default locale in case if a locale doesn't exist. So to be nasty if I pass http://localhost:3000/?locale=de and that translation doesn't exist, 'en' will be used.
Have a look here http://guides.rubyonrails.org/i18n.html , especially the section "2.3 Setting and Passing the Locale"
#config/initializers/available_locales.rb
# Get loaded locales conveniently
module I18n
class << self
def available_locales; backend.available_locales; end
end
module Backend
class Simple
def available_locales; translations.keys.collect { |l| l.to_s }.sort; end
end
end
end
# You need to "force-initialize" loaded locales
I18n.backend.send(:init_translations)
AVAILABLE_LOCALES = I18n.backend.available_locales
RAILS_DEFAULT_LOGGER.debug "* Loaded locales: #{AVAILABLE_LOCALES.inspect}"
You can then wrap the constant for easy access in ApplicationController:
class ApplicationController < ActionController::Base
def available_locales; AVAILABLE_LOCALES; end
end
You can implement it like this in your ApplicationController:
before_filter :set_locale
def set_locale
I18n.locale = extract_locale_from_params
end
def extract_locale_from_params
parsed_locale = params[:locale]
(available_locales.include? parsed_locale) ? parsed_locale : nil
end
HTH

Related

How to set Rails engine locale (it's using :en even tough host app has a different locale)

I followed the great Rails guide on engines (https://guides.rubyonrails.org/engines.html) and managed to get my engine working in a host app.
However, the engine is loading only the en.yml locale, even tough the host application has I18n.default_locale and I18n.locale both set to pt-br, and I have a config/locales/pt-br.yml file in my engine.
The guide only states that "For locales, simply place the locale files in the config/locales directory, just like you would in an application.", but apparently I need to do something else.
How would I make the engine to load the correct I18n locale files, based on the host app settings? If that's not possible, how the host app could set this locale in an initializer file, like a config option?
I managed to solve it. The key is to remember that I18n.locale is a setting that should be set on every request.
So on my engine entry point (lib/cron_monitor.rb), I defined a setting:
module CronMonitor
class << self
attr_accessor :i18n
end
self.i18n = I18n.default_locale
Then in my engine's ApplicationController, following Rails i18n documentation:
module CronMonitor
class ApplicationController < ActionController::Base
around_action :switch_locale
private
def switch_locale(&action)
locale = CronMonitor.i18n || I18n.default_locale
I18n.with_locale(locale, &action)
end
end
end
Also, if you have code in models or service objects that you also want to be translated, you should use I18n as well. Example:
module CronMonitor
class Category < ApplicationRecord
def self.some_method
message = I18n.translate(
"cron_monitor.starting_or_finishing.failure",
title: self.title,
locale: CronMonitor.i18n
)
end
end

How to correctly implement I18n in Blacklight for field labels?

The docs are sketchy on how to do it properly. I tried this:
class ApplicationController < ActionController::Base
# ...
before_action :set_locale
def set_locale
session[:locale] = I18n.locale = params.delete(:locale) || session[:locale] || I18n.default_locale
end
end
And this suffices for a lot of things; however, my fields are configured like this (following the Blacklight guide):
class CatalogController < ApplicationController
include Blacklight::Catalog
configure_blacklight do |config|
# ...
config.add_facet_field 'date', label: 'Date', single: false
# ...
end
end
This configuration happens before the request is processed, so if I try to use I18n.t('Date') for label, it will not respond to changes in locale, and will always serve the labels corresponding to the default locale.
What is the "correct" way to do this?
EDIT: Found the solution for the individual fields. Still searching for the "proper" solution for the search fields (config.add_search_field). It seems those are just displaying their label if present, and #labelize-d key if not. As a quick stop-gap measure, I made this class:
class Localized
def initialize(key)
#key = key
end
def to_s
I18n.t(key)
end
end
and configured the search field with
... label: Localized.new('blacklight.search.general.all_fields')
Thanks to Surya, I saw where to look. The helper methods are already being invoked by the Blacklight's default templates, as long as one uses the correct keys. So, to localise the date field label in English, one needs the key named en.blacklight.search.fields.date.

Rails: set locale for a specific path

I want to specify locale for specific path.
in my whole application I have my default local e set to :es
config.i18n.default_locale = :es
That works in the normal fashion for the whole application, I want to know how can I specify a specific locale for a set of paths...
I integrated a third party application called maily_herald, in order to make it's paths available for my application i have to add this line to my routes.rb file
mount MailyHerald::Webui::Engine => "/maily_webui"
the problem is that there are not translations for locale :es, so it does not work properly... I want to let all the paths under /maily_webui to have locale :en so the third party application will work in english while my application will still work in :es
any idea how to do this?
class ApplicationController < ActionController::Base
.....
before_filter :set_locale
def set_locale
if request.fullpath == "some_path"
I18n.locale = :some_locale
else
I18n.locale = params[:locale] || I18n.default_locale
end
end
end

Rails: How to have the locale in links inside emails?

How can I have Rails automatically include the locale in every link in every email?
I want:
http://www.some-company.com/en/welcome
...instead of just...
http://www.some-company.com/welcome
I just know that for normal views, it would be:
class ApplicationController < ActionController::Base
...
def self.default_url_options(options={})
options.merge({ locale: I18n.locale })
end
...
end
But how is this achieved for email views?
It should work if you put something like self.class.default_url_options[:locale] = my_locale in your mailer methods. You'll have to set that my_locale somehow - maybe pass it as an argument to the mailer method.

rails-breadcrumb and I18n

I run into an issue with rails-breadcrumb since i localized my application.
In my Controller, I've got this :
class FooController < PrivateController
add_breadcrumb I18n.t('breadcrumbs.foo.index'), :foo_url
end
When my breadcrumb is displayed, the localized string is always taken from en.yml, no matter which language i set up in I18n.locale
After having look at the code, it occurs that add_breadcrumbacts as a before_filter, and after some test, i came to the conclusion that, even if the content of add_breadcrumb has the right locale, it seems that the value passed does not.
If I try this :
add_breadcrumb I18n.t('breadcrumbs.foo.index', :locale => "fr"), :foo_url
Everything goes fine.
How cas i force my string to be correctly localized?
Thank you per advance
I finaly got this. After i determined that my issue cames out of the fact that I18n didn't know anything about my locale as i was asking it to translate something, i monkey-patched the rails-breadcrumb to manage the localization itself.
Know i pass a Symbol as first parameters, and i call I18n.translate() in rails-breadcrumb
add_breadcrumb (:'breadcrumbs.foo.index'), :foo_url
d
# config/initializers/rails-breadcrumb-fix.rb
module Rails
module Breadcrumbs
class ActionController::Base
protected
def add_breadcrumb(name, url = '')
#breadcrumbs ||= []
# if given `name` is a Symbol, we localize it
if name.is_a?(Symbol)
name = I18n.t(name)
end
url = send(url) if url.is_a?(Symbol)
#breadcrumbs << [name, url]
end
def self.add_breadcrumb(name, url, options = {})
before_filter options do |controller|
controller.send(:add_breadcrumb, name, url)
end
end
end
module Helper
def breadcrumbs(separator = "›")
#breadcrumbs.map do |txt, path|
link_to_unless (path.blank? || current_page?(path)), h(txt), path
end.join(" #{separator} ").html_safe
end
end
end
end
ActionController::Base.send(:include, Rails::Breadcrumbs)
ActionView::Base.send(:include, Rails::Breadcrumbs::Helper)

Resources