i18n-tasks 0.3.6 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,127 +0,0 @@
1
- require 'i18n/tasks/data_traversal'
2
- require 'i18n/tasks/key_pattern_matching'
3
-
4
- module I18n::Tasks
5
- module Data
6
- module Storage
7
- module FileStorage
8
-
9
- def self.included(base)
10
- base.extend KlassMethods
11
- end
12
-
13
- include ::I18n::Tasks::DataTraversal
14
- include ::I18n::Tasks::KeyPatternMatching
15
- attr_reader :config
16
-
17
- DEFAULTS = {
18
- read: ['config/locales/%{locale}.yml'],
19
- write: ['config/locales/%{locale}.yml']
20
- }.with_indifferent_access
21
-
22
- def initialize(config = {})
23
- self.config = config
24
- end
25
-
26
- def config=(config)
27
- opt = DEFAULTS.deep_merge((config || {}).with_indifferent_access)
28
- @read = opt[:read]
29
- @write = opt[:write].map { |x| x.is_a?(String) ? ['*', x] : x }.map { |x|
30
- [compile_key_pattern(x[0]), x[1]]
31
- }
32
- @locale_data = {}
33
- end
34
-
35
- # get locale tree
36
- def get(locale)
37
- locale = locale.to_s
38
- @locale_data[locale] ||= begin
39
- @read.map do |path|
40
- Dir.glob path % {locale: locale}
41
- end.flatten.map do |locale_file|
42
- load_file locale_file
43
- end.inject({}) do |hash, locale_data|
44
- hash.deep_merge! locale_data || {}
45
- hash
46
- end[locale.to_s] || {}
47
- end.with_indifferent_access
48
- end
49
-
50
- alias [] get
51
-
52
- # set locale tree
53
- def set(locale, value_tree)
54
- locale = locale.to_s
55
- out = {}
56
- traverse value_tree do |key, value|
57
- route = @write.detect { |route| route[0] =~ key }
58
- key_match = $~
59
- path = route[1] % {locale: locale}
60
- path.gsub!(/[\\]\d+/) { |m| key_match[m[1..-1].to_i] }
61
- (out[path] ||= []) << [key, value]
62
- end
63
- out.each do |path, data|
64
- tree = {locale => list_to_tree(data)}
65
- write_tree(path, tree)
66
- end
67
- @locale_data[locale] = nil
68
- end
69
-
70
- alias []= set
71
-
72
- def reload
73
- @locale_data = {}
74
- @available_locales = nil
75
- self
76
- end
77
-
78
- # Get available locales from the list of file names to read
79
- def available_locales
80
- @available_locales ||= begin
81
- locales = Set.new
82
- @read.map do |pattern|
83
- [pattern, Dir.glob(pattern % {locale: '*'})] if pattern.include?('%{locale}')
84
- end.compact.each do |pattern, paths|
85
- p = pattern.gsub('\\', '\\\\').gsub('/', '\/').gsub('.', '\.')
86
- p = p.gsub(/(\*+)/) { $1 == '**' ? '.*' : '[^/]*?' }.gsub('%{locale}', '([^/.]+)')
87
- re = /\A#{p}\z/
88
- paths.each do |path|
89
- if re =~ path
90
- locales << $1
91
- end
92
- end
93
- end
94
- locales
95
- end
96
- end
97
-
98
- protected
99
-
100
- def load_file(file)
101
- adapter_for(file).parse ::File.read(file)
102
- end
103
-
104
- def write_tree(path, tree)
105
- ::File.open(path, 'w') { |f| f.write(adapter_for(path).dump(tree)) }
106
- end
107
-
108
- def adapter_for(file)
109
- self.class.adapter_for(file)
110
- end
111
-
112
- module KlassMethods
113
- # @param pattern [String] File.fnmatch pattern
114
- # @param adapter [responds to parse(string)->hash and dump(hash)->string]
115
- def register_adapter(pattern, adapter)
116
- (@fn_patterns ||= {})[pattern] = adapter
117
- end
118
-
119
- def adapter_for(path)
120
- @fn_patterns.detect { |pattern, adapter| ::File.fnmatch(pattern, path) }[1] or
121
- raise "Adapter not found for #{path}. Registered adapters: #{@fn_patterns.inspect}"
122
- end
123
- end
124
- end
125
- end
126
- end
127
- end
@@ -1,51 +0,0 @@
1
- module I18n::Tasks::DataTraversal
2
- # translation of the key found in the passed hash or nil
3
- # @return [String,nil]
4
- def t(key, locale = base_locale)
5
- key.to_s.split('.').inject(self.data[locale]) { |r, seg| r[seg] if r }
6
- end
7
-
8
- def t_proc(locale = base_locale)
9
- proc { |k| t(k, locale) }
10
- end
11
-
12
- # traverse => map if yield(k, v)
13
- def traverse_map_if(hash)
14
- list = []
15
- traverse hash do |k, v|
16
- mapped = yield(k, v)
17
- list << mapped if mapped
18
- end
19
- list
20
- end
21
-
22
- # traverse hash, yielding with full key and value
23
- # @param hash [Hash{String => String,Hash}] translation data to traverse
24
- # @yield [full_key, value] yields full key and value for every translation in #hash
25
- # @return [nil]
26
- def traverse(path = '', hash)
27
- q = [[path, hash]]
28
- until q.empty?
29
- path, value = q.pop
30
- if value.is_a?(Hash)
31
- value.each { |k, v| q << ["#{path}.#{k}", v] }
32
- else
33
- yield path[1..-1], value
34
- end
35
- end
36
- end
37
-
38
- # [[key, value], ...] list to tree
39
- def list_to_tree(list)
40
- list = list.sort
41
- tree = {}
42
- list.each do |key, value|
43
- key_segments = key.to_s.split('.')
44
- node = key_segments[0..-2].inject(tree) do |r, segment|
45
- r[segment] ||= {}
46
- end
47
- node[key_segments.last] = value
48
- end
49
- tree
50
- end
51
- end
@@ -1,60 +0,0 @@
1
- require 'i18n/tasks/data/file_system'
2
-
3
- module I18n::Tasks::TranslationData
4
-
5
- # I18n data provider
6
- # @see I18n::Tasks::Data::Yaml
7
- def data
8
- @data ||= data_config[:adapter].constantize.new(data_config[:options])
9
- end
10
-
11
- # whether the value for key exists in locale (defaults: base_locale)
12
- def key_value?(key, locale = base_locale)
13
- t(key, locale).present?
14
- end
15
-
16
- def non_base_locales(from = nil)
17
- from = self.locales unless from
18
- Array(from) - [base_locale]
19
- end
20
-
21
- # write to store, normalizing all data
22
- def normalize_store!(from = nil)
23
- from = self.locales unless from
24
- Array(from).each do |target_locale|
25
- # the store itself handles normalization
26
- data[target_locale] = data[target_locale]
27
- end
28
- end
29
-
30
- # @param locales
31
- # @param locale
32
- # @param keys
33
- # @param value
34
- # @param values
35
- def update_data(opts = {})
36
- if opts.key?(:locales)
37
- locales = (Array(opts[:locales]).presence || self.locales).map(&:to_s)
38
- # make sure base_locale always comes first if present
39
- locales = [base_locale] + (locales - [base_locale]) if locales.include?(base_locale)
40
- opts = opts.except(:locales)
41
- locales.each { |locale| update_data(opts.merge(locale: locale)) }
42
- return
43
- end
44
- locale = opts[:locale] || base_locale
45
- keys = opts[:keys]
46
- keys = keys.call(locale) if keys.respond_to?(:call)
47
- return if keys.empty?
48
- values = opts[:values]
49
- values = values.call(keys, locale) if values.respond_to?(:call)
50
- unless values
51
- value = opts[:value]
52
- values = if value.respond_to?(:call)
53
- keys.map { |key| value.call(key, locale) }
54
- else
55
- [value] * keys.size
56
- end
57
- end
58
- data[locale] = data[locale].deep_merge(list_to_tree keys.map(&:to_s).zip(values))
59
- end
60
- end