Class: LcpRuby::I18nCheck::KeyDeriver
- Inherits:
-
Object
- Object
- LcpRuby::I18nCheck::KeyDeriver
- Defined in:
- lib/lcp_ruby/i18n_check/key_deriver.rb
Overview
Computes the canonical i18n key (or ordered lookup chain) for every labeled metadata element the lint inspects. Mirrors the runtime ‘I18n.t(…)` call sites — see `docs/design/i18n_consistency_check.md` §“Tier 1 vs Tier 2” for the canonical-key table.
Stateless. Used by ‘RegistryWalker` to compute keys for the missing-translation check and for suggested-fix messaging.
Defined Under Namespace
Classes: UnknownKindError
Constant Summary collapse
- TIER1_TEMPLATES =
Tier 1 — runtime calls ‘I18n.t(<key>, default: …)` on these. Lint checks each key against every configured locale; both `:missing_translation` and `:literal_in_dsl` may fire. Array values mean “ordered lookup chain”: the lint considers a key resolved if ANY entry resolves; missing-translation fires only when all entries are absent in a given locale.
{ presenter_label: "lcp_ruby.models.%{model}.other", presenter_description: "lcp_ruby.presenters.%{name}.%{view}.description", presenter_section: "lcp_ruby.presenters.%{name}.sections.%{section_key}", presenter_form_submit: "lcp_ruby.presenters.%{name}.form.submitting.%{action}", model_label_singular: "lcp_ruby.models.%{name}.one", model_label_plural: "lcp_ruby.models.%{name}.other", model_field: [ "lcp_ruby.models.%{model}.fields.%{field}", "lcp_ruby.fields.%{field}" ], model_enum_value: [ "lcp_ruby.models.%{model}.enums.%{field}.%{value}", "lcp_ruby.enums.%{model}.%{field}.%{value}" ], menu_entry: "lcp_ruby.menu.%{label_slug}", menu_aria_label: "lcp_ruby.menu.aria.%{label_slug}", workflow_state: "lcp_ruby.workflows.%{workflow}.states.%{state}", workflow_transition: "lcp_ruby.workflows.%{workflow}.transitions.%{transition}", custom_action_label: "lcp_ruby.actions.form.%{action}", scope_label: "lcp_ruby.scopes.%{name}", parameter_label: "lcp_ruby.parameters.%{name}" }.freeze
- TIER2_KINDS =
Tier 2 — runtime renders the literal directly. ‘derive` returns nil so callers know to skip missing-translation checks.
%i[ presenter_column_label presenter_field_label_override presenter_filter_label presenter_saved_filter_label presenter_tab_label presenter_step_label view_group_view_label workflow_state_description type_label nested_fields_add_label ].to_set.freeze
Instance Method Summary collapse
-
#derive(kind:, **args) ⇒ Object
Returns an Array of one or more keys (the lookup chain), or nil for Tier 2 kinds.
-
#expected_humanize_for(kind, args) ⇒ Object
The runtime “default” fallback that would render when the locale entry is missing.
-
#identifier_like?(value) ⇒ Boolean
Single source of truth for “looks like a code identifier rather than UI text.” Delegates to the ‘Heuristics` module so the walker’s Tier 2 path can suppress noise from snake_case enum keys, short ALL-CAPS acronyms, etc.
-
#parameterize_menu_label(label) ⇒ Object
Menu entries key off the parameterized rendered label, NOT the YAML path or any explicit identifier (see ‘lib/lcp_ruby/metadata/menu_item.rb`).
-
#parameterize_section(raw_title) ⇒ Object
Section keys are runtime-parameterized to snake_case before lookup (see ‘app/helpers/lcp_ruby/layout_helper.rb`).
-
#tier2?(kind) ⇒ Boolean
Returns true iff ‘kind` is recognised as Tier 2.
Instance Method Details
#derive(kind:, **args) ⇒ Object
Returns an Array of one or more keys (the lookup chain), or nil for Tier 2 kinds. Raises ‘UnknownKindError` for unrecognised kinds —the walker should always hand-pick from the documented list.
63 64 65 66 67 68 69 70 71 |
# File 'lib/lcp_ruby/i18n_check/key_deriver.rb', line 63 def derive(kind:, **args) return nil if TIER2_KINDS.include?(kind) template = TIER1_TEMPLATES.fetch(kind) do raise UnknownKindError, "unknown kind #{kind.inspect}; " \ "expected one of #{TIER1_TEMPLATES.keys + TIER2_KINDS.to_a}" end Array(template).map { |t| format(t, args.transform_values(&:to_s)) } end |
#expected_humanize_for(kind, args) ⇒ Object
The runtime “default” fallback that would render when the locale entry is missing. The walker compares the actual label against this to decide whether the author “overrode the default” (and therefore introduced a literal worth flagging).
Returns nil for kinds whose runtime fallback IS the literal itself (menu_entry, workflow_transition, workflow_state) — those use missing-only walker semantics, so the comparison never runs.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/lcp_ruby/i18n_check/key_deriver.rb', line 99 def expected_humanize_for(kind, args) case kind when :presenter_label, :model_label_singular, :scope_label, :parameter_label args[:name].to_s.humanize when :model_label_plural args[:name].to_s.humanize.pluralize when :presenter_section args[:section_key].to_s.humanize when :presenter_form_submit, :custom_action_label args[:action].to_s.humanize when :model_field args[:field].to_s.humanize when :model_enum_value args[:value].to_s.humanize when :presenter_description # Presenter descriptions have no humanize fallback — empty string # treated as "any literal is an override". "" when :menu_entry, :menu_aria_label, :workflow_state, :workflow_transition # Walker uses missing_only: true for these kinds; the comparison # is never invoked. nil is the explicit signal. nil end end |
#identifier_like?(value) ⇒ Boolean
Single source of truth for “looks like a code identifier rather than UI text.” Delegates to the ‘Heuristics` module so the walker’s Tier 2 path can suppress noise from snake_case enum keys, short ALL-CAPS acronyms, etc.
131 132 133 |
# File 'lib/lcp_ruby/i18n_check/key_deriver.rb', line 131 def identifier_like?(value) Heuristics.identifier_like?(value) end |
#parameterize_menu_label(label) ⇒ Object
Menu entries key off the parameterized rendered label, NOT the YAML path or any explicit identifier (see ‘lib/lcp_ruby/metadata/menu_item.rb`).
87 88 89 |
# File 'lib/lcp_ruby/i18n_check/key_deriver.rb', line 87 def (label) label.to_s.parameterize(separator: "_") end |
#parameterize_section(raw_title) ⇒ Object
Section keys are runtime-parameterized to snake_case before lookup (see ‘app/helpers/lcp_ruby/layout_helper.rb`). Walker must apply the same transformation when deriving the key from the raw title.
81 82 83 |
# File 'lib/lcp_ruby/i18n_check/key_deriver.rb', line 81 def parameterize_section(raw_title) raw_title.to_s.parameterize(separator: "_") end |
#tier2?(kind) ⇒ Boolean
Returns true iff ‘kind` is recognised as Tier 2.
74 75 76 |
# File 'lib/lcp_ruby/i18n_check/key_deriver.rb', line 74 def tier2?(kind) TIER2_KINDS.include?(kind) end |