fast_gettext 1.6.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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