i18n_yaml_sorter 0.1.1 → 0.2.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.
@@ -0,0 +1,10 @@
1
+ module I18nYamlSorter
2
+ if defined? Rails::Railtie
3
+ require 'rails'
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ load "tasks/i18n_yaml_sorter.rake"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,128 @@
1
+ module I18nYamlSorter
2
+ class Sorter
3
+ def initialize(io_input)
4
+ @io_input = io_input
5
+ end
6
+
7
+ def sort
8
+ @array = break_blocks_into_array
9
+ @current_array_index = 0
10
+ sorted_yaml_from_blocks_array
11
+ end
12
+
13
+ private
14
+
15
+ def break_blocks_into_array
16
+ array = []
17
+
18
+ loop do
19
+
20
+ maybe_next_line = @read_line_again || @io_input.gets || break
21
+ @read_line_again = nil
22
+ maybe_next_line.chomp!
23
+
24
+ #Is it blank? Discard!
25
+ next if maybe_next_line.match(/^\s*$/)
26
+
27
+ #Does it look like a key: value line?
28
+ key_value_parse = maybe_next_line.match(/^(\s*)(["']?[\w\-]+["']?)(: )(\s*)(\S.*\S)(\s*)$/)
29
+ if key_value_parse
30
+ array << maybe_next_line.concat("\n") #yes, it is the beginning of a key:value block
31
+
32
+ #Special cases when it should add extra lines to the array element (multi line quoted strings)
33
+
34
+ #Is the value surrounded by quotes?
35
+ starts_with_quote = key_value_parse[5].match(/^["']/)[0] rescue nil
36
+ ends_with_quote = key_value_parse[5].match(/[^\\](["'])$/)[1] rescue nil
37
+ if starts_with_quote and !(starts_with_quote == ends_with_quote)
38
+
39
+ loop do #Append next lines until we find the closing quote
40
+ content_line = @io_input.gets || break
41
+ content_line.chomp!
42
+ array.last << content_line.concat("\n")
43
+ break if content_line.match(/[^\\][#{starts_with_quote}]\s*$/)
44
+ end
45
+
46
+ end # if starts_with_quote
47
+
48
+ next
49
+ end # if key_value_parse
50
+
51
+ # Is it a | or > string alue?
52
+ is_special_string = maybe_next_line.match(/^(\s*)(["']?[\w\-]+["']?)(: )(\s*)([|>])(\s*)$/)
53
+ if is_special_string
54
+ array << maybe_next_line.concat("\n") #yes, it is the beginning of a key block
55
+ indentation = is_special_string[1]
56
+ #Append the next lines until we find one that is not indented
57
+ loop do
58
+ content_line = @io_input.gets || break
59
+ processed_line = content_line.chomp
60
+ this_indentation = processed_line.match(/^\s*/)[0] rescue ""
61
+ if indentation.size < this_indentation.size
62
+ array.last << processed_line.concat("\n")
63
+ else
64
+ @read_line_again = content_line
65
+ break
66
+ end
67
+ end
68
+
69
+ next
70
+ end #if is_special_string
71
+
72
+ # Is it the begining of a multi level hash?
73
+ is_start_of_hash = maybe_next_line.match(/^(\s*)(["']?[\w\-]+["']?)(:)(\s*)$/)
74
+ if is_start_of_hash
75
+ array << maybe_next_line.concat("\n")
76
+ next
77
+ end
78
+
79
+ #If we got here and nothing was done, this line
80
+ # should probably be merged with the previous one.
81
+ if array.last
82
+ array.last << maybe_next_line.concat("\n")
83
+ else
84
+ array << maybe_next_line.concat("\n")
85
+ end
86
+ end #loop
87
+
88
+ #debug:
89
+ #puts array.join("$$$$$$$$$$$$$$$$$$$$$$\n")
90
+
91
+ array
92
+ end
93
+
94
+ def sorted_yaml_from_blocks_array(current_block = nil)
95
+
96
+ unless current_block
97
+ current_block = @array[@current_array_index]
98
+ @current_array_index += 1
99
+ end
100
+
101
+ out_array = []
102
+ current_match = current_block.match(/^(\s*)(["']?[\w\-]+["']?)(:)/)
103
+ current_level = current_match[1] rescue ''
104
+ current_key = current_match[2].downcase.tr(%q{"'}, "") rescue ''
105
+ out_array << [current_key, current_block]
106
+
107
+ loop do
108
+ next_block = @array[@current_array_index] || break
109
+ @current_array_index += 1
110
+
111
+ current_match = next_block.match(/^(\s*)(["']?[\w\-]+["']?)(:)/) || next
112
+ current_key = current_match[2].downcase.tr(%q{"'}, "")
113
+ next_level = current_match[1]
114
+
115
+ if current_level.size < next_level.size
116
+ out_array.last.last << sorted_yaml_from_blocks_array(next_block)
117
+ elsif current_level.size == next_level.size
118
+ out_array << [current_key, next_block]
119
+ elsif current_level.size > next_level.size
120
+ @current_array_index -= 1
121
+ break
122
+ end
123
+ end
124
+
125
+ return out_array.sort.map(&:last).join
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,16 @@
1
+ require 'i18n_yaml_sorter'
2
+
3
+ namespace :i18n do
4
+
5
+ desc "Sort locales keys in alphabetic order. Sort all locales if no path parameter given"
6
+
7
+ task :sort, [:path_to_file] => :environment do |t , args|
8
+ locales = args[:path_to_file] || Dir.glob("#{Rails.root}/config/locales/**/*.yml")
9
+
10
+ locales.each do |locale_path|
11
+ sorted_contents = File.open(locale_path) { |f| I18nYamlSorter::Sorter.new(f).sort }
12
+ File.open(locale_path, 'w') { |f| f << sorted_contents}
13
+ end
14
+ end
15
+
16
+ end
@@ -1,8 +1,17 @@
1
1
  require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
2
10
  require 'test/unit'
11
+ require 'yaml'
3
12
 
4
- $LOAD_PATH.unshift(File.dirname(__FILE__))
5
13
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
15
  require 'i18n_yaml_sorter'
7
16
 
8
17
  class Test::Unit::TestCase
@@ -1,4 +1,4 @@
1
-
1
+ # encoding: UTF-8
2
2
 
3
3
  m_13: >
4
4
  Não deve dar problema aqui!
@@ -0,0 +1,239 @@
1
+ # encoding: UTF-8
2
+ # pt-BR translations for Ruby on Rails
3
+ "pt-BR":
4
+ date:
5
+ # formatos de data e hora
6
+ formats:
7
+ default: "%d/%m/%Y"
8
+ short: "%d de %B"
9
+ long: "%d de %B de %Y"
10
+
11
+ day_names:
12
+ - Domingo
13
+ - Segunda
14
+ - Terça
15
+ - Quarta
16
+ - Quinta
17
+ - Sexta
18
+ - Sábado
19
+ abbr_day_names:
20
+ - Dom
21
+ - Seg
22
+ - Ter
23
+ - Qua
24
+ - Qui
25
+ - Sex
26
+ - Sáb
27
+
28
+ month_names:
29
+ - ~
30
+ - Janeiro
31
+ - Fevereiro
32
+ - Março
33
+ - Abril
34
+ - Maio
35
+ - Junho
36
+ - Julho
37
+ - Agosto
38
+ - Setembro
39
+ - Outubro
40
+ - Novembro
41
+ - Dezembro
42
+ abbr_month_names:
43
+ - ~
44
+ - Jan
45
+ - Fev
46
+ - Mar
47
+ - Abr
48
+ - Mai
49
+ - Jun
50
+ - Jul
51
+ - Ago
52
+ - Set
53
+ - Out
54
+ - Nov
55
+ - Dez
56
+ order:
57
+ - :day
58
+ - :month
59
+ - :year
60
+
61
+ time:
62
+ formats:
63
+ default: "%A, %d de %B de %Y, %H:%M h"
64
+ short: "%d/%m, %H:%M h"
65
+ long: "%A, %d de %B de %Y, %H:%M h"
66
+ am: ''
67
+ pm: ''
68
+
69
+ support:
70
+ array:
71
+ # Usado no Array.to_sentence
72
+ words_connector: ", "
73
+ two_words_connector: " e "
74
+ last_word_connector: " e "
75
+
76
+ select:
77
+ prompt: "Por favor selecione"
78
+
79
+ number:
80
+ format:
81
+ separator: ','
82
+ delimiter: '.'
83
+ precision: 3
84
+ significant: false
85
+ strip_insignificant_zeros: false
86
+
87
+ currency:
88
+ format:
89
+ format: '%u %n'
90
+ unit: 'R$'
91
+ separator: ','
92
+ delimiter: '.'
93
+ precision: 2
94
+ significant: false
95
+ strip_insignificant_zeros: false
96
+
97
+ percentage:
98
+ format:
99
+ delimiter: '.'
100
+
101
+ precision:
102
+ format:
103
+ delimiter: '.'
104
+
105
+ human:
106
+ format:
107
+ delimiter: '.'
108
+ precision: 2
109
+ significant: true
110
+ strip_insignificant_zeros: true
111
+ storage_units:
112
+ format: "%n %u"
113
+ units:
114
+ byte:
115
+ one: "Byte"
116
+ other: "Bytes"
117
+ kb: "KB"
118
+ mb: "MB"
119
+ gb: "GB"
120
+ tb: "TB"
121
+ decimal_units:
122
+ # number_to_human()
123
+ # new in rails 3: please add to other locales
124
+ format: "%n %u"
125
+ units:
126
+ unit: ""
127
+ thousand: "mil"
128
+ million:
129
+ one: milhão
130
+ other: milhões
131
+ billion:
132
+ one: bilhão
133
+ other: bilhões
134
+ trillion:
135
+ one: trilhão
136
+ other: trilhões
137
+ quadrillion:
138
+ one: quatrilhão
139
+ other: quatrilhões
140
+
141
+ datetime:
142
+ distance_in_words:
143
+ # distancia do tempo em palavras
144
+ half_a_minute: 'meio minuto'
145
+ less_than_x_seconds:
146
+ one: 'menos de 1 segundo'
147
+ other: 'menos de %{count} segundos'
148
+ x_seconds:
149
+ one: '1 segundo'
150
+ other: '%{count} segundos'
151
+ less_than_x_minutes:
152
+ one: 'menos de um minuto'
153
+ other: 'menos de %{count} minutos'
154
+ x_minutes:
155
+ one: '1 minuto'
156
+ other: '%{count} minutos'
157
+ about_x_hours:
158
+ one: 'aproximadamente 1 hora'
159
+ other: 'aproximadamente %{count} horas'
160
+ x_days:
161
+ one: '1 dia'
162
+ other: '%{count} dias'
163
+ about_x_months:
164
+ one: 'aproximadamente 1 mês'
165
+ other: 'aproximadamente %{count} meses'
166
+ x_months:
167
+ one: '1 mês'
168
+ other: '%{count} meses'
169
+ about_x_years:
170
+ one: 'aproximadamente 1 ano'
171
+ other: 'aproximadamente %{count} anos'
172
+ over_x_years:
173
+ one: 'mais de 1 ano'
174
+ other: 'mais de %{count} anos'
175
+ almost_x_years:
176
+ one: 'quase 1 ano'
177
+ other: 'quase %{count} anos'
178
+ prompts:
179
+ year: "Ano"
180
+ month: "Mês"
181
+ day: "Dia"
182
+ hour: "Hora"
183
+ minute: "Minuto"
184
+ second: "Segundo"
185
+
186
+ helpers:
187
+ select:
188
+ prompt: "Por favor selecione"
189
+
190
+ submit:
191
+ create: 'Criar %{model}'
192
+ update: 'Atualizar %{model}'
193
+ submit: 'Salvar %{model}'
194
+
195
+ errors:
196
+ format: "%{attribute} %{message}"
197
+
198
+ template:
199
+ header:
200
+ one: "Não foi possível gravar %{model}: 1 erro"
201
+ other: "Não foi possível gravar %{model}: %{count} erros."
202
+ body: "Por favor, verifique o(s) seguinte(s) campo(s):"
203
+
204
+ messages: &errors_messages
205
+ inclusion: "não está incluído na lista"
206
+ exclusion: "não está disponível"
207
+ invalid: "não é válido"
208
+ confirmation: "não está de acordo com a confirmação"
209
+ accepted: "deve ser aceito"
210
+ empty: "não pode ficar vazio"
211
+ blank: "não pode ficar em branco"
212
+ too_long: "é muito longo (máximo: %{count} caracteres)"
213
+ too_short: "é muito curto (mínimo: %{count} caracteres)"
214
+ wrong_length: "não possui o tamanho esperado (%{count} caracteres)"
215
+ not_a_number: "não é um número"
216
+ not_an_integer: "não é um número inteiro"
217
+ greater_than: "deve ser maior que %{count}"
218
+ greater_than_or_equal_to: "deve ser maior ou igual a %{count}"
219
+ equal_to: "deve ser igual a %{count}"
220
+ less_than: "deve ser menor que %{count}"
221
+ less_than_or_equal_to: "deve ser menor ou igual a %{count}"
222
+ odd: "deve ser ímpar"
223
+ even: "deve ser par"
224
+
225
+ activerecord:
226
+ errors:
227
+ template:
228
+ header:
229
+ one: "Não foi possível gravar %{model}: 1 erro"
230
+ other: "Não foi possível gravar %{model}: %{count} erros."
231
+ body: "Por favor, verifique o(s) seguinte(s) campo(s):"
232
+
233
+ messages:
234
+ taken: "já está em uso"
235
+ record_invalid: "A validação falhou: %{errors}"
236
+ <<: *errors_messages
237
+
238
+ full_messages:
239
+ format: "%{attribute} %{message}"
@@ -0,0 +1,28 @@
1
+ pt-BR:
2
+ # Note how this is a nice way of inputing
3
+ # paragraphs of text in YAML.
4
+ apples: >
5
+ Maçãs são boas,
6
+ só não coma
7
+ seus iPods!
8
+ grapes: Não comemos elas.
9
+ bananas: |
10
+ Bananas são "legais":
11
+ - Elas são <b> doces </b>.
12
+ isto: não é chave
13
+
14
+ Por isto todos gostam de bananas!
15
+ en-US:
16
+ # Note that our comments are important:
17
+ # Don't let your yaml sorter delete them!
18
+ grapes: We dont' eat them.
19
+ bananas: |
20
+ Bananas are "nice":
21
+ - They are <b> sweet </b>.
22
+ this: not a key
23
+
24
+ That is why everyone like bananas!
25
+ apples: >
26
+ Apples are fine,
27
+ just don't eat your
28
+ iPods!