Module: Flycal::Locale

Defined in:
lib/flycal/locale.rb

Overview

Shared i18n helpers used by core formatters/pipelines. Locale JSON files live with the CLI package (flycal_cli/locales) by default.

Constant Summary collapse

FALLBACK_LOCALE =
"en"

Class Method Summary collapse

Class Method Details

.current_localeObject



42
43
44
# File 'lib/flycal/locale.rb', line 42

def current_locale
  Thread.current[:flycal_locale_override] || default_locale
end

.day_abbr(date_or_time) ⇒ Object



24
25
26
27
28
# File 'lib/flycal/locale.rb', line 24

def day_abbr(date_or_time)
  idx = date_or_time.to_date.wday
  days = t("common.weekdays.abbr")
  days[idx] || date_or_time.strftime("%a")
end

.day_name(date_or_time) ⇒ Object



18
19
20
21
22
# File 'lib/flycal/locale.rb', line 18

def day_name(date_or_time)
  idx = date_or_time.to_date.wday
  days = t("common.weekdays.full")
  days[idx] || date_or_time.strftime("%A").downcase
end

.default_localeObject



46
47
48
49
50
51
52
53
# File 'lib/flycal/locale.rb', line 46

def default_locale
  provider = Thread.current[:flycal_locale_default_provider]
  value = provider.call if provider.respond_to?(:call)
  value = value.to_s.strip if value
  value && !value.empty? ? value : FALLBACK_LOCALE
rescue StandardError
  FALLBACK_LOCALE
end

.default_locale_provider=(provider) ⇒ Object



55
56
57
# File 'lib/flycal/locale.rb', line 55

def default_locale_provider=(provider)
  Thread.current[:flycal_locale_default_provider] = provider
end

.default_locales_pathObject



72
73
74
75
76
77
78
79
80
# File 'lib/flycal/locale.rb', line 72

def default_locales_path
  # Monorepo: flycal_cli/locales; gem package: lib/../locales
  candidates = [
    File.expand_path("../../flycal_cli/locales", __dir__),
    File.expand_path("../../../locales", __dir__),
    File.expand_path("../../locales", __dir__)
  ]
  candidates.find { |path| Dir.exist?(path) } || candidates.first
end

.format_long_date(date_or_time) ⇒ Object



36
37
38
39
40
# File 'lib/flycal/locale.rb', line 36

def format_long_date(date_or_time)
  # Calendar date in the value's own zone — not TimeWithZone#to_time (system TZ / AS 8.1).
  d = Date.new(date_or_time.year, date_or_time.month, date_or_time.day)
  "#{day_abbr(d).downcase} #{d.day} #{month_name(d)} #{d.year}"
end

.interpolate(value, vars) ⇒ Object



97
98
99
100
101
102
103
# File 'lib/flycal/locale.rb', line 97

def interpolate(value, vars)
  return value unless value.is_a?(String)

  value.gsub(/%\{(\w+)\}/) do
    vars.fetch(Regexp.last_match(1).to_sym, Regexp.last_match(0)).to_s
  end
end

.locales_pathObject



63
64
65
# File 'lib/flycal/locale.rb', line 63

def locales_path
  Thread.current[:flycal_locales_path] || default_locales_path
end

.locales_path=(path) ⇒ Object



67
68
69
70
# File 'lib/flycal/locale.rb', line 67

def locales_path=(path)
  Thread.current[:flycal_locales_path] = path
  @cache = nil
end

.lookup(hash, dotted_key) ⇒ Object



91
92
93
94
95
# File 'lib/flycal/locale.rb', line 91

def lookup(hash, dotted_key)
  dotted_key.to_s.split(".").reduce(hash) do |acc, part|
    acc.is_a?(Hash) ? acc[part] : nil
  end
end

.month_name(date_or_time) ⇒ Object



30
31
32
33
34
# File 'lib/flycal/locale.rb', line 30

def month_name(date_or_time)
  idx = date_or_time.to_date.month - 1
  months = t("common.months.full")
  months[idx] || date_or_time.strftime("%B")
end

.override!(locale) ⇒ Object



59
60
61
# File 'lib/flycal/locale.rb', line 59

def override!(locale)
  Thread.current[:flycal_locale_override] = locale.to_s if locale && !locale.to_s.strip.empty?
end

.t(key, vars = {}) ⇒ Object



13
14
15
16
# File 'lib/flycal/locale.rb', line 13

def t(key, vars = {})
  value = lookup(translations(current_locale), key) || lookup(translations(FALLBACK_LOCALE), key) || key
  interpolate(value, vars)
end

.translations(locale) ⇒ Object



82
83
84
85
86
87
88
89
# File 'lib/flycal/locale.rb', line 82

def translations(locale)
  @cache ||= {}
  loc = locale.to_s
  @cache[loc] ||= begin
    path = File.join(locales_path, "#{loc}.json")
    File.exist?(path) ? JSON.parse(File.read(path)) : {}
  end
end