spree_address_format_i18n 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rubocop.yml +1 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +673 -0
  6. data/README.md +58 -0
  7. data/app/.gitkeep +0 -0
  8. data/app/controllers/.gitkeep +0 -0
  9. data/app/helpers/spree/addresses_helper_decorator.rb +47 -0
  10. data/app/helpers/spree/admin/base_helper_decorator.rb +16 -0
  11. data/app/models/.gitkeep +0 -0
  12. data/app/models/spree/user_decorator.rb +40 -0
  13. data/app/models/spree_address_format_i18n/address_decorator.rb +145 -0
  14. data/app/models/spree_address_format_i18n/permitted_attributes_decorator.rb +9 -0
  15. data/app/models/spree_address_format_i18n/store_decorator.rb +14 -0
  16. data/app/overrides/spree/account/profile/edit/reorder_position_fields.html.erb.deface +39 -0
  17. data/app/overrides/spree/admin/shared/_address/reorder_address_fields.html.erb.deface +6 -0
  18. data/app/overrides/spree/admin/stores/add_country_field_settings.rb +6 -0
  19. data/app/overrides/spree/remove_address_phone.rb +13 -0
  20. data/app/overrides/spree/replace_ship_address_format.rb +6 -0
  21. data/app/overrides/spree/shared/_address/reorder_address_fields.html.erb.deface +6 -0
  22. data/app/serializers/.gitkeep +0 -0
  23. data/app/services/.gitkeep +0 -0
  24. data/app/views/spree/address_format/_address_field.html.erb +20 -0
  25. data/app/views/spree/address_format/_address_group.html.erb +13 -0
  26. data/app/views/spree/addresses/_form.html.erb +55 -0
  27. data/app/views/spree/admin/shared/_address_form.html.erb +45 -0
  28. data/app/views/spree/admin/stores/_country_field_settings.html.erb +9 -0
  29. data/bin/rails +8 -0
  30. data/config/initializers/spree_permitted_attributes.rb +10 -0
  31. data/config/locales/en.yml +6 -0
  32. data/config/locales/ja.yml +27 -0
  33. data/config/locales/order.ja.yml +48 -0
  34. data/db/migrate/20241231080436_add_kana_columns_to_users.rb +6 -0
  35. data/db/migrate/20250428020947_change_value_country.rb +11 -0
  36. data/db/migrate/20250505070307_add_company_kana_and_fax_to_spree_addresses.rb +6 -0
  37. data/lib/generators/spree_address_format_i18n/add_kana_fields_generator.rb +20 -0
  38. data/lib/generators/spree_address_format_i18n/install/install_generator.rb +20 -0
  39. data/lib/generators/spree_address_format_i18n/install_generator.rb +13 -0
  40. data/lib/generators/spree_address_format_i18n/templates/initializer.rb +8 -0
  41. data/lib/spree_address_format_i18n/configuration.rb +9 -0
  42. data/lib/spree_address_format_i18n/engine.rb +32 -0
  43. data/lib/spree_address_format_i18n/factories.rb +6 -0
  44. data/lib/spree_address_format_i18n/version.rb +7 -0
  45. data/lib/spree_address_format_i18n.rb +21 -0
  46. data/spree_address_format_i18n.gemspec +34 -0
  47. metadata +200 -0
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ SpreeAddressFormatI18n
2
+ =====================
3
+
4
+ This extension provides:
5
+ 1. Customizable address field ordering through YAML configuration
6
+ 2. Japanese kana field support for addresses (firstname_kana, lastname_kana)
7
+
8
+ Install
9
+ =======
10
+
11
+ Add the following line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem "spree_address_format_i18n", :git => "https://github.com/be-agile/spree_address_format_i18n.git", :branch => 'master'
15
+ ```
16
+
17
+ Run:
18
+
19
+ ```bash
20
+ bundle install
21
+ bundle exec rails g spree_address_format_i18n:install
22
+ ```
23
+
24
+ Configuration
25
+ ============
26
+
27
+ To customize the order of address fields, create a YAML file in your application's config/locales directory:
28
+
29
+ ```yaml
30
+ # config/locales/order.ja.yml
31
+ ja:
32
+ address_format_i18n:
33
+ - lastname
34
+ - firstname
35
+ - lastname_kana
36
+ - firstname_kana
37
+ - country
38
+ - zipcode
39
+ - state
40
+ - city
41
+ - address1
42
+ - address2
43
+ ```
44
+
45
+ The extension will use this configuration to determine the order of fields in address forms and displays. Fields not specified in the configuration will be displayed at the end in their default order.
46
+
47
+ Japanese Kana Support
48
+ ====================
49
+
50
+ This extension adds support for Japanese kana fields (firstname_kana, lastname_kana) to Spree addresses. These fields are automatically added to the database when you run the migrations.
51
+
52
+ To use the kana fields:
53
+
54
+ 1. Make sure you've run the migrations: `bundle exec rails g spree_address_format_i18n:install`
55
+ 2. Include the kana fields in your address_format_i18n configuration (see example above)
56
+ 3. The kana fields will be displayed in address forms and on address display pages according to your configuration
57
+
58
+ Validation for kana fields ensures that they contain only katakana characters.
data/app/.gitkeep ADDED
File without changes
File without changes
@@ -0,0 +1,47 @@
1
+ module Spree
2
+ module AddressesHelperDecorator
3
+ # List of kana fields that should not be excluded even when `store.use_kana_fields` is false.
4
+ IGNORED_KANA_FIELDS = [ :company_kana ]
5
+
6
+ def order_address_fields(store)
7
+ name_order = I18n.t('address_format_i18n.fields')
8
+ return Spree::Address::ADDRESS_FIELDS if name_order.blank?
9
+
10
+ fields = filter_address_fields(Spree::Address::ADDRESS_FIELDS, store)
11
+
12
+ # Filter out kana fields if use_kana_fields is false
13
+ unless store.use_kana_fields
14
+ fields = fields.reject { |field| field.include?('kana') }
15
+ end
16
+
17
+ fields.sort_by do |field|
18
+ name_order.index(field) || Float::INFINITY
19
+ end
20
+ end
21
+
22
+ def order_address_groups(store)
23
+ groups = I18n.t('address_format_i18n.groups').deep_dup
24
+ unless store.use_kana_fields
25
+ fn_group = groups.find { |group| group[:name] == 'fn' }
26
+ fn_group[:fields] = fn_group[:fields].reject { |field| field.include?('kana') }
27
+ end
28
+ groups
29
+ end
30
+
31
+ def order_account_edit
32
+ I18n.t('address_format_i18n.account.profile', default: %w[last_name first_name phone email])
33
+ end
34
+
35
+ private
36
+
37
+ def filter_address_fields(fields, store)
38
+ return fields if store.use_kana_fields
39
+
40
+ fields.reject do |field|
41
+ field.include?('kana') && !IGNORED_KANA_FIELDS.include?(field.to_sym)
42
+ end
43
+ end
44
+ end
45
+
46
+ Spree::AddressesHelper.prepend(AddressesHelperDecorator)
47
+ end
@@ -0,0 +1,16 @@
1
+ module Spree
2
+ module Admin
3
+ module BaseHelperDecorator
4
+ def order_address_fields(address_fields)
5
+ name_order = I18n.t('address_format_i18n')
6
+ return address_fields if name_order.blank?
7
+
8
+ Spree::Address::ADDRESS_FIELDS.sort_by do |field|
9
+ name_order.index(field) || Float::INFINITY
10
+ end
11
+ end
12
+ end
13
+
14
+ Spree::Admin::BaseHelper.prepend(BaseHelperDecorator)
15
+ end
16
+ end
File without changes
@@ -0,0 +1,40 @@
1
+ module CustomNameOfPerson
2
+ class PersonName < NameOfPerson::PersonName
3
+ def full
4
+ @full ||= begin
5
+ field_suffixes = I18n.t('address_format_i18n.field_suffixes', default: {})
6
+ suffix = field_suffixes['fn'] || field_suffixes[:fn] || ''
7
+
8
+ order = I18n.t("address_format_i18n.address.full_name", default: %w[first_name last_name])
9
+ parts = order.map do |part|
10
+ case part.to_s.downcase
11
+ when "first_name" then first.to_s.strip
12
+ when "last_name" then last.to_s.strip
13
+ else nil
14
+ end
15
+ end.compact.join(" ").strip
16
+
17
+ base_name = parts.blank? ? first.to_s.strip : parts
18
+ base_name += " #{suffix}" if suffix
19
+ base_name
20
+ end
21
+ end
22
+
23
+ # to_sメソッドもオーバーライドして、デフォルトでfullを返すように
24
+ def to_s
25
+ full
26
+ end
27
+ end
28
+ end
29
+
30
+ module Spree
31
+ module UserDecorator
32
+ def name
33
+ return nil if first_name.blank?
34
+
35
+ @custom_name ||= CustomNameOfPerson::PersonName.new(first_name.to_s.strip, last_name.to_s.strip)
36
+ end
37
+ end
38
+ end
39
+
40
+ Spree.user_class.prepend(Spree::UserDecorator)
@@ -0,0 +1,145 @@
1
+ module SpreeAddressFormatI18n
2
+ module AddressDecorator
3
+ FIELDS_TO_NORMALIZE = [ "phone", "alternative_phone", "zipcode" ]
4
+
5
+ def self.prepended(base)
6
+ base.before_validation :remove_emoji_and_normalize
7
+
8
+ base.const_set(:ADDRESS_FIELDS, %w[firstname lastname firstname_kana lastname_kana company address1 address2 city state zipcode country phone fax company_kana])
9
+
10
+ # カナ presence は「新規入力」または「このリクエストでカナを変更したとき」のみ要求する。
11
+ # use_kana_fields を後から有効化したストアには、カナ未登録の既存住所が多数存在する
12
+ # (実運用のストアでは3割を超えることもある)。これらは clone_shipping_address で bill=ship として再検証される
13
+ # 際に空のままなので、無条件 presence だと既存ユーザーがチェックアウトできなくなる。
14
+ # 永続済み・未変更の空カナはスキップし、新規 or ユーザーが明示的にカナを変更/クリアした
15
+ # 場合のみ必須にすることで、データ品質(新規は必須)と既存ユーザーの購入可否を両立する。
16
+ # @see https://github.com/be-agile/giga-repeat/issues/1210
17
+ kana_presence_required = lambda do |address, field|
18
+ next false unless Spree::Store.current.use_kana_fields
19
+ address.new_record? || address.public_send(:"#{field}_changed?")
20
+ end
21
+
22
+ # セイ(lastname_kana)を先に定義してエラーメッセージの順序を制御
23
+ base.validates :lastname_kana, presence: true, if: -> { kana_presence_required.call(self, :lastname_kana) }
24
+ base.validates :lastname_kana, format: { with: /\A[\p{Katakana}\p{Blank}ー・]+\z/, allow_blank: true, message: :invalid_katakana }, if: -> { Spree::Store.current.use_kana_fields }
25
+
26
+ # メイ(firstname_kana)
27
+ base.validates :firstname_kana, presence: true, if: -> { kana_presence_required.call(self, :firstname_kana) }
28
+ base.validates :firstname_kana, format: { with: /\A[\p{Katakana}\p{Blank}ー・]+\z/, allow_blank: true, message: :invalid_katakana }, if: -> { Spree::Store.current.use_kana_fields }
29
+
30
+ base.validates :company_kana, format: { with: /\A[\p{Katakana}\p{Blank}ー・]+\z/ }, if: -> { company_kana.present? }
31
+ end
32
+
33
+
34
+ # @gem-override spree_core-5.3.6/app/models/spree/address.rb#to_s
35
+ # @see https://github.com/be-agile/giga-repeat/commit/c1a9869799d490211889807bc603fe7c94ea66dc
36
+ # 本家の固定フォーマットではなく、i18n の groups 定義に沿った日本語住所表記で組む。
37
+ def to_s
38
+ # texts.reject(&:blank?).join("<br/>").html_safe
39
+ safe_texts = texts.reject(&:blank?).map do |text|
40
+ ERB::Util.html_escape(text.to_s)
41
+ end
42
+ # rubocop:disable Rails/OutputSafety
43
+ safe_texts.join("<br/>").html_safe
44
+ # rubocop:enable Rails/OutputSafety
45
+ end
46
+
47
+ def to_text
48
+ texts.reject(&:blank?).join("\n")
49
+ end
50
+
51
+ def oneline
52
+ texts.join(" ")
53
+ end
54
+
55
+ def texts
56
+ delimiter = I18n.t("address_format_i18n.delimiter", default: " ")
57
+ groups = I18n.t('address_format_i18n.groups').deep_dup
58
+ field_suffixes = I18n.t('address_format_i18n.field_suffixes', default: {})
59
+
60
+ unless Spree::Store.current.use_kana_fields
61
+ fn_group = groups.find { |group| group[:name] == 'fn' }
62
+ fn_group[:fields] = fn_group[:fields].reject { |field| field.include?('kana') }
63
+ end
64
+
65
+ result = groups.flat_map do |group|
66
+ nodes = group[:children] || [ group ]
67
+
68
+ nodes.map do |node|
69
+ # show_country_fieldがfalseの場合、countryフィールドを除外
70
+ visible_fields = node[:fields].dup
71
+ visible_fields.reject! { |field| field.to_s == 'country' } unless Spree::Store.current.show_country_field
72
+
73
+ # 名前グループの特別処理(カナがある場合)
74
+ if group[:name] == 'fn' && Spree::Store.current.use_kana_fields
75
+ line = format_name_with_kana(visible_fields, delimiter)
76
+ else
77
+ field_values = visible_fields.filter_map { |field| respond_to?(field) ? send(field) : nil }
78
+ line = field_values.join(delimiter) if field_values.present?
79
+ end
80
+
81
+ if line.present?
82
+ # グループに接尾辞が設定されている場合は追加
83
+ suffix = field_suffixes[group[:name].to_sym] || field_suffixes[group[:name]]
84
+ line += " #{suffix}" if suffix
85
+ line
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ # @gem-override spree_core-5.3.6/app/models/spree/address.rb#full_name
92
+ # @see https://github.com/be-agile/giga-repeat/commit/c1a9869799d490211889807bc603fe7c94ea66dc
93
+ # 本家 `"#{firstname} #{lastname}"` ではなく、i18n の名前順・接尾辞(様 等)を反映する。
94
+ def full_name
95
+ field_suffixes = I18n.t('address_format_i18n.field_suffixes', default: {})
96
+
97
+ name = I18n.t("address_format_i18n.address.full_name", default: [ "firstname", "lastname" ])
98
+ .map { |part| send(part) if respond_to?(part) }
99
+ .compact.join(" ").strip
100
+
101
+ # fnグループの接尾辞があれば追加
102
+ suffix = field_suffixes['fn'] || field_suffixes[:fn]
103
+ name += " #{suffix}" if suffix && name.present?
104
+
105
+ name
106
+ end
107
+
108
+ private
109
+
110
+ def remove_emoji_and_normalize
111
+ attributes_to_normalize = attributes.slice(*FIELDS_TO_NORMALIZE)
112
+ normalized_attributes = attributes_to_normalize.compact_blank.deep_transform_values do |value|
113
+ NormalizeString.remove_emoji_and_normalize(value.to_s).strip
114
+ end
115
+
116
+ normalized_attributes.transform_keys! { |key| key.gsub('original_', '') } if defined?(Spree::Security::Addresses)
117
+
118
+ assign_attributes(normalized_attributes)
119
+ end
120
+
121
+ def format_name_with_kana(fields, delimiter)
122
+ # 漢字とカナのフィールドを分離
123
+ kanji_fields = fields.reject { |field| field.include?('kana') }
124
+ kana_fields = fields.select { |field| field.include?('kana') }
125
+
126
+ # 漢字名を取得
127
+ kanji_values = kanji_fields.filter_map { |field| respond_to?(field) ? send(field) : nil }
128
+ return nil if kanji_values.blank?
129
+
130
+ kanji_name = kanji_values.join(delimiter)
131
+
132
+ # カナ名を取得(両方空でない場合のみ)
133
+ kana_values = kana_fields.filter_map { |field| respond_to?(field) ? send(field) : nil }
134
+
135
+ if kana_values.present? && kana_values.any?(&:present?)
136
+ kana_name = kana_values.join('') # カナはスペースなしで連結
137
+ "#{kanji_name}(#{kana_name})"
138
+ else
139
+ kanji_name
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ Spree::Address.prepend(SpreeAddressFormatI18n::AddressDecorator)
@@ -0,0 +1,9 @@
1
+ module SpreeAddressFormatI18n
2
+ module PermittedAttributesDecorator
3
+ def self.prepended(base)
4
+ base.address_attributes.push(:firstname_kana, :lastname_kana, :company_kana, :fax)
5
+ end
6
+ end
7
+ end
8
+
9
+ Spree::PermittedAttributes.prepend(SpreeAddressFormatI18n::PermittedAttributesDecorator)
@@ -0,0 +1,14 @@
1
+ require 'active_record/typed_store'
2
+
3
+ module SpreeAddressFormatI18n
4
+ module StoreDecorator
5
+ def self.prepended(base)
6
+ base.typed_store :settings, coder: ActiveRecord::TypedStore::IdentityCoder do |s|
7
+ s.boolean :use_kana_fields, default: false, null: false
8
+ s.boolean :show_country_field, default: false, null: false
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ Spree::Store.prepend SpreeAddressFormatI18n::StoreDecorator
@@ -0,0 +1,39 @@
1
+ <!-- replace_contents 'div.page-container' -->
2
+ <div class="lg:col-span-3">
3
+ <%= render 'spree/account/account_nav', current: 'account' %>
4
+ </div>
5
+ <div class="lg:col-span-8 lg:col-start-5 pb-6">
6
+ <h5 class="uppercase font-medium mb-4"><%= Spree.t('storefront.account.personal_details') %></h5>
7
+ <div class="flex justify-between">
8
+ <p class="mb-3 text-neutral-600">
9
+ <%= Spree.t('storefront.account.please_update_your_contact_details') %>
10
+ </p>
11
+ <% if defined?(spree_edit_password_path) %>
12
+ <%= link_to Spree.t('storefront.account.change_password'), spree_edit_password_path %>
13
+ <% end %>
14
+ </div>
15
+ <%= render partial: 'spree/shared/error_messages', locals: { target: @user } %>
16
+ <%= form_for @user, url: spree.account_profile_path, html: {class: "flex flex-col gap-4"}, method: :put do |f| %>
17
+ <% order_account_edit.each do |field| %>
18
+ <div>
19
+ <% if field == "first_name" %>
20
+ <%= f.label :first_name, Spree.t(:first_name), class: 'text-xs text-neutral-600 block mb-2' %>
21
+ <%= f.text_field :first_name, class: 'text-input w-full', placeholder: Spree.t(:first_name), required: true %>
22
+ <% end %>
23
+ <% if field == "last_name" %>
24
+ <%= f.label :last_name, Spree.t(:last_name), class: 'text-xs text-neutral-600 block mb-2' %>
25
+ <%= f.text_field :last_name, class: 'text-input w-full', placeholder: Spree.t(:last_name), required: true %>
26
+ <% end %>
27
+ <% if field == "phone" %>
28
+ <%= f.label :phone, Spree.t(:phone), class: 'text-xs text-neutral-600 block mb-2' %>
29
+ <%= f.telephone_field :phone, class: 'text-input w-full', placeholder: Spree.t(:phone) %>
30
+ <% end %>
31
+ <% if field == "email" %>
32
+ <%= f.label :email, Spree.t(:email), class: 'text-xs text-neutral-600 block mb-2' %>
33
+ <%= f.text_field :email, class: 'text-input w-full', placeholder: Spree.t(:email), required: true %>
34
+ <% end %>
35
+ </div>
36
+ <% end %>
37
+ <%= f.submit Spree.t(:update), class: 'btn-primary w-full mb-6' %>
38
+ <% end %>
39
+ </div>
@@ -0,0 +1,6 @@
1
+ <!-- replace_contents 'div.address.vcard' -->
2
+ <% address_groups = order_address_groups(current_store) %>
3
+
4
+ <div class="address vcard">
5
+ <%= address %>
6
+ </div>
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: "spree/admin/stores/form/_basic",
3
+ name: "add_show_country_field",
4
+ insert_before: "erb[loud]:contains('render_admin_partials')",
5
+ partial: "spree/admin/stores/country_field_settings"
6
+ )
@@ -0,0 +1,13 @@
1
+ Deface::Override.new(
2
+ virtual_path: "spree/checkout/complete",
3
+ name: "remove_ship_address_phone",
4
+ remove: "erb[loud]:contains('@order.ship_address.phone')",
5
+ original: "<%= @order.ship_address.phone %>"
6
+ )
7
+
8
+ Deface::Override.new(
9
+ virtual_path: "spree/checkout/complete",
10
+ name: "remove_bill_address_phone",
11
+ remove: "erb[loud]:contains('@order.bill_address.phone')",
12
+ original: "<%= @order.bill_address.phone %>"
13
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/checkout/edit',
3
+ name: 'replace_ship_address_format',
4
+ replace: "erb[loud]:contains('@order.ship_address.to_s.gsub')",
5
+ text: "<%= @order.ship_address.to_s.gsub('<br/>', I18n.t('address_format_i18n.delimiter', default: ' ')).html_safe %>"
6
+ )
@@ -0,0 +1,6 @@
1
+ <!-- replace_contents 'div.text-sm' -->
2
+ <% address_groups = order_address_groups(current_store) %>
3
+
4
+ <div class="address vcard">
5
+ <%= address %>
6
+ </div>
File without changes
File without changes
@@ -0,0 +1,20 @@
1
+ <% case field %>
2
+ <% when 'firstname', 'lastname', 'firstname_kana', 'lastname_kana' %>
3
+ <%= address.send(field) %>
4
+ <% when 'company' %>
5
+ <%= address.company %>
6
+ <% when 'address1', 'address2' %>
7
+ <div class="street-address-line">
8
+ <%= address.send(field) %>
9
+ </div>
10
+ <% when 'city' %>
11
+ <span class="locality"><%= address.city %></span>
12
+ <% when 'state' %>
13
+ <span class="region"><%= address.state_text %></span>
14
+ <% when 'zipcode' %>
15
+ <span class="postal-code"><%= address.zipcode %></span>
16
+ <% when 'country' %>
17
+ <%= address.country.try(:name) %>
18
+ <% else %>
19
+ <%= address.send(field) if address.respond_to?(field) %>
20
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <div class="<%= group[:name] %>">
2
+ <% if group[:fields].present? %>
3
+ <% group[:fields].each do |field| %>
4
+ <%= render partial: 'spree/address_format/address_field', locals: { field: field, address: address } %>
5
+ <% end %>
6
+ <% end %>
7
+
8
+ <% if group[:children].present? %>
9
+ <% group[:children].each do |child_group| %>
10
+ <%= render partial: 'spree/address_format/address_group', locals: { group: child_group, address: address } %>
11
+ <% end %>
12
+ <% end %>
13
+ </div>
@@ -0,0 +1,55 @@
1
+ <%# @gem-override spree_core-5.3.6/app/views/spree/addresses/_form.html.erb %>
2
+ <%# reason: 住所フォームを order_address_fields の可変フィールド方式に置き換え、国フィールド非表示や必須マーカー表示を追加している %>
3
+ <%# Spree 5.3 追従: countries/states の data 属性を address_form_countries_states_cache_key で cache 化 %>
4
+ <%# @see https://github.com/be-agile/giga-repeat/commit/42492d8a839026e80c486d1e4f1621d16b5ae02f %>
5
+ <% address ||= address_form.object %>
6
+ <% address_id = address_type.chars.first %>
7
+
8
+ <%# address-autocomplete (Spree 5.3コアのGoogle Places補完) は外す。本フォームは
9
+ 可変フィールド方式で address1 等のコア必須ターゲットを持たないため、付けたままだと
10
+ コントローラが Missing target "address1" で disconnect 時に JSエラーを出す。 %>
11
+ <div class="inner"
12
+ data-controller="address-form"
13
+ <% cache address_form_countries_states_cache_key do %>
14
+ data-address-form-countries-value="<%= available_countries.to_json %>"
15
+ data-address-form-states-value="<%= available_states.to_json %>"
16
+ <% end %>
17
+ data-address-form-current-state-id-value="<%= address.state_id %>">
18
+
19
+ <% order_address_fields(current_store).each do |field| %>
20
+ <% if field == "country" %>
21
+ <%# 国フィールドをdisplay:noneで非表示にする(show_country_fieldがfalseの場合) %>
22
+ <div id="<%= "#{address_id}country" %>" <%= ('style="display:none;"'.html_safe) unless current_store.show_country_field %>>
23
+ <div class="form-group mb-0">
24
+ <div id="<%= "#{address_id}country-selection" %>">
25
+ <%= address_form.label(Spree.t(:country), Spree.t(:country), class: 'block text-xs text-neutral-600 mb-1') %>
26
+ <%= address_form.select :country_id, options_for_select(available_countries.map { |c| [c.name, c.id, data: { iso: c.iso }] }, address_form.object.country_id || current_store.default_country_id),
27
+ { },
28
+ { class: 'w-full select-input mb-4',
29
+ data: {
30
+ 'address-form-target': 'country',
31
+ 'action': "change->address-form#changeCountry"
32
+ },
33
+ aria: { label: Spree.t(:country) } } %>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ <% elsif field == "state" %>
38
+ <div class="form-group mb-4 address-form">
39
+ <%= address_field(address_form, :state, address_id) { address_state(address_form, address.country, address_id) } if Spree::Config[:address_requires_state] %>
40
+ </div>
41
+ <% elsif field == "zipcode" %>
42
+ <div class="form-group mb-4">
43
+ <%= address_field(address_form, :zipcode, address_id) { address_zipcode(address_form, address.country, address_id) } %>
44
+ </div>
45
+ <% else %>
46
+ <% next if field == "company" && !Spree::Config[:company] %>
47
+ <% next if field == "alternative_#{address_id}_phone" && !Spree::Config["alternative_#{address_id}_phone"] %>
48
+ <div class="form-group mb-4">
49
+ <%= address_field(address_form, field.to_sym, address_id) %>
50
+ </div>
51
+ <% end %>
52
+ <% end %>
53
+
54
+ <p class="text-right mb-5 checkout-content-inner-field"><span id="required_marker"><%= Spree.t(:required) %></span> <%= Spree.t(:required_fields) %></p>
55
+ </div>
@@ -0,0 +1,45 @@
1
+ <% s_or_b = type.chars.first %>
2
+
3
+ <div id="<%= type %>" data-hook="address_fields">
4
+ <% order_address_fields(Spree::Address::ADDRESS_FIELDS).each do |field| %>
5
+ <% if field == "country" %>
6
+ <%= field_container (s_or_b + '_' + field), nil, class: ["#{type}-row"] do %>
7
+ <%= f.label :country_id, Spree.t(:country) %>
8
+ <div id="<%= s_or_b %>country">
9
+ <%= f.collection_select :country_id, all_countries, :id, :name, {}, { class: 'select2 w-100' } %>
10
+ </div>
11
+ <% end %>
12
+ <% elsif field == "state" %>
13
+ <%= field_container (s_or_b + '_' + field), :state, class: ["#{type}-row"] do %>
14
+ <%= f.label :state_id, Spree.t(:state) %>
15
+ <div id="<%= s_or_b %>state">
16
+ <% if f.object.country.try(:states) %>
17
+ <%= f.text_field :state_name,
18
+ style: "display: #{f.object.country.try(:states) && f.object.country.states.empty? ? 'block' : 'none' };",
19
+ disabled: !(f.object.country.try(:states) && f.object.country.states.empty?), class: 'form-control state_name' %>
20
+ <%= f.collection_select :state_id, f.object.country.states.sort, :id, :name, { include_blank: true }, { class: 'select2 w-100', disabled: f.object.country.states.empty? } %>
21
+ <% else %>
22
+ <div>
23
+ <em><%= Spree.t(:no_country) %></em>
24
+ </div>
25
+ <% end %>
26
+ </div>
27
+ <%= error_message_on f.object, :state_id %>
28
+ <% end %>
29
+ <% else %>
30
+ <%= field_container (s_or_b + '_' + field), nil, class: ["#{type}-row"] do %>
31
+ <%= f.label field, Spree.t(field) %>
32
+ <%= f.text_field field, class: 'form-control' %>
33
+ <%= error_message_on f.object, field %>
34
+ <% end %>
35
+ <% end %>
36
+ <% end %>
37
+ </div>
38
+
39
+ <% content_for :head do %>
40
+ <script>
41
+ document.addEventListener("spree:load", function() {
42
+ $('#<%= s_or_b %>country select').on('change', function() { updateAddressState('<%= s_or_b %>'); });
43
+ })
44
+ </script>
45
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <div class="card mb-4">
2
+ <div class="card-header">
3
+ <h5 class="card-title"><%= Spree.t(:address_field_settings) %></h5>
4
+ </div>
5
+ <div class="card-body">
6
+ <%= f.spree_check_box :show_country_field, label: Spree.t(:show_country_field) %>
7
+ <%= f.spree_check_box :use_kana_fields, label: Spree.t(:use_kana_fields) %>
8
+ </div>
9
+ </div>
data/bin/rails ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" from the root of your extension
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/spree_address_format_i18n/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module PermittedAttributes
3
+ mattr_accessor :store_attributes
4
+
5
+ @@store_attributes ||= []
6
+ @@store_attributes += [
7
+ :use_kana_fields
8
+ ]
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ en:
2
+ spree:
3
+ use_kana_fields: "Use Kana Fields in Address"
4
+ show_country_field: "Show Country Field in Address"
5
+ address_field_settings: "Address Field Settings"
6
+ internationalization: "Internationalization"
@@ -0,0 +1,27 @@
1
+ ja:
2
+ spree:
3
+ lastname_kana: セイ
4
+ firstname_kana: メイ
5
+ fax: FAX
6
+ company_kana: カナ会社名
7
+ use_kana_fields: "住所にかなフィールドを使用する"
8
+ show_country_field: "住所に国フィールドを表示する"
9
+ address_field_settings: "住所フィールド設定"
10
+ internationalization: "国際化"
11
+ activerecord:
12
+ attributes:
13
+ spree/address:
14
+ lastname_kana: セイ
15
+ firstname_kana: メイ
16
+ company_kana: カナ会社名
17
+ fax: FAX
18
+ spree/order/bill_address:
19
+ lastname_kana: セイ
20
+ firstname_kana: メイ
21
+ company_kana: カナ会社名
22
+ fax: FAX
23
+ spree/order/ship_address:
24
+ lastname_kana: セイ
25
+ firstname_kana: メイ
26
+ company_kana: カナ会社名
27
+ fax: FAX