Completa i18n IT/EN/FR/DE/ES su sito pubblico, area autenticata e admin.
Tutte le view marketing, legali, viewer, dashboard e admin usano t(); mailer utente-facing e flash localizzati; admin con LocaleResolver e selettore lingua. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -23,7 +23,7 @@ module AdminHelper
|
||||
def admin_session_watch_links(session)
|
||||
links = []
|
||||
if session.matchlivetv_platform?
|
||||
links << { label: "Pagina live", url: session.watch_page_url }
|
||||
links << { label: I18n.t("admin.common.live_page"), url: session.watch_page_url }
|
||||
end
|
||||
youtube = session.youtube_watch_url
|
||||
links << { label: "YouTube", url: youtube } if youtube.present?
|
||||
|
||||
@@ -31,6 +31,34 @@ module ApplicationHelper
|
||||
I18n.locale.to_s
|
||||
end
|
||||
|
||||
def confirm_dialog_i18n_json
|
||||
{
|
||||
eyebrow: t("common.confirm_eyebrow"),
|
||||
title: t("common.confirm_title"),
|
||||
deleteTitle: t("common.delete_title"),
|
||||
confirmOk: t("common.confirm_ok"),
|
||||
deleteOk: t("common.delete_ok"),
|
||||
cancel: t("common.cancel"),
|
||||
multiDeleteTitle: t("common.multi_delete_title"),
|
||||
multiDeleteMessage: t("common.multi_delete_message"),
|
||||
deleteYoutubeTitle: t("common.delete_youtube_title"),
|
||||
deleteYoutubeMessage: t("common.delete_youtube_message"),
|
||||
deleteYoutubeOk: t("common.delete_youtube_ok"),
|
||||
deleteSiteTitle: t("common.delete_site_title"),
|
||||
deleteSiteMessageWithYoutube: t("common.delete_site_message_with_youtube"),
|
||||
deleteSiteMessageOnly: t("common.delete_site_message_only"),
|
||||
deleteSiteOk: t("common.delete_site_ok"),
|
||||
choiceSiteLabel: t("common.choice_site_label"),
|
||||
choiceSiteHintWithYoutube: t("common.choice_site_hint_with_youtube"),
|
||||
choiceSiteHintOnly: t("common.choice_site_hint_only"),
|
||||
choiceYoutubeLabel: t("common.choice_youtube_label"),
|
||||
choiceYoutubeHintWithSite: t("common.choice_youtube_hint_with_site"),
|
||||
choiceYoutubeHintOnly: t("common.choice_youtube_hint_only"),
|
||||
choiceBothLabel: t("common.choice_both_label"),
|
||||
choiceBothHint: t("common.choice_both_hint")
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def sport_catalog_options(selected = nil)
|
||||
options = Sports::Catalog.as_api_list.map { |entry| [entry[:label], entry[:key]] }
|
||||
options_for_select(options, Sports::Catalog.normalize_key(selected))
|
||||
|
||||
@@ -2,25 +2,25 @@ module Public
|
||||
module BillingHelper
|
||||
def plan_billing_action(current_slug:, target_plan:, stripe_subscription_active:, current_interval: nil, subscription: nil)
|
||||
if target_plan.slug == "free"
|
||||
return { kind: :current, label: "Piano attuale" } if current_slug == "free"
|
||||
return { kind: :current, label: I18n.t("billing.actions.current_plan") } if current_slug == "free"
|
||||
return { kind: :none } if stripe_subscription_active
|
||||
|
||||
return { kind: :contact, label: "Per passare al piano Free, contatta il supporto." }
|
||||
return { kind: :contact, label: I18n.t("billing.actions.contact_for_free") }
|
||||
end
|
||||
|
||||
unless MatchLiveTv.stripe_enabled?
|
||||
return { kind: :disabled, label: "Stripe non configurato" }
|
||||
return { kind: :disabled, label: I18n.t("billing.actions.stripe_not_configured") }
|
||||
end
|
||||
|
||||
intervals = Billing::Stripe::PriceCatalog.available_intervals(plan_slug: target_plan.slug)
|
||||
return { kind: :disabled, label: "Prezzi Stripe non configurati" } if intervals.empty?
|
||||
return { kind: :disabled, label: I18n.t("billing.actions.stripe_prices_not_configured") } if intervals.empty?
|
||||
|
||||
active_interval = current_interval.presence || Billing::Stripe::PriceCatalog::DEFAULT_INTERVAL
|
||||
|
||||
if current_slug == target_plan.slug && stripe_subscription_active && !subscription&.plan_change_pending?
|
||||
other_intervals = intervals - [active_interval]
|
||||
if other_intervals.empty?
|
||||
label = "Piano attuale — #{Billing::Stripe::PriceCatalog.label(plan_slug: target_plan.slug, interval: active_interval)}"
|
||||
label = "#{I18n.t('billing.actions.current_plan')} — #{Billing::Stripe::PriceCatalog.label(plan_slug: target_plan.slug, interval: active_interval)}"
|
||||
return { kind: :current, label: label }
|
||||
end
|
||||
|
||||
@@ -87,9 +87,9 @@ module Public
|
||||
|
||||
def billing_profile_incomplete_message(club)
|
||||
missing = club.billing_profile_errors
|
||||
return "Completa i dati di fatturazione prima di attivare un piano premium." if missing.empty?
|
||||
return I18n.t("billing.actions.profile_incomplete_default") if missing.empty?
|
||||
|
||||
"Mancano: #{missing.join(", ")}."
|
||||
I18n.t("billing.actions.profile_missing", fields: missing.join(", "))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -8,16 +8,16 @@ module Public
|
||||
when "basket", "timed"
|
||||
live_score_period_label(match, score_state)
|
||||
when "timer"
|
||||
"Cronometro"
|
||||
t("score.timer_label")
|
||||
when "generic"
|
||||
"Punteggio"
|
||||
t("score.generic_label")
|
||||
else
|
||||
"Set #{score_state.current_set} · Set vinti #{score_state.home_sets}-#{score_state.away_sets}"
|
||||
t("score.sets_label", set: score_state.current_set, home: score_state.home_sets, away: score_state.away_sets)
|
||||
end
|
||||
end
|
||||
|
||||
def live_score_period_label(match, score_state)
|
||||
return "—" unless score_state
|
||||
return t("score.fallback") unless score_state
|
||||
|
||||
score_state.current_period_label
|
||||
end
|
||||
@@ -35,16 +35,16 @@ module Public
|
||||
def live_scheduled_label(datetime)
|
||||
return nil unless datetime
|
||||
|
||||
datetime.in_time_zone.strftime("%d/%m/%Y alle %H:%M")
|
||||
datetime.in_time_zone.strftime(t("score.scheduled_date_format"))
|
||||
end
|
||||
|
||||
def live_scheduled_relative(datetime)
|
||||
return nil unless datetime
|
||||
|
||||
if datetime.to_date == Time.zone.today
|
||||
"Oggi alle #{datetime.strftime('%H:%M')}"
|
||||
t("score.scheduled_today", time: datetime.strftime("%H:%M"))
|
||||
elsif datetime.to_date == Time.zone.tomorrow
|
||||
"Domani alle #{datetime.strftime('%H:%M')}"
|
||||
t("score.scheduled_tomorrow", time: datetime.strftime("%H:%M"))
|
||||
else
|
||||
live_scheduled_label(datetime)
|
||||
end
|
||||
@@ -52,7 +52,7 @@ module Public
|
||||
|
||||
def live_match_card_heading(match, link_team: true)
|
||||
team = match.team
|
||||
club_name = team.club&.name.presence || "Società"
|
||||
club_name = team.club&.name.presence || t("score.default_club_name")
|
||||
team_slug = team.respond_to?(:slug) ? team.slug : nil
|
||||
team_label = if link_team && team_slug.present?
|
||||
link_to(team.name, public_team_page_path(team_slug), class: "live-card__team-link")
|
||||
@@ -69,7 +69,7 @@ module Public
|
||||
|
||||
def live_match_page_heading(match)
|
||||
team = match.team
|
||||
club_name = team.club&.name.presence || "Società"
|
||||
club_name = team.club&.name.presence || t("score.default_club_name")
|
||||
content_tag(:div, class: "live-page-heading") do
|
||||
safe_join([
|
||||
content_tag(:p, club_name, class: "live-page-heading__club"),
|
||||
@@ -79,7 +79,7 @@ module Public
|
||||
end
|
||||
|
||||
def live_score_points_label(match, score_state)
|
||||
return "—" unless score_state
|
||||
return t("score.fallback") unless score_state
|
||||
|
||||
board = match.effective_board_type
|
||||
home = case board
|
||||
@@ -91,7 +91,7 @@ module Public
|
||||
else score_state.away_points
|
||||
end
|
||||
|
||||
"#{match.team.name} #{home} - #{away} #{match.opponent_name}"
|
||||
t("score.points_label", team: match.team.name, home: home, away: away, opponent: match.opponent_name)
|
||||
end
|
||||
|
||||
private
|
||||
@@ -101,8 +101,11 @@ module Public
|
||||
set_no = data[:set] || data["set"]
|
||||
home = data[:home] || data["home"]
|
||||
away = data[:away] || data["away"]
|
||||
label = set_no.present? ? "Set #{set_no}" : "Set"
|
||||
"#{label} #{home}-#{away}"
|
||||
if set_no.present?
|
||||
t("score.partial_entry", set: set_no, home: home, away: away)
|
||||
else
|
||||
t("score.partial_entry_no_number", home: home, away: away)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,14 +12,60 @@ module Public
|
||||
when "basket", "timed"
|
||||
live_score_period_label(match, score)
|
||||
when "timer"
|
||||
"Cronometro"
|
||||
t("regia.board.stopwatch")
|
||||
when "generic"
|
||||
"Punteggio"
|
||||
t("regia.board.generic_score")
|
||||
else
|
||||
"Set #{score.current_set}"
|
||||
t("regia.board.set_label", number: score.current_set)
|
||||
end
|
||||
end
|
||||
|
||||
def regia_js_i18n_json
|
||||
{
|
||||
periodUpdated: t("regia.js.period_updated"),
|
||||
nowInPeriodTemplate: t("regia.js.now_in_period", period: "%{period}"),
|
||||
setWonTitle: t("regia.modal.set_won_title"),
|
||||
setWonBodyTemplate: t("regia.js.set_won_body", winner: "%{winner}"),
|
||||
matchWonTitle: t("regia.js.match_won_title"),
|
||||
matchWonBodyTemplate: t("regia.js.match_won_body", winner: "%{winner}"),
|
||||
closeSetTitle: t("regia.board.close_set"),
|
||||
closeSetConfirm: t("regia.js.close_set_confirm"),
|
||||
scoreUpdateError: t("regia.js.score_update_error"),
|
||||
genericError: t("regia.js.generic_error"),
|
||||
setsLineTemplate: t("regia.js.sets_line", current: "%{current}", home: "%{home}", away: "%{away}"),
|
||||
setPartialLabelTemplate: t("regia.board.set_label", number: "%{number}"),
|
||||
freeScore: t("regia.board.free_score"),
|
||||
stopwatch: t("regia.board.stopwatch"),
|
||||
quarterLabelTemplate: t("regia.js.quarter_label", n: "%{n}"),
|
||||
halfLabelTemplate: t("regia.js.half_label", n: "%{n}"),
|
||||
overtimeBasketTemplate: t("regia.js.overtime_basket", n: "%{n}"),
|
||||
overtimeOther: t("regia.js.overtime_other"),
|
||||
unknownPeriod: t("regia.js.unknown_period"),
|
||||
partialsPrefix: t("regia.board.partials_prefix"),
|
||||
resumed: t("regia.js.resumed"),
|
||||
pausedCover: t("regia.js.paused_cover"),
|
||||
closed: t("regia.js.closed"),
|
||||
resumeError: t("regia.js.resume_error"),
|
||||
pauseError: t("regia.js.pause_error"),
|
||||
closeError: t("regia.js.close_error"),
|
||||
closeConfirm: t("regia.js.close_confirm"),
|
||||
linkUnavailable: t("regia.js.link_unavailable"),
|
||||
linkCopied: t("regia.js.link_copied"),
|
||||
copyPrompt: t("regia.js.copy_prompt"),
|
||||
shareRegiaText: t("regia.js.share_regia_text"),
|
||||
shareLiveText: t("regia.js.share_live_text"),
|
||||
previewWaiting: t("regia.preview_waiting"),
|
||||
streamEnded: t("regia.preview_ended"),
|
||||
resumeLabel: t("regia.resume"),
|
||||
pauseLabel: t("regia.pause"),
|
||||
endedBadge: t("regia.status.ended"),
|
||||
pausedBadge: t("regia.status.paused"),
|
||||
liveBadge: t("regia.status.live"),
|
||||
waitingBadge: t("regia.status.waiting"),
|
||||
subtitlePrefix: t("regia.subtitle_prefix")
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def format_clock_secs(secs, count_up: false)
|
||||
total = secs.to_i
|
||||
return count_up ? "0:00" : "—" if total <= 0 && !count_up
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module Public
|
||||
module TeamPagesHelper
|
||||
def team_page_meta_description(team, club)
|
||||
"Segui #{team.name} (#{club.name}): dirette live, calendario partite e replay su Match Live TV."
|
||||
t("team_pages.show.meta_description", team: team.name, club: club.name)
|
||||
end
|
||||
|
||||
def filter_params_for_canonical
|
||||
|
||||
@@ -19,14 +19,14 @@ module RosterHelper
|
||||
|
||||
def roster_category_options
|
||||
TeamRosterMember::DISPLAY_ORDER.map do |cat|
|
||||
[TeamRosterMember::CATEGORY_LABELS[cat], cat]
|
||||
[TeamRosterMember.category_label(cat), cat]
|
||||
end
|
||||
end
|
||||
|
||||
def roster_player_role_options(team, selected = nil)
|
||||
roles = Sports::PlayerRoles.for_team(team)
|
||||
options_for_select(
|
||||
[["— Seleziona ruolo —", ""]] + roles.map { |r| [r, r] },
|
||||
[[t("roster.role_select_blank"), ""]] + roles.map { |r| [r, r] },
|
||||
selected
|
||||
)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user