fast_gettext 1.6.0 → 2.1.0

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,29 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fast_gettext/mo_file'
2
4
  module FastGettext
3
5
  # Responsibility:
4
6
  # - abstract po files for Po Repository
5
7
  class PoFile < MoFile
6
- def initialize(file, options={})
8
+ def initialize(file, options = {})
7
9
  @options = options
8
10
  super
9
11
  end
10
12
 
11
- def self.to_mo_file(file, options={})
13
+ def self.to_mo_file(file, options = {})
12
14
  MoFile.new(parse_po_file(file, options))
13
15
  end
14
16
 
15
- protected
16
-
17
- def load_data
18
- @data = if @filename.is_a? FastGettext::GetText::MOFile
19
- @filename
20
- else
21
- FastGettext::PoFile.parse_po_file(@filename, @options)
22
- end
23
- make_singular_and_plural_available
24
- end
25
-
26
- def self.parse_po_file(file, options={})
17
+ def self.parse_po_file(file, options = {})
27
18
  require 'fast_gettext/vendor/poparser'
28
19
  parser = FastGettext::GetText::PoParser.new
29
20
 
@@ -35,5 +26,17 @@ module FastGettext
35
26
  parser.parse_file(file, mo_file)
36
27
  mo_file
37
28
  end
29
+
30
+ protected
31
+
32
+ def load_data
33
+ @data =
34
+ if @filename.is_a? FastGettext::GetText::MOFile
35
+ @filename
36
+ else
37
+ FastGettext::PoFile.parse_po_file(@filename, @options)
38
+ end
39
+ make_singular_and_plural_available
40
+ end
38
41
  end
39
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fast_gettext/cache'
2
4
 
3
5
  module FastGettext
@@ -12,11 +14,15 @@ module FastGettext
12
14
  end
13
15
  end
14
16
 
17
+ DEFAULT_PLURALIZATION_RULE = ->(i) { i != 1 }
18
+
15
19
  [:available_locales, :_locale, :text_domain, :pluralisation_rule].each do |method_name|
16
- key = "fast_gettext_#{method_name}".to_sym
17
- define_method "#{method_name}=" do |value|
18
- switch_cache if Thread.current[key] != Thread.current[key]=value
19
- end
20
+ key = "fast_gettext_#{method_name}"
21
+ eval <<-RUBY, nil, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
22
+ def #{method_name}=(value)
23
+ switch_cache if Thread.current[:#{key}] != Thread.current[:#{key}] = value
24
+ end
25
+ RUBY
20
26
  end
21
27
 
22
28
  def _locale
@@ -24,11 +30,11 @@ module FastGettext
24
30
  end
25
31
  private :_locale, :_locale=
26
32
 
27
-
28
33
  def available_locales
29
34
  locales = Thread.current[:fast_gettext_available_locales] || default_available_locales
30
35
  return unless locales
31
- locales.map{|s|s.to_s}
36
+
37
+ locales.map(&:to_s)
32
38
  end
33
39
 
34
40
  # cattr_accessor with defaults
@@ -37,7 +43,7 @@ module FastGettext
37
43
  [:default_text_domain, "nil"],
38
44
  [:cache_class, "FastGettext::Cache"]
39
45
  ].each do |name, default|
40
- eval <<-Ruby
46
+ eval <<-RUBY, nil, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
41
47
  @@#{name} = #{default}
42
48
  def #{name}=(value)
43
49
  @@#{name} = value
@@ -47,7 +53,7 @@ module FastGettext
47
53
  def #{name}
48
54
  @@#{name}
49
55
  end
50
- Ruby
56
+ RUBY
51
57
  end
52
58
 
53
59
  def text_domain
@@ -57,7 +63,7 @@ module FastGettext
57
63
  # if overwritten by user( FastGettext.pluralisation_rule = xxx) use it,
58
64
  # otherwise fall back to repo or to default lambda
59
65
  def pluralisation_rule
60
- Thread.current[:fast_gettext_pluralisation_rule] || current_repository.pluralisation_rule || lambda{|i| i!=1}
66
+ Thread.current[:fast_gettext_pluralisation_rule] || current_repository.pluralisation_rule || DEFAULT_PLURALIZATION_RULE
61
67
  end
62
68
 
63
69
  def cache
@@ -69,8 +75,8 @@ module FastGettext
69
75
  translation_repositories.values.each(&:reload)
70
76
  end
71
77
 
72
- #global, since re-parsing whole folders takes too much time...
73
- @@translation_repositories={}
78
+ # global, since re-parsing whole folders takes too much time...
79
+ @@translation_repositories = {} # rubocop:disable Style/ClassVars
74
80
  def translation_repositories
75
81
  @@translation_repositories
76
82
  end
@@ -97,7 +103,7 @@ module FastGettext
97
103
  end
98
104
 
99
105
  def locale
100
- _locale || ( default_locale || (available_locales||[]).first || 'en' )
106
+ _locale || (default_locale || (available_locales || []).first || 'en')
101
107
  end
102
108
 
103
109
  def locale=(new_locale)
@@ -107,15 +113,15 @@ module FastGettext
107
113
  # for chaining: puts set_locale('xx') == 'xx' ? 'applied' : 'rejected'
108
114
  # returns the current locale, not the one that was supplied
109
115
  # like locale=(), whoes behavior cannot be changed
110
- def set_locale(new_locale)
116
+ def set_locale(new_locale) # rubocop:disable Naming/AccessorMethodName
111
117
  new_locale = best_locale_in(new_locale)
112
118
  self._locale = new_locale
113
119
  locale
114
120
  end
115
121
 
116
- @@default_locale = nil
122
+ @@default_locale = nil # rubocop:disable Style/ClassVars
117
123
  def default_locale=(new_locale)
118
- @@default_locale = best_locale_in(new_locale)
124
+ @@default_locale = best_locale_in(new_locale) # rubocop:disable Style/ClassVars
119
125
  switch_cache
120
126
  end
121
127
 
@@ -123,17 +129,17 @@ module FastGettext
123
129
  @@default_locale
124
130
  end
125
131
 
126
- #Opera: de-DE,de;q=0.9,en;q=0.8
127
- #Firefox de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
128
- #IE6/7 de
129
- #nil if nothing matches
132
+ # Opera: de-DE,de;q=0.9,en;q=0.8
133
+ # Firefox de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
134
+ # IE6/7 de
135
+ # nil if nothing matches
130
136
  def best_locale_in(locales)
131
137
  formatted_sorted_locales(locales).each do |candidate|
132
- return candidate if not available_locales
138
+ return candidate unless available_locales
133
139
  return candidate if available_locales.include?(candidate)
134
- return candidate[0..1] if available_locales.include?(candidate[0..1])#available locales include a langauge
140
+ return candidate[0..1] if available_locales.include?(candidate[0..1]) # available locales include a langauge
135
141
  end
136
- return nil#nothing found im sorry :P
142
+ nil # nothing found im sorry :P
137
143
  end
138
144
 
139
145
  # temporarily switch locale for a block
@@ -146,27 +152,27 @@ module FastGettext
146
152
  set_locale current_locale
147
153
  end
148
154
 
149
- #turn off translation if none was defined to disable all resulting errors
155
+ # turn off translation if none was defined to disable all resulting errors
150
156
  def silence_errors
151
157
  require 'fast_gettext/translation_repository/base'
152
- translation_repositories[text_domain] ||= TranslationRepository::Base.new('x', :path => 'locale')
158
+ translation_repositories[text_domain] ||= TranslationRepository::Base.new('x', path: 'locale')
153
159
  end
154
160
 
155
161
  private
156
162
 
157
163
  # de-de,DE-CH;q=0.9 -> ['de_DE','de_CH']
158
164
  def formatted_sorted_locales(locales)
159
- found = weighted_locales(locales).reject{|x|x.empty?}.sort_by{|l|l.last}.reverse #sort them by weight which is the last entry
160
- found.flatten.map{|l| format_locale(l)}
165
+ found = weighted_locales(locales).reject(&:empty?).sort_by(&:last).reverse # sort them by weight which is the last entry
166
+ found.flatten.map { |l| format_locale(l) }
161
167
  end
162
168
 
163
- #split the locale and seperate it into different languages
164
- #de-de,de;q=0.9,en;q=0.8 => [['de-de','de','0.5'], ['en','0.8']]
169
+ # split the locale and seperate it into different languages
170
+ # de-de,de;q=0.9,en;q=0.8 => [['de-de','de','0.5'], ['en','0.8']]
165
171
  def weighted_locales(locales)
166
- locales = locales.to_s.gsub(/\s/,'')
172
+ locales = locales.to_s.gsub(/\s/, '')
167
173
  found = [[]]
168
174
  locales.split(',').each do |part|
169
- if part =~ /;q=/ #contains language and weight ?
175
+ if part.include? ';q=' # contains language and weight ?
170
176
  found.last << part.split(/;q=/)
171
177
  found.last.flatten!
172
178
  found << []
@@ -177,9 +183,9 @@ module FastGettext
177
183
  found
178
184
  end
179
185
 
180
- #de-de -> de_DE
186
+ # de-de -> de_DE
181
187
  def format_locale(locale)
182
- locale.sub(/^([a-zA-Z]{2,3})[-_]([a-zA-Z]{2,3})$/){$1.downcase+'_'+$2.upcase}
188
+ locale.sub(/^([a-zA-Z]{2,3})[-_]([a-zA-Z]{2,3})$/) { $1.downcase + '_' + $2.upcase }
183
189
  end
184
190
 
185
191
  def switch_cache
@@ -1,4 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FastGettext
4
+ TRANSLATION_METHODS = [:_, :n_, :s_, :p_, :ns_, :np_].freeze
5
+ NIL_BLOCK = -> { nil }
6
+
2
7
  # this module should be included
3
8
  # Responsibility:
4
9
  # - direct translation queries to the current repository
@@ -6,145 +11,114 @@ module FastGettext
6
11
  # - understand / enforce namespaces
7
12
  # - decide which plural form is used
8
13
  module Translation
9
- extend self
10
-
11
- #make it usable in class definition, e.g.
12
- # class Y
13
- # include FastGettext::Translation
14
- # @@x = _('y')
15
- # end
16
- def self.included(klas) #:nodoc:
17
- klas.extend self
18
- end
19
-
20
- def _(key, &block)
21
- FastGettext.cached_find(key) or (block ? block.call : key)
14
+ def _(key)
15
+ FastGettext.cached_find(key) || (block_given? ? yield : key)
22
16
  end
23
17
 
24
- #translate pluralized
18
+ # translate pluralized
25
19
  # some languages have up to 4 plural forms...
26
20
  # n_(singular, plural, plural form 2, ..., count)
27
21
  # n_('apple','apples',3)
28
- def n_(*keys, &block)
29
- count = keys.pop
22
+ def n_(*keys, count)
30
23
  translations = FastGettext.cached_plural_find(*keys)
31
-
32
24
  selected = FastGettext.pluralisation_rule.call(count)
33
- selected = (selected ? 1 : 0) unless selected.is_a? Numeric #convert booleans to numbers
25
+ selected = (selected ? 1 : 0) unless selected.is_a? Numeric # convert booleans to numbers
34
26
 
27
+ # If we have a translation return it
35
28
  result = translations[selected]
36
- if result
37
- result
38
- elsif keys[selected]
39
- _(keys[selected])
40
- else
41
- block ? block.call : keys.last
42
- end
29
+ return result if result
30
+
31
+ # If we have a block always use it in place of a translation
32
+ return yield if block_given?
33
+
34
+ # Fall back to the best fit translated key if it's there
35
+ _(keys[selected] || keys.last)
36
+ end
37
+
38
+ # translate with namespace
39
+ # 'Car', 'Tire' -> Tire if no translation could be found
40
+ # p_('Car', 'Tire') == s_('Car|Tire')
41
+ def p_(namespace, key, separator = nil)
42
+ msgid = "#{namespace}#{separator || CONTEXT_SEPARATOR}#{key}"
43
+
44
+ translation = FastGettext.cached_find(msgid)
45
+ return translation if translation
46
+
47
+ block_given? ? yield : key
43
48
  end
44
49
 
45
- #translate, but discard namespace if nothing was found
50
+ # translate, but discard namespace if nothing was found
46
51
  # Car|Tire -> Tire if no translation could be found
47
- def s_(key, separator=nil, &block)
48
- translation = FastGettext.cached_find(key) and return translation
49
- block ? block.call : key.split(separator||NAMESPACE_SEPARATOR).last
52
+ def s_(key, separator = nil)
53
+ translation = FastGettext.cached_find(key)
54
+ return translation if translation
55
+
56
+ block_given? ? yield : key.split(separator || NAMESPACE_SEPARATOR).last
50
57
  end
51
58
 
52
- #tell gettext: this string need translation (will be found during parsing)
59
+ # tell gettext: this string need translation (will be found during parsing)
53
60
  def N_(translate)
54
61
  translate
55
62
  end
56
63
 
57
- #tell gettext: this string need translation (will be found during parsing)
64
+ # tell gettext: this string need translation (will be found during parsing)
58
65
  def Nn_(*keys)
59
66
  keys
60
67
  end
61
68
 
62
- def ns_(*args, &block)
63
- translation = n_(*args, &block)
64
- # block is called once again to compare result
65
- block && translation == block.call ? translation : translation.split(NAMESPACE_SEPARATOR).last
66
- end
67
- end
69
+ # translate pluralized with separator
70
+ def ns_(*args)
71
+ translation = n_(*args, &NIL_BLOCK)
72
+ return translation if translation
68
73
 
69
- # this module should be included for multi-domain support
70
- module TranslationMultidomain
71
- extend self
72
-
73
- #make it usable in class definition, e.g.
74
- # class Y
75
- # include FastGettext::TranslationMultidomain
76
- # @@x = d_('domain', 'y')
77
- # end
78
- def self.included(klas) #:nodoc:
79
- klas.extend self
80
- end
81
-
82
- # helper block for changing domains
83
- def _in_domain domain
84
- old_domain = FastGettext.text_domain
85
- FastGettext.text_domain = domain
86
- yield if block_given?
87
- ensure
88
- FastGettext.text_domain = old_domain
89
- end
90
-
91
- # gettext functions to translate in the context of given domain
92
- def d_(domain, key, &block)
93
- _in_domain domain do
94
- FastGettext::Translation._(key, &block)
95
- end
96
- end
74
+ return yield if block_given?
97
75
 
98
- def dn_(domain, *keys, &block)
99
- _in_domain domain do
100
- FastGettext::Translation.n_(*keys, &block)
101
- end
76
+ n_(*args).split(NAMESPACE_SEPARATOR).last
102
77
  end
103
78
 
104
- def ds_(domain, key, separator=nil, &block)
105
- _in_domain domain do
106
- FastGettext::Translation.s_(key, separator, &block)
107
- end
108
- end
79
+ # translate pluralized with context
80
+ def np_(context, plural_one, *args, separator: nil)
81
+ nargs = ["#{context}#{separator || CONTEXT_SEPARATOR}#{plural_one}"] + args
82
+ translation = n_(*nargs, &NIL_BLOCK)
83
+ return translation if translation
109
84
 
110
- def dns_(domain, *keys, &block)
111
- _in_domain domain do
112
- FastGettext::Translation.ns_(*keys, &block)
113
- end
114
- end
85
+ return yield if block_given?
115
86
 
116
- # gettext functions to translate in the context of any domain
117
- # (note: if mutiple domains contains key, random translation is returned)
118
- def D_(key)
119
- FastGettext.translation_repositories.each_key do |domain|
120
- result = FastGettext::TranslationMultidomain.d_(domain, key) {nil}
121
- return result unless result.nil?
122
- end
123
- key
87
+ n_(plural_one, *args)
124
88
  end
89
+ end
125
90
 
126
- def Dn_(*keys)
127
- FastGettext.translation_repositories.each_key do |domain|
128
- result = FastGettext::TranslationMultidomain.dn_(domain, *keys) {nil}
129
- return result unless result.nil?
130
- end
131
- keys[-3].split(keys[-2]||NAMESPACE_SEPARATOR).last
132
- end
91
+ module TranslationAliased
92
+ include Translation
93
+ TRANSLATION_METHODS.each { |m| alias_method "#{m.to_s.delete('_')}gettext", m }
94
+ end
133
95
 
134
- def Ds_(key, separator=nil)
135
- FastGettext.translation_repositories.each_key do |domain|
136
- result = FastGettext::TranslationMultidomain.ds_(domain, key, separator) {nil}
137
- return result unless result.nil?
138
- end
139
- key.split(separator||NAMESPACE_SEPARATOR).last
140
- end
96
+ # this module should be included for multi-domain support
97
+ module TranslationMultidomain
98
+ include Translation
141
99
 
142
- def Dns_(*keys)
143
- FastGettext.translation_repositories.each_key do |domain|
144
- result = FastGettext::TranslationMultidomain.dns_(domain, *keys) {nil}
145
- return result unless result.nil?
146
- end
147
- keys[-2].split(NAMESPACE_SEPARATOR).last
100
+ # gettext functions to translate in the context of given domain
101
+ TRANSLATION_METHODS.each do |method|
102
+ eval <<-RUBY, nil, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
103
+ # translate in given domain
104
+ def d#{method}(domain, *args, &block)
105
+ FastGettext.with_domain(domain) { #{method}(*args, &block) }
106
+ end
107
+
108
+ # translate with whatever domain finds a translation
109
+ def D#{method}(*args, &block)
110
+ repos = FastGettext.translation_repositories
111
+ last = repos.size - 1
112
+ repos.each_key.each_with_index do |domain, i|
113
+ if i == last
114
+ return d#{method}(domain, *args, &block)
115
+ else
116
+ result = d#{method}(domain, *args, &NIL_BLOCK)
117
+ return result if result
118
+ end
119
+ end
120
+ end
121
+ RUBY
148
122
  end
149
123
  end
150
124
  end