YAML ファイルを並べ替えるにはどうすればよいですか?

概要

新しい翻訳をより適切に整理された方法で管理できるように、Ruby を使用して i18n 翻訳 YAML ファイルを並べ替えようとしていますが、その作業を軽減する方法はないかと考えていました。

YAML ファイル ライターを見つけたので、ハッシュをファイルに書き込むことができますが、問題はハッシュを正しく並べ替えることです。ハッシュ h を取得した場合、h.sort は配列を返しますが、それを行う簡単な方法がまだわかりません。

次のような YAML ファイルがあります。

pt-br:    
  global:
    misc:
      total: "Total"
      all: "Todos"
      close: "Fechar"
      cancel: "Cancelar"

    crud:
      access: "Acessar"
      back: "Voltar"
      edit: "Editar"
      confirm: "Confirmar"
      send: "Enviar"

...

(ファイルはこれよりかなり大きくなります)

しかし、私はこれらを次のように並べ替えたいと思います。

pt-br:    
  global:
    crud:
      access: "Acessar"
      back: "Voltar"
      confirm: "Confirmar"
      edit: "Editar"
      send: "Enviar"

    misc:
      all: "Todos"
      cancel: "Cancelar"
      close: "Fechar"          
      total: "Total"

いくつかの単純な再帰的メソッドが次のように役立つと思いました。

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)

解決策

ハッシュのディープソートが必要な私のユースケースでは、ハッシュは常にキーがラベルであり、値が(サブ)ツリー(ハッシュの場合)またはリーフ(ハッシュの場合)であるツリーです。ツリーのラベル (値ではなく) のみをディープソートする必要があります。

私はこれを得た

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}}

これとともに

    def deeply_sort_hash(object)
      return object unless object.is_a?(Hash)
      hash = Hash.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