Skip to content

Commit

Permalink
Set fallback locale for Mobility based on current store
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalcymerys committed Jul 21, 2023
1 parent fefbbce commit 8a25054
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 8 deletions.
4 changes: 1 addition & 3 deletions core/app/models/concerns/spree/translatable_resource_slug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ module TranslatableResourceSlug

included do
def localized_slugs_for_store(store)
localized_slugs = Hash[translations.pluck(:locale, :slug)]
default_locale = store.default_locale
supported_locales = store.supported_locales_list

supported_locales.each_with_object({}) do |locale, hash|
hash[locale] = localized_slugs[locale] || localized_slugs[default_locale]
hash[locale] = I18n.with_locale(locale) { slug }
end
end
end
Expand Down
7 changes: 5 additions & 2 deletions core/app/models/spree/taxon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Taxon < Spree::Base
extend FriendlyId
friendly_id :permalink, slug_column: :permalink, use: :history
before_validation :set_permalink, on: :create, if: :name
alias_attribute :slug, :permalink

acts_as_nested_set dependent: :destroy

Expand Down Expand Up @@ -66,10 +67,12 @@ class Taxon < Spree::Base

def set_permalink
parent = translated_model.parent
name_with_fallback = name || translated_model.name

if parent.present?
self.permalink = [parent.permalink, (permalink.blank? ? name.to_url : permalink.split('/').last)].join('/')
self.permalink = [parent.permalink, (permalink.blank? ? name_with_fallback.to_url : permalink.split('/').last)].join('/')
else
self.permalink = name.to_url if permalink.blank?
self.permalink = name_with_fallback.to_url if permalink.blank?
end
end
end
Expand Down
16 changes: 16 additions & 0 deletions core/app/services/spree/locales/set_fallback_locale_for_store.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Spree
module Locales
class SetFallbackLocaleForStore
def call(store:)
store_default_locale = store.default_locale
fallbacks = store.supported_locales_list.each_with_object({}) do |locale, object|
object[locale] = [store_default_locale]
end

fallbacks_instance = I18n::Locale::Fallbacks.new(fallbacks)

Mobility.store_based_fallbacks = fallbacks_instance
end
end
end
end
4 changes: 1 addition & 3 deletions core/config/initializers/mobility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
backend_reader
query
cache
fallbacks
store_based_fallbacks
locale_accessors
presence
dirty
end

config.defaults[:fallbacks] = true
end
51 changes: 51 additions & 0 deletions core/lib/mobility/plugins/store_based_fallbacks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true

require 'concurrent'
require 'mobility'

module Mobility
@store_based_fallbacks = Concurrent::ThreadLocalVar.new(I18n::Locale::Fallbacks.new)

class << self
def store_based_fallbacks
@store_based_fallbacks.value
end

def store_based_fallbacks=(value)
@store_based_fallbacks.value = value
end
end

module Plugins
module StoreBasedFallbacks
extend ::Mobility::Plugin

default true
requires :backend, include: :before

# Applies fallbacks plugin to attributes. Completely disables fallbacks
# on model if option is +false+.
included_hook do |_, backend_class|
unless options[:fallbacks] == false
backend_class.include(BackendInstanceMethods)
end
end

module BackendInstanceMethods
def read(locale, fallback: true, **kwargs)
return super(locale, **kwargs) if !fallback || kwargs[:locale]

locales = Mobility.store_based_fallbacks[locale]
locales.each do |fallback_locale|
value = super(fallback_locale, **kwargs)
return value if Util.present?(value)
end

super(locale, **kwargs)
end
end
end

register_plugin(:store_based_fallbacks, StoreBasedFallbacks)
end
end
7 changes: 7 additions & 0 deletions core/lib/spree/core/controller_helpers/locale.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Locale

included do
before_action :set_locale
before_action :set_fallback_locale

if defined?(helper_method)
helper_method :supported_locales
Expand All @@ -21,6 +22,12 @@ def set_locale
I18n.locale = current_locale
end

def set_fallback_locale
return unless respond_to?(:current_store) && current_store.present?

Spree::Locales::SetFallbackLocaleForStore.new.call(store: current_store)
end

def current_locale
@current_locale ||= if user_locale?
try_spree_current_user.selected_locale
Expand Down
1 change: 1 addition & 0 deletions core/lib/spree_core.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'friendly_id/paranoia'
require 'mobility/plugins/store_based_fallbacks'

require 'spree/core'
2 changes: 2 additions & 0 deletions core/spec/models/spree/product_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,8 @@ def build_option_type_with_values(name, values)
let(:product) { create(:product, stores: [store], slug: 'test_slug_en') }
let!(:product_translation_fr) { product.translations.create(slug: 'test_slug_fr', locale: 'fr') }

before { Spree::Locales::SetFallbackLocaleForStore.new.call(store: store) }

subject { product.localized_slugs_for_store(store) }

context 'when there are slugs in locales not supported by the store' do
Expand Down
2 changes: 2 additions & 0 deletions core/spec/models/spree/taxon_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@
let(:taxon) { create(:taxon, taxonomy: taxonomy, permalink: 'test_slug_en') }
let!(:taxon_translation_fr) { taxon.translations.create(slug: 'test_slug_fr', locale: 'fr') }

before { Spree::Locales::SetFallbackLocaleForStore.new.call(store: store) }

subject { taxon.localized_slugs_for_store(store) }

context 'when there are slugs in locales not supported by the store' do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require 'spec_helper'

module Spree
describe Locales::SetFallbackLocaleForStore do
let(:command) { described_class.new }

describe '#call' do
let(:store) { create(:store, default_locale: 'pl', supported_locales: 'en,de,pl') }
let(:product) { create(:product, name: 'test') }

let(:name_en) { 'name en' }
let(:name_pl) { 'name pl' }

let!(:translation_en) { product.translations.find_or_create_by(locale: 'en') { |e| e.name = name_en } }
let!(:translation_pl) { product.translations.find_or_create_by(locale: 'pl') { |e| e.name = name_pl } }

before { command.call(store: store) }

context 'when translatable object does not have a translation in the requested locale' do
it 'sets mobility to retrieve value in the fallback locale' do
name = I18n.with_locale(:de) { product.name }
expect(name).to eq(name_pl)
end
end

context 'when translatable object has a translation in the requested locale' do
let(:name_de) { 'name de' }
let!(:translation_de) { product.translations.find_or_create_by(locale: 'de') { |e| e.name = name_de } }

it 'sets mobility to retrieve value directly' do
name = I18n.with_locale(:de) { product.name }
expect(name).to eq(name_de)
end
end
end
end
end

0 comments on commit 8a25054

Please sign in to comment.