Module: StructuredParams::I18n

Extended by:
ActiveSupport::Concern
Included in:
Params
Defined in:
lib/structured_params/i18n.rb,
sig/structured_params/i18n.rbs

Overview

Provides i18n-aware human_attribute_name resolution for nested dot-notation attributes (e.g. "hobbies.0.name").

When included in a Params subclass, overrides human_attribute_name so that each segment of the path is resolved by the corresponding nested model class, ensuring that child-model translations are respected instead of falling back to the parent model's i18n context.

i18n keys

You can customize how array indices and object nesting are rendered by defining the following keys in your locale file:

ja:
activemodel:
  errors:
    nested_attribute:
      array:  "%{parent} %{index} 番目の%{child}"
      object: "%{parent}の%{child}"

Without these keys the defaults are (with array_index_base: 0):

array  → "<parent> <index> <child>"   (e.g. "Hobbies 0 Name")
object → "<parent> <child>"           (e.g. "Address Postal code")

With array_index_base: 1 (human-friendly):

array   "Hobbies 1 Name"

Instance Method Summary collapse

Instance Method Details

#attr_segmentsArray[[ String?, String ]]

Convert a parts array into (index_or_nil, attr) pairs.

attr_segments(["hobbies", "0", "name"]) #=> [[nil, "hobbies"], ["0", "name"]]
attr_segments(["address", "postal_code"]) #=> [[nil, "address"], [nil, "postal_code"]]

: (Array) -> Array[[String?, String]]

Parameters:

  • (Array[String])

Returns:

  • (Array[[ String?, String ]])


66
# File 'sig/structured_params/i18n.rbs', line 66

def attr_segments: (Array[String]) -> Array[[ String?, String ]]

#build_nested_labelString

Combine result (accumulated label so far), an optional array index, and the new attr_human into a single label string.

Uses the i18n keys:

activemodel.errors.nested_attribute.array  (parent, index, child)
activemodel.errors.nested_attribute.object (parent, child)

The index value passed to the i18n template is adjusted by StructuredParams.configuration.array_index_base:

* +0+ (default) – raw 0-based Ruby index (e.g. 0, 1, 2, …)
* +1+           – human-friendly 1-based index (e.g. 1, 2, 3, …)

The locale: key from options is forwarded to ::I18n.t so that an explicit locale passed to human_attribute_name is honoured.

: (String?, String?, String, Hash[untyped, untyped]) -> String

Parameters:

  • (String, nil)
  • (String, nil)
  • (String)
  • (Hash[untyped, untyped])

Returns:

  • (String)


84
# File 'sig/structured_params/i18n.rbs', line 84

def build_nested_label: (String?, String?, String, Hash[untyped, untyped]) -> String

#human_attribute_nameString

Override human_attribute_name to resolve nested dot-notation paths.

Flat attributes (no dot) are delegated to the default ActiveModel behaviour unchanged.

Example (en default, array_index_base: 0):

human_attribute_name(:'hobbies.0.name') # => "Hobbies 0 Name"

Example with i18n (ja) and array_index_base: 1:

human_attribute_name(:'hobbies.0.name') # => "趣味 1 番目の名前"

: (Symbol | String, ?Hash[untyped, untyped]) -> String

Parameters:

  • (Symbol, String)
  • (Hash[untyped, untyped])

Returns:

  • (String)


45
# File 'sig/structured_params/i18n.rbs', line 45

def human_attribute_name: (Symbol | String, ?Hash[untyped, untyped]) -> String

#resolve_nested_human_attribute_nameString

Walk parts (e.g. ["hobbies", "0", "name"]) and build a human-readable label by delegating each segment to the appropriate nested class.

Only :locale is forwarded to inner human_attribute_name calls. Options such as :default are specific to the outer call (e.g. from full_messages) and must not bleed into individual segment lookups, where they would replace the segment's own translation fallback.

: (Array, Hash[untyped, untyped]) -> String

Parameters:

  • (Array[String])
  • (Hash[untyped, untyped])

Returns:

  • (String)


58
# File 'sig/structured_params/i18n.rbs', line 58

def resolve_nested_human_attribute_name: (Array[String], Hash[untyped, untyped]) -> String