Class: Locallingo::StateStore

Inherits:
Object
  • Object
show all
Defined in:
lib/locallingo/state_store.rb

Overview

Reads and writes the source-hash drift state under state_dir.

State is split into one JSON file per top-level namespace and locale (accounts.de.json, ...) so diffs stay small and reviewable. Each entry records the source hash a key was translated from, so a later source change marks the translation outdated. Optionally a target_hash and manual flag are tracked so hand-edited target values can be protected from overwrites.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(state_dir) ⇒ StateStore

Returns a new instance of StateStore.



18
19
20
21
# File 'lib/locallingo/state_store.rb', line 18

def initialize(state_dir)
  @state_dir = state_dir
  FileUtils.mkdir_p(@state_dir)
end

Instance Attribute Details

#state_dirObject (readonly)

Returns the value of attribute state_dir.



16
17
18
# File 'lib/locallingo/state_store.rb', line 16

def state_dir
  @state_dir
end

Class Method Details

.hash(text) ⇒ Object

CRC32 hash — fast and compact (8 hex chars).



24
25
26
# File 'lib/locallingo/state_store.rb', line 24

def self.hash(text)
  format("%08x", Zlib.crc32(text.to_s))
end

Instance Method Details

#hash(text) ⇒ Object



28
# File 'lib/locallingo/state_store.rb', line 28

def hash(text) = self.class.hash(text)

#load(locale) ⇒ Object

Load the combined state for a locale (merged across its namespace files).



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/locallingo/state_store.rb', line 31

def load(locale)
  combined = {}
  Dir.glob(File.join(state_dir, "*.#{locale}.json")).each do |file|
    combined.merge!(JSON.parse(File.read(file)))
  end
  combined
rescue JSON::ParserError => e
  raise Error,
        "Corrupted state file: #{e.message}\n" \
        "This would cause state loss. Fix the JSON manually or restore from git."
end

#save(locale, locale_state) ⇒ Object

Save a locale's state, split back into per-namespace files. Namespace files that no longer have keys are removed.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/locallingo/state_store.rb', line 45

def save(locale, locale_state)
  by_namespace = locale_state.each_with_object({}) do |(key, value), groups|
    namespace = key.split(".").first
    (groups[namespace] ||= {})[key] = value
  end

  by_namespace.each do |namespace, keys|
    state_file = File.join(state_dir, "#{namespace}.#{locale}.json")
    File.write(state_file, JSON.pretty_generate(keys.sort.to_h))
  end

  Dir.glob(File.join(state_dir, "*.#{locale}.json")).each do |file|
    namespace = File.basename(file).delete_suffix(".#{locale}.json")
    File.delete(file) unless by_namespace.key?(namespace)
  end
end