I have the old frontend (yeah I know i need to upd...
# support
c
I have the old frontend (yeah I know i need to update, lol). On the checkout screen for the address input there's no way to translate states (even in the new frontend I think), without overriding some JS. See the path for api/states: https://github.com/solidusio/solidus_frontend/blob/dae732ed7442a755cc0426cd2afa6ac[…]e7105/app/assets/javascripts/spree/frontend/checkout/address.js and https://github.com/solidusio/solidus_starter_frontend/blob/main/templates/app/assets/javascripts/utils.js.erb I tried to change the checkout form like this:
Copy code
<span class="js-address-fields" style="display: none;">
        <%=
          form.collection_select(
            :state_id, address.country.states, :id, Proc.new { |val| t(val.name) },
            {include_blank: true},
            {
              class: have_states ? 'required border-slate-400 grow text-slate-900 focus:border-sky-200 focus:ring-1 focus:ring-sky-100 text-xs lg:text-sm xl:text-base rounded' : '',
              style: have_states ? '' : 'display: none;',
              disabled: !have_states,
              autocomplete: address_type + ' address-level1',
            })
          %>
        <%=
          form.text_field(
            :state_name,
            class: !have_states ? 'required border-slate-400 grow text-slate-900 focus:border-sky-200 focus:ring-1 focus:ring-sky-100 text-xs lg:text-sm xl:text-base rounded' : '',
            style: have_states ? 'display: none;' : '',
            disabled: have_states,
            autocomplete: address_type + ' address-level1',
          )
        %>
      </span>
If I turn off the JS then I've got to write some new js for countries that don't have states, or the form element won't show. This Proc added to the collection_select won't work, it show sup for a few ms then disappears.
✅ 1
w
States names come from the database. You should be able to translate them using https://github.com/shioyama/mobility.
Alternatively, you can use https://github.com/solidusio-contrib/solidus_globalize, but it’s a bit outdated
k
For geografic regions you can also use libraries like Carmen (which should already be a Solidus dependency BTW), and use their system to translate the state names
👍 1
For example, something like:
Copy code
form.collection_select(:state_id, address.country.states, :id, Proc.new { |val| t(val.i18n_name) }
and defining a method like this in `Spree::State`:
Copy code
def i18n_name
  carmen_country = Carmen::Country.coded(country.iso)
  carmen_country.subregions.named(name).name
end
+ setting the carmen locale to your current one:
Copy code
Carmen.i18n_backend.locale = I18n.locale
c
Great solutions! I was aware of Globalize and Mobility, but kinda wanted to avoided them. The Carmen solution is a good fit for us, thank you!
Well this is weird. It's still not working.
Copy code
module Spree
  class State < Spree::Base
    module StateI18n

      def i18n_name
        carmen_country = Carmen::Country.coded(country.iso)
        carmen_country.subregions.coded(abbr).name
      end

      Spree::State.prepend self
    end
  end
end
Maybe I HAVE to do Mobility. I had to change the code a little bit (the subregion in Carmen is coded to the language already (Japanese in our case). So I had to go with the prefecture code (aka 'abbr') to get to the name. But it still shows up in English...
Copy code
<%= form.collection_select(
            :state_id, address.country.states, :id, Proc.new { |val| t(val.i18n_name) }
          %>
So this renders the Japanese for a split second, and then appears to be getting overwritten again with English. I think it's because whatever gets rendered gets put through "fill states" here: https://github.com/solidusio/solidus_frontend/blob/dae732ed7442a755cc0426cd2afa6ac[…]e7105/app/assets/javascripts/spree/frontend/checkout/address.js or here: https://github.com/solidusio/solidus_starter_frontend/blob/main/templates/app/assets/javascripts/checkout/address.js#L26 And fills it with the "name" attribute from api/state (e.g. ours: https://funabiki.info/ja/api/states ) Also tried Mobility to extend the Spree::State model. It slows everything down, and it needs an attribute extension (eg. 'name_ja'). Which means I'd need to modify the API to include at name_ja attribute, and then need to modify the JS file to call that attribute from the api data.
k
To avoid that, I think you could just override the name getter for Spree::State. That’s more drastic but should change it consistently
✅ 1
c
Finally got it! I learned about: Carmen, how to override an attribute getter, and the downsides of Mobility (lol). Below is what I ended up with, thank you!
Copy code
module Spree
  class State < Spree::Base
    module StateNameOverride
      def i18n_name
        carmen_country = Carmen::Country.coded(country.iso)
        carmen_country.subregions.coded(abbr).name
      end

      def name
        i18n_name || self[:name]
      end

      Spree::State.prepend self
    end
  end
end
🎊 1