This hack took me through the refinerycms-i18n
gem, and I discovered that it does not aid in achieving graceful content fallback, amongst other issues.
It should be noted this bit of work focused on Refinery v2.0.9 and may not be entirely applicable with the current release.
My solution involved adding the following decorator,
puts "Overriding Refinery::Page - #{__FILE__[/(vendor[\/\w\.]+)/]}"
Refinery::Page.class_eval do
# The `Refinery::Page.find_by_path_or_id` call in
# `Refinery::PagesController#find_page` calls `Refinery::Page.find_by_path` if
# `params[:path].friendly_id?` is true.
#
# # With slugs scoped to the parent page we need to find a page by its full path.
# # For example with about/example we would need to find 'about' and then its child
# # called 'example' otherwise it may clash with another page called /example.
# def self.find_by_path(path)
# split_path = path.to_s.split('/').reject(&:blank?)
# page = ::Refinery::Page.by_slug(split_path.shift, :parent_id => nil).first
# page = page.children.by_slug(split_path.shift).first until page.nil? || split_path.empty?
#
# page
# end
#
# It can be seen that `Refinery::Page.by_slug` is used to scope results via
# the Globalize gem, only returning pages that have translations for the
# locale.
if defined?(::Refinery::I18n)
raise ScriptError, "Please remove `refinerycms-i18n` from your Gemfile!"
end
# Finds pages by their slug. See by_title
def self.by_slug(slug, conditions={})
#locales = Refinery.i18n_enabled? ? Refinery::I18n.frontend_locales.map(&:to_s) : ::I18n.locale.to_s
results = with_globalize({ :locale => ::I18n.locale.to_s, :slug => slug }.merge(conditions))
return results if results && results.any?
# NOTE get results for the default locale
with_globalize({ :locale => ::I18n.default_locale.to_s, :slug => slug }.merge(conditions))
end
end
My hack is detailed rather clearly, and works on whichever approach is taken to obtain the locale context.
However, my work presented another hurdle — to ensure the locale is the first path segment. Getting this to work with refinery placed a few challenges which I was able to get around with
get "/", to: redirect('/en/')
scope "/:locale", constraints: ->(r){r.path !~ %r{^/refinery}} do
mount Refinery::Core::Engine, :at => '/'
end
mount Refinery::Core::Engine, :at => '/' # for CMS access via /refinery
My friend David helped with the above in reminding me that Refinery needed to be mounted outside the scope as well, for CMS access.