Module: Tina4::Localization
- Defined in:
- lib/tina4/localization.rb
Constant Summary collapse
- LOCALE_DIRS =
%w[locales translations i18n src/locales].freeze
Class Method Summary collapse
- .add(locale, key, value) ⇒ Object
- .add_translation(locale, key, value) ⇒ Object
-
.available_locales(root_dir = Dir.pwd) ⇒ Object
List available locale codes by scanning the configured locale dir(s) for *.json / *.yml / *.yaml file stems, sorted.
- .current_locale ⇒ Object
- .current_locale=(locale) ⇒ Object
-
.default_locale ⇒ Object
The fallback locale used when a key is missing in the current locale.
-
.flat_aliases ⇒ Object
Flat alias map: { locale => { leaf_key => value } } First-wins on conflict — later duplicates are ignored.
- .get_locale ⇒ Object
- .load(root_dir = Dir.pwd) ⇒ Object
-
.load_locale(locale, root_dir = Dir.pwd) ⇒ Object
Load a SINGLE locale's file (JSON, then YAML) from the configured search dirs if it is not already loaded.
- .load_translations(locale) ⇒ Object
- .set_locale(locale) ⇒ Object
- .t(key, locale: nil, default: nil, **interpolations) ⇒ Object
- .translate(key, params: nil, locale: nil) ⇒ Object
- .translations ⇒ Object
Class Method Details
.add(locale, key, value) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/tina4/localization.rb', line 114 def add(locale, key, value) translations[locale.to_s] ||= {} keys = key.to_s.split(".") hash = translations[locale.to_s] keys[0..-2].each do |k| hash[k] ||= {} hash = hash[k] end hash[keys.last] = value # Register leaf-key alias (first-wins) leaf = keys.last if value.is_a?(String) flat_aliases[locale.to_s] ||= {} flat_aliases[locale.to_s][leaf] ||= value end end |
.add_translation(locale, key, value) ⇒ Object
110 111 112 |
# File 'lib/tina4/localization.rb', line 110 def add_translation(locale, key, value) add(locale, key, value) end |
.available_locales(root_dir = Dir.pwd) ⇒ Object
List available locale codes by scanning the configured locale dir(s) for *.json / *.yml / *.yaml file stems, sorted. When no dir exists/has files, returns a [default_locale] floor (parity with Python/PHP/Node — never an empty list when a default locale is known).
136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/tina4/localization.rb', line 136 def available_locales(root_dir = Dir.pwd) stems = [] locale_search_dirs(root_dir).each do |locale_dir| %w[*.json *.yml *.yaml].each do |pattern| Dir.glob(File.join(locale_dir, pattern)).each do |file| stems << File.basename(file, File.extname(file)) end end end stems.uniq! stems.empty? ? [default_locale] : stems.sort end |
.current_locale ⇒ Object
19 20 21 |
# File 'lib/tina4/localization.rb', line 19 def current_locale @current_locale || ENV["TINA4_LOCALE"] || "en" end |
.current_locale=(locale) ⇒ Object
23 24 25 |
# File 'lib/tina4/localization.rb', line 23 def current_locale=(locale) @current_locale = locale.to_s end |
.default_locale ⇒ Object
The fallback locale used when a key is missing in the current locale. Mirrors the Python master (TINA4_LOCALE, else "en").
29 30 31 |
# File 'lib/tina4/localization.rb', line 29 def default_locale ENV["TINA4_LOCALE"] || "en" end |
.flat_aliases ⇒ Object
Flat alias map: { locale => { leaf_key => value } } First-wins on conflict — later duplicates are ignored.
15 16 17 |
# File 'lib/tina4/localization.rb', line 15 def flat_aliases @flat_aliases ||= {} end |
.get_locale ⇒ Object
97 98 99 |
# File 'lib/tina4/localization.rb', line 97 def get_locale current_locale end |
.load(root_dir = Dir.pwd) ⇒ Object
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/tina4/localization.rb', line 33 def load(root_dir = Dir.pwd) locale_search_dirs(root_dir).each do |locale_dir| Dir.glob(File.join(locale_dir, "*.json")).each do |file| ingest_json_file(File.basename(file, ".json"), file) end Dir.glob(File.join(locale_dir, "*.{yml,yaml}")).each do |file| ingest_yaml_file(File.basename(file, File.extname(file)), file) end end end |
.load_locale(locale, root_dir = Dir.pwd) ⇒ Object
Load a SINGLE locale's file (JSON, then YAML) from the configured search dirs if it is not already loaded. Boot-safe (a malformed file is skipped, never raised) — mirrors Python's _load_locale.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/tina4/localization.rb', line 75 def load_locale(locale, root_dir = Dir.pwd) locale = locale.to_s return if translations.key?(locale) locale_search_dirs(root_dir).each do |locale_dir| json = File.join(locale_dir, "#{locale}.json") if File.file?(json) ingest_json_file(locale, json) return end %w[yml yaml].each do |ext| yaml = File.join(locale_dir, "#{locale}.#{ext}") if File.file?(yaml) ingest_yaml_file(locale, yaml) return end end end # No file found — cache an empty table so lookups fall back to the key. translations[locale] ||= {} end |
.load_translations(locale) ⇒ Object
105 106 107 108 |
# File 'lib/tina4/localization.rb', line 105 def load_translations(locale) load(Dir.pwd) if translations.empty? translations[locale.to_s] || {} end |
.set_locale(locale) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'lib/tina4/localization.rb', line 63 def set_locale(locale) self.current_locale = locale.to_s # Lazily load the new locale's file if it hasn't been loaded yet, so a # switch to an unloaded locale resolves its keys (parity with Python/PHP/ # Node, where setting the locale triggers a per-locale load). load_locale(locale.to_s) unless translations.key?(locale.to_s) current_locale end |
.t(key, locale: nil, default: nil, **interpolations) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/tina4/localization.rb', line 44 def t(key, locale: nil, default: nil, **interpolations) lang = locale || current_locale value = lookup(lang, key) # Fallback: current locale -> default/fallback locale -> the key itself. if value.nil? && lang != default_locale value = lookup(default_locale, key) end value = default || key if value.nil? # Interpolation: "Hello {name}" => "Hello World". PARTIAL — each {name} # token present in interpolations is replaced; a missing param's # placeholder is left literal, and a malformed placeholder ({x.y} with a # dot, {n:d} with a spec, a lone unmatched brace) is left literal too. # Never raises — a bad template must not crash t(). interpolate(value, interpolations) end |
.translate(key, params: nil, locale: nil) ⇒ Object
101 102 103 |
# File 'lib/tina4/localization.rb', line 101 def translate(key, params: nil, locale: nil) t(key, locale: locale, **(params || {})) end |
.translations ⇒ Object
9 10 11 |
# File 'lib/tina4/localization.rb', line 9 def translations @translations ||= {} end |