ruby sorting internationalization yaml

ruby - ¿Cómo puedo ordenar los archivos YAML?



sorting internationalization (8)

ACTUALIZACIÓN Abril 2014:

Usando Rails 3 .2.13, Ruby 1.9 .3p489:

Acabo de usar la gema i18n_yaml_sorter ( https://github.com/redealumni/i18n_yaml_sorter ).

Simplemente agregue a su Gemfile :

gem ''i18n_yaml_sorter'', group: :development

Luego ejecuta la tarea de rake para ordenar los archivos de tus locales:

rake i18n:sort

Funcionó a la perfección , a pesar de que la gema se escribió hace dos años. Le tomó 5 minutos máximo.

He estado tratando de ordenar un archivo YAML i18n translations con Ruby para poder administrar las nuevas traducciones de una manera mejor y más organizada, pero me he estado preguntando si hay algo para facilitar la tarea.

Encontré un escritor de archivos YAML para poder escribir un hash en un archivo, pero mi problema es ordenar el hash correctamente. Si obtuve el hash h , h.sort devuelve una matriz y todavía no he encontrado una forma sencilla de hacerlo.

Tengo archivos YAML como este:

pt-br: global: misc: total: "Total" all: "Todos" close: "Fechar" cancel: "Cancelar" crud: access: "Acessar" back: "Voltar" edit: "Editar" confirm: "Confirmar" send: "Enviar" ...

(Los archivos son mucho más grandes que esto)

Pero quiero ordenarlos de esta manera:

pt-br: global: crud: access: "Acessar" back: "Voltar" confirm: "Confirmar" edit: "Editar" send: "Enviar" misc: all: "Todos" cancel: "Cancelar" close: "Fechar" total: "Total"

Pensé que algún método recursivo simple podría ayudarme así:

def translation_sort(h) if h.class == Hash h = h.sort h.each{|item| translation_sort(item)} end h end require "yaml" h=YAML.load_file(File.open("~/pt-br.sample.yml")) translation_sort(h)


Aquí hay otra alternativa para cualquiera que se encuentre con esto.

require ''yaml'' yaml = YAML.load(IO.read(File.join(File.dirname(__FILE__), ''example.yml''))) @yml_string = "---/n" def recursive_hash_to_yml_string(hash, depth=0) spacer = "" depth.times { spacer += " "} hash.keys.sort.each do |sorted_key| @yml_string += spacer + sorted_key + ": " if hash[sorted_key].is_a?(Hash) @yml_string += "/n" recursive_hash_to_yml_string(hash[sorted_key], depth+1) else @yml_string += "#{hash[sorted_key].to_s}/n" end end end recursive_hash_to_yml_string(yaml) open(File.join(File.dirname(__FILE__), ''example.yml''), ''w'') { |f| f.write @yml_string }


En Ruby 1.8, los hashes no tienen un orden particular, por lo que no puedes simplemente ordenarlos.

Podrías aplicar un parche / sobrescribir el método to_yaml de Hash esta manera:

#!/usr/local/bin/ruby -w require ''yaml'' class Hash def to_yaml(opts = {}) YAML::quick_emit(self, opts) do |out| out.map(taguri, to_yaml_style) do |map| keys.sort.each do |k| v = self[k] map.add(k, v) end end end end end dict = YAML.load($<.read) puts dict.to_yaml

Por supuesto, los detalles exactos pueden depender de su versión de YAML / Ruby. El ejemplo anterior es para Ruby 1.8.6.


En realidad esta es una buena pregunta. Quieres profundizar los hashes. Así que no me gusta reinventar la rueda y luego busqué una buena implementación y encontré una que me gusta. Míralo https://gist.github.com/1083930 . Funciona bien.



No debe usar la biblioteca YAML como se sugiere en las otras respuestas. Destruirá el formato de los valores de cadena larga, eliminará tus comentarios y escupirá escapes de caracteres ilegibles cuando uses acentos y caracteres especiales (lo que harás, ya que estás haciendo i18n). Utilice esta joya que he creado:

https://github.com/redealumni/i18n_yaml_sorter

Solo ordenará las líneas en el archivo, por lo que todo seguirá igual que en el yaml original (sus acentos, la construcción YAML que utilizó para ingresar las cadenas, la sangría, etc.). Funcionará con yamls profundamente anidados y los resultados son bastante sólidos. La gema incluye pruebas y es buena para rubí 1.8 o 1.9.

Viene con un TextMate Bundle (Shift + Command + S) y una tarea de rastreo de Rails para que pueda ordenar los archivos de forma fácil e instantánea en su editor. Es muy rapido

Para ilustrar la diferencia:

Original:

pt-BR: # Note how this is a nice way of inputing # paragraphs of text in YAML. apples: > Maçãs são boas, só não coma seus iPods! grapes: Não comemos elas. bananas: | Bananas são "legais": - Elas são <b> doces </b>. isto: não é chave Por isto todos gostam de bananas!

Resultados por YAML :: dump:

pt-BR: apples: "Ma/xC3/xA7/xC3/xA3s s/xC3/xA3o boas, s/xC3/xB3 n/xC3/xA3o coma seus iPods!/n" bananas: "Bananas s/xC3/xA3o /"legais/":/n - Elas s/xC3/xA3o <b> doces </b>./n isto: n/xC3/xA3o /xC3/xA9 chave/n/n/ Por isto todos gostam de bananas!/n" grapes: "N/xC3/xA3o comemos elas."

Resultados por i18n_yaml_sorter:

pt-BR: # Note how this is a nice way of inputing # paragraphs of text in YAML. apples: > Maçãs são boas, só não coma seus iPods! bananas: | Bananas são "legais": - Elas são <b> doces </b>. isto: não é chave Por isto todos gostam de bananas! grapes: Não comemos elas.



https://gist.github.com/1083930 no funciona como esperaba. Ordena en profundidad NO SOLAMENTE las claves de hash, PERO TAMBIÉN HAY valores de hash En mis casos de uso donde se necesita una ordenación profunda, el hash es siempre un árbol donde las claves son etiquetas y los valores son (sub) árboles (si hay hashes) u hojas (de lo contrario). Necesito profundizar solo las etiquetas de los árboles.

tengo esto

before: {"a":[2,10,{"5":null,"1":null,"3":null}],"x":{"5":null,"1":null,"3":null},"a2":{"5":[2,10,5],"1":null,"3":null}} after: {"a":[2,10,{"5":null,"1":null,"3":null}],"a2":{"1":null,"3":null,"5":[2,10,5]},"x":{"1":null,"3":null,"5":null}}

con este

require ''active_support'' def deeply_sort_hash(object) return object unless object.is_a?(Hash) hash = RUBY_VERSION >= ''1.9'' ? Hash.new : ActiveSupport::OrderedHash.new object.each { |k, v| hash[k] = deeply_sort_hash(v) } sorted = hash.sort { |a, b| a[0].to_s <=> b[0].to_s } hash.class[sorted] end