2011-09-01 73 views
16

我一直在嘗試對i18n進行排序來翻譯Ruby的YAML文件,這樣我就可以以更好和有組織的方式管理新的翻譯,但我一直在想是否有什麼可以緩解任務。如何分類YAML文件?

我發現一個YAML文件編寫器,所以我可以寫一個哈希到一個文件,但我的問題是正確排序哈希。如果我得到散列hh.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) 
+0

是否有任何崇高的插件爲相同? –

回答

9

其實這是一個很好的問題。你想深入排序哈希。所以我不喜歡重新發明輪子,然後尋找一個好的實現,並找到我喜歡的一個。看看它https://gist.github.com/1083930。它工作正常。

+0

它的工作,謝謝lucapette! – AndreDurao

+0

這個解決方案有一個小故障:它也排序值。 – Ando

+0

我喜歡這個解決方案,但是在我的Yaml文件中沒有雙引號(它看起來像這樣:'sub_diagnostics_count:!'#Sous-diagnostics''仍然被解釋爲String但看起來很糟糕)。有沒有解決方案來糾正@lucapette? – MrYoshiji

1

在Ruby 1.8中,哈希函數沒有特定的順序,所以您不能對它們進行排序。

你可以猴子補丁/覆蓋的Hash這樣的to_yaml方法:

#!/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 

當然,具體細節可能取決於你的YAML/Ruby的版本。上面的例子適用於Ruby 1.8.6。

1

這裏的另一種選擇爲別人誰碰到這個來..

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

你不應該使用YAML庫的建議一樣在其他的答案。當你使用重音和特殊字符(你會,因爲你正在做i18n),它會搞亂長字符串值的格式,刪除你的註釋並吐出不可讀的字符轉義。 使用此寶石我創建:

https://github.com/redealumni/i18n_yaml_sorter

它只會在文件中的行排序,所以一切都將保持它的方式是對原有YAML一樣(你的口音,在YAML構建你用來進入字符串,縮進等)。它將與深層嵌套yamls一起工作,結果非常穩固。寶石包括測試,對紅寶石1.8或1.9有好處。

它帶有一個TextMate軟件包(Shift + Command + S)和一個Rails rake任務,因此您可以在編輯器中輕鬆快捷地對文件進行排序。這真的很快。

爲了說明差異:

原文:

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! 

結果通過YAML ::轉儲:

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." 

結果通過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. 
+0

這似乎很有趣,我會嘗試! Obrigado Bernardo。 – AndreDurao

+0

我只是嘗試這個gem排序config.yml文件,它沒有工作。結果被排序但是也不同。 – Ando

+0

糟糕,多年後,我再次滑入這顆寶石。這個gem不工作的原因是因爲它忽略了引用,這意味着依賴關係沒有正確排序。 爲了讓您的YAML文件具有彈性,可以按照鍵排序方式重命名已命名的鍵,以便在引用之前它們會出現。 EG: (1)首先,我將'some_key:&some_name'重命名爲'_some_key:&some_name'並添加了'some_key:\ n <<:* some_name'。 (2)然後,我將所有已命名的鍵和它們的值移到文件的頂部,並在需要的地方向鍵添加數字。 請注意,此手動調整隻需要一次。 – Ando

6

https://gist.github.com/1083930不按預期工作。它不僅對散列鍵進行深度排序,而且對散列值進行深度排序。在我需要深度排序哈希的用例中,哈希總是一棵樹,其中鍵是標籤,值是(子)樹(如果散列)或葉(否則)。我只需要深入分類樹的標籤。

我得到這個

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

與此

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 
6

UPDATE 2014年4月:

使用的Rails 3 .2.13 ,Ruby 1.9 .3p489:

我剛使用了i18n_yaml_sorter gem(https://github.com/redealumni/i18n_yaml_sorter)。

只需添加到您的Gemfile

gem 'i18n_yaml_sorter', group: :development 

然後運行 rake任務到您的語言環境文件排序:

rake i18n:sort 

工作完美,儘管創業板最近一次是在2年前撰寫的。最多花了5分鐘。

1

還有一個原子包,也會這樣做https://github.com/akfernun/yaml-sortkeys

+3

一個潛在的解決方案的鏈接總是受歡迎的,但請[在鏈接周圍添加上下文](http://meta.stackoverflow.com/a/8259/169503),以便您的同行用戶可以瞭解它是什麼以及爲什麼在那。如果目標網站無法訪問或永久離線,請始終引用重要鏈接中最相關的部分。考慮到_barely不僅僅是一個鏈接到外部網站_是一個可能的原因[爲什麼和如何刪除一些答案?](http://stackoverflow.com/help/deleted-answers)。 – Tunaki