bisu 1.2.3 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +5 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +44 -0
- data/lib/bisu.rb +45 -13
- data/lib/bisu/dictionary.rb +43 -0
- data/lib/bisu/google_sheet.rb +63 -0
- data/lib/bisu/localizer.rb +74 -0
- data/lib/bisu/version.rb +2 -2
- data/spec/bisu/config_spec.rb +35 -0
- data/spec/bisu/dictionary_spec.rb +69 -0
- data/spec/bisu/google_sheet_spec.rb +61 -0
- data/spec/bisu/localizer_spec.rb +149 -0
- data/spec/bisu/logger_spec.rb +36 -0
- data/{test/support → spec/fixtures}/sample_kb_public_info.html +0 -0
- data/{test/support → spec/fixtures}/sample_kb_public_sheet.html +0 -0
- data/{test/support → spec/fixtures}/sample_translatable.yml +0 -0
- data/spec/spec_helper.rb +116 -0
- metadata +29 -23
- data/lib/bisu/knowledge_base.rb +0 -73
- data/lib/bisu/translator.rb +0 -105
- data/test/test_bisu_config.rb +0 -26
- data/test/test_bisu_knowledge_base.rb +0 -42
- data/test/test_bisu_logger.rb +0 -22
- data/test/test_bisu_translator.rb +0 -121
- data/test/test_helper.rb +0 -3
data/lib/bisu/knowledge_base.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require "net/https"
|
2
|
-
require "xmlsimple"
|
3
|
-
|
4
|
-
module Bisu
|
5
|
-
|
6
|
-
class KnowledgeBase
|
7
|
-
def initialize(kb)
|
8
|
-
raise "Bad KB format (expected Hash)" unless kb.is_a?(Hash)
|
9
|
-
raise "Bad KB format (expected :languages Array)" unless kb.key?(:languages) && kb[:languages].is_a?(Array)
|
10
|
-
raise "Bad KB format (expected :keys Hash)" unless kb.key?(:keys) && kb[:keys].is_a?(Hash)
|
11
|
-
@kb = kb
|
12
|
-
end
|
13
|
-
|
14
|
-
def has_language?(language)
|
15
|
-
@kb[:languages].include?(language)
|
16
|
-
end
|
17
|
-
|
18
|
-
def localize(key, language)
|
19
|
-
if locals = @kb[:keys][key]
|
20
|
-
locals[language]
|
21
|
-
else
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
class GoogleDriveKB < KnowledgeBase
|
29
|
-
def initialize(sheet_id, keys_column_title)
|
30
|
-
raw = raw_data(sheet_id)
|
31
|
-
kb = parse(raw, keys_column_title)
|
32
|
-
super(kb)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def feed_data(uri, headers=nil)
|
38
|
-
uri = URI.parse(uri)
|
39
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
40
|
-
http.use_ssl = true
|
41
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
42
|
-
data = http.get(uri.path, headers)
|
43
|
-
XmlSimple.xml_in(data.body, 'KeyAttr' => 'name')
|
44
|
-
end
|
45
|
-
|
46
|
-
def raw_data(sheet_id)
|
47
|
-
Logger.info("Downloading Knowledge Base...")
|
48
|
-
sheet = feed_data("https://spreadsheets.google.com/feeds/worksheets/#{sheet_id}/public/full")
|
49
|
-
feed_data(sheet["entry"][0]["link"][0]["href"])
|
50
|
-
end
|
51
|
-
|
52
|
-
def parse(raw_data, key)
|
53
|
-
Logger.info("Parsing Knowledge Base...")
|
54
|
-
|
55
|
-
remove = ["id", "updated", "category", "title", "content", "link", key]
|
56
|
-
|
57
|
-
kb_keys = {}
|
58
|
-
raw_data["entry"].each do |entry|
|
59
|
-
hash = entry.select { |d| !remove.include?(d) }
|
60
|
-
hash = hash.each.map { |k, v| v.first == {} ? [k, nil] : [k, v.first] }
|
61
|
-
kb_keys[entry[key].first] = Hash[hash]
|
62
|
-
end
|
63
|
-
|
64
|
-
kb = { languages: kb_keys.values.first.keys, keys: kb_keys }
|
65
|
-
|
66
|
-
Logger.info("Knowledge Base parsed successfully!")
|
67
|
-
Logger.info("Found #{kb[:keys].count} keys in #{kb[:languages].count} languages.")
|
68
|
-
|
69
|
-
kb
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
data/lib/bisu/translator.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module Bisu
|
4
|
-
class Translator
|
5
|
-
def initialize(knowledge_base, type)
|
6
|
-
@kb = knowledge_base
|
7
|
-
@type = type.downcase.to_sym
|
8
|
-
|
9
|
-
unless [:ios, :android, :ror].include?(@type)
|
10
|
-
Logger.error("Unknown type #{@type}")
|
11
|
-
raise
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def translate(language, locale, in_path, out_path, default_language=nil)
|
16
|
-
unless @kb.has_language?(language)
|
17
|
-
Logger.error("Unknown language #{language}")
|
18
|
-
return false
|
19
|
-
end
|
20
|
-
|
21
|
-
return false unless in_file = open_file(in_path, "r", true)
|
22
|
-
return false unless out_file = open_file(out_path, "w", false)
|
23
|
-
|
24
|
-
Logger.info("Translating #{in_path} to #{language} > #{out_path}...")
|
25
|
-
|
26
|
-
in_file.each_line do |line|
|
27
|
-
out_file.write(localize(line, language, locale, default_language))
|
28
|
-
end
|
29
|
-
|
30
|
-
out_file.flush
|
31
|
-
out_file.close
|
32
|
-
in_file.close
|
33
|
-
|
34
|
-
true
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def open_file(file_name, method, must_exist)
|
40
|
-
if !File.file?(File.expand_path(file_name))
|
41
|
-
if must_exist
|
42
|
-
Logger.error("File #{file_name} not found!")
|
43
|
-
return nil
|
44
|
-
else
|
45
|
-
FileUtils.mkdir_p(File.dirname(file_name))
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
File.open(File.expand_path(file_name), method)
|
50
|
-
end
|
51
|
-
|
52
|
-
def localize(text, language, locale, default_language=nil)
|
53
|
-
t = text
|
54
|
-
t = t.gsub("$specialKLanguage$", language)
|
55
|
-
t = t.gsub("$specialKLocale$", locale)
|
56
|
-
t = t.gsub("$specialKComment1$", "This file was automatically generated based on a translation template.")
|
57
|
-
t = t.gsub("$specialKComment2$", "Remember to CHANGE THE TEMPLATE and not this file!")
|
58
|
-
|
59
|
-
if l = localization_params(t)
|
60
|
-
if localized = @kb.localize(l[:loc_key], language) || @kb.localize(l[:loc_key], default_language)
|
61
|
-
l[:loc_vars].each do |param, value|
|
62
|
-
localized = localized.gsub("%{#{param}}", value)
|
63
|
-
end
|
64
|
-
t = t.gsub(l[:match], process(localized))
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
t.scan(/\$k[^\$]+\$/) { |match| Logger.warn("Could not find translation for #{match} in #{language}") }
|
69
|
-
t.scan(/%{[^}]+}/) { |match| Logger.error("Could not find translation param for #{match} in #{language}") }
|
70
|
-
|
71
|
-
t
|
72
|
-
end
|
73
|
-
|
74
|
-
def localization_params(text)
|
75
|
-
return nil unless matches = text.match(/\$(k[^\$\{]+)(?:\{(.+)\})?\$/)
|
76
|
-
|
77
|
-
loc_vars = if matches[2]
|
78
|
-
vars = matches[2].split(",").map(&:strip)
|
79
|
-
vars = vars.map do |var|
|
80
|
-
key, value = var.split(":", 2).map(&:strip)
|
81
|
-
[key.to_sym, value]
|
82
|
-
end
|
83
|
-
Hash[vars]
|
84
|
-
end
|
85
|
-
|
86
|
-
{ match: matches[0],
|
87
|
-
loc_key: matches[1],
|
88
|
-
loc_vars: loc_vars || {} }
|
89
|
-
end
|
90
|
-
|
91
|
-
def process(text)
|
92
|
-
if @type.eql?(:android)
|
93
|
-
text = text.gsub(/[']/, "\\\\\\\\'")
|
94
|
-
text = text.gsub("...", "…")
|
95
|
-
text = text.gsub("& ", "& ")
|
96
|
-
text = text.gsub("@", "\\\\@")
|
97
|
-
|
98
|
-
elsif @type.eql?(:ios)
|
99
|
-
text = text.gsub(/\"/, "\\\\\"")
|
100
|
-
end
|
101
|
-
|
102
|
-
text
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
data/test/test_bisu_config.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'bisu/config'
|
3
|
-
|
4
|
-
class BisuConfigTest < Minitest::Test
|
5
|
-
|
6
|
-
def test_parse
|
7
|
-
config = Bisu::Config.parse("test/support/sample_translatable.yml")
|
8
|
-
|
9
|
-
assert_equal config[:type], "BisuOS"
|
10
|
-
assert_equal config[:sheet_id], "abc1234567890"
|
11
|
-
assert_equal config[:keys_column], "key_name"
|
12
|
-
|
13
|
-
assert_equal config[:in], [
|
14
|
-
"path/to/file/to/1.ext.translatable",
|
15
|
-
"path/to/file/to/2.ext.translatable"
|
16
|
-
]
|
17
|
-
|
18
|
-
assert_equal config[:out_path], "path/to/final-%{locale}/%{out_name}"
|
19
|
-
|
20
|
-
assert_equal config[:out], [
|
21
|
-
{ locale: "en", kb_language: "english", path: "path/to/default/%{out_name}" },
|
22
|
-
{ locale: "pt", kb_language: "portuguese" },
|
23
|
-
{ locale: "pt-PT", kb_language: "portuguese" }
|
24
|
-
]
|
25
|
-
end
|
26
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'bisu/knowledge_base'
|
3
|
-
|
4
|
-
class BisuKnowledgeBaseTest < Minitest::Test
|
5
|
-
|
6
|
-
def test_parsing
|
7
|
-
stub_request(:get, "https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full").to_return(
|
8
|
-
status: 200, body: File.read("test/support/sample_kb_public_info.html"), headers: {})
|
9
|
-
|
10
|
-
stub_request(:get, "https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full").to_return(
|
11
|
-
status: 200, body: File.read("test/support/sample_kb_public_sheet.html"), headers: {})
|
12
|
-
|
13
|
-
Bisu::Logger.silent_mode = true
|
14
|
-
|
15
|
-
Bisu::GoogleDriveKB.new("abc1234567890", "key_column")
|
16
|
-
|
17
|
-
Bisu::Logger.silent_mode = false
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_has_language?
|
21
|
-
kb = Bisu::KnowledgeBase.new({
|
22
|
-
languages: ["portuguese"],
|
23
|
-
keys: {}
|
24
|
-
})
|
25
|
-
|
26
|
-
assert_equal kb.has_language?("kriolo"), false
|
27
|
-
assert_equal kb.has_language?("portuguese"), true
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_localize
|
31
|
-
key = "kYouKnowNothingJohnSnow"
|
32
|
-
pt_trans = "Não sabes nada João das Neves"
|
33
|
-
|
34
|
-
kb = Bisu::KnowledgeBase.new({
|
35
|
-
languages: ["portuguese"],
|
36
|
-
keys: { key => { "portuguese" => pt_trans } }
|
37
|
-
})
|
38
|
-
|
39
|
-
assert_equal kb.localize(key, "kriolo"), nil
|
40
|
-
assert_equal kb.localize(key, "portuguese"), pt_trans
|
41
|
-
end
|
42
|
-
end
|
data/test/test_bisu_logger.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'bisu/logger'
|
3
|
-
|
4
|
-
class BisuLoggerTest < Minitest::Test
|
5
|
-
|
6
|
-
def test_print_summary
|
7
|
-
Bisu::Logger.clean_summary
|
8
|
-
Bisu::Logger.silent_mode = true
|
9
|
-
|
10
|
-
1.times { Bisu::Logger.info "info" }
|
11
|
-
2.times { Bisu::Logger.warn "warn" }
|
12
|
-
3.times { Bisu::Logger.error "error" }
|
13
|
-
|
14
|
-
Bisu::Logger.silent_mode = false
|
15
|
-
|
16
|
-
sum = Bisu::Logger.summary
|
17
|
-
|
18
|
-
assert_equal sum[:info], 1
|
19
|
-
assert_equal sum[:warn], 2
|
20
|
-
assert_equal sum[:error], 3
|
21
|
-
end
|
22
|
-
end
|
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'bisu/translator'
|
3
|
-
|
4
|
-
class BisuTranslatorTest < Minitest::Test
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@lang = "portuguese"
|
8
|
-
@incomplete_lang = "english"
|
9
|
-
@locale = "PT-PT"
|
10
|
-
|
11
|
-
kb = Bisu::KnowledgeBase.new({
|
12
|
-
languages: [@lang, @missing_lang],
|
13
|
-
keys: {
|
14
|
-
"kRegularKey1" => { @lang => "Não sabes nada João das Neves", @incomplete_lang => "You know nothing John Snow" },
|
15
|
-
"kRegularKey2" => { @lang => "Não sabes isto João das Neves" },
|
16
|
-
"kIOSKey" => { @lang => "Não sabes nada \"João das Neves\"" },
|
17
|
-
"kAndroidKey1" => { @lang => "Não sabes nada 'João das Neves'" },
|
18
|
-
"kAndroidKey2" => { @lang => "Não sabes nada João das Neves..." },
|
19
|
-
"kAndroidKey3" => { @lang => "Não sabes nada João das Neves & Pícaros" },
|
20
|
-
"k1ParameterKey" => { @lang => "Não sabes nada %{name}" },
|
21
|
-
"k2ParametersKey" => { @lang => "Sabes %{percentage} por cento %{name}." },
|
22
|
-
"kAtBegin" => { @lang => "\@hole19golf on twitter" },
|
23
|
-
"kAtMiddle" => { @lang => "Find us @hole19golf on twitter" },
|
24
|
-
}
|
25
|
-
})
|
26
|
-
|
27
|
-
@tios = Bisu::Translator.new(kb, :ios)
|
28
|
-
@tand = Bisu::Translator.new(kb, :android)
|
29
|
-
@tror = Bisu::Translator.new(kb, :ror)
|
30
|
-
|
31
|
-
Bisu::Logger.silent_mode = true
|
32
|
-
end
|
33
|
-
|
34
|
-
def teardown
|
35
|
-
Bisu::Logger.silent_mode = false
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_simple_translate
|
39
|
-
orig0 = "0: $kUnknownKey$"
|
40
|
-
orig1 = "1: $specialKComment1$"
|
41
|
-
orig2 = "2: $specialKComment2$"
|
42
|
-
orig3 = "3: $specialKLanguage$"
|
43
|
-
orig4 = "4: $specialKLocale$"
|
44
|
-
orig5 = "5: $kRegularKey1$"
|
45
|
-
orig6_1 = "6.1: $k1ParameterKey$"
|
46
|
-
orig6_2 = "6.2: $k1ParameterKey{name:%1$s}$"
|
47
|
-
orig7_1 = "7.1: $k2ParametersKey$"
|
48
|
-
orig7_2 = "7.2: $k2ParametersKey{percentage:%2$d, name:%1$s}$"
|
49
|
-
orig7_3 = "7.3: $k2ParametersKey{name:%1$s, percentage:%2$d}$"
|
50
|
-
orig8_1 = "8.1: $kRegularKey1$"
|
51
|
-
orig8_2 = "8.2: $kRegularKey2$"
|
52
|
-
orig8_3 = "8.3: $kRegularKey2$"
|
53
|
-
|
54
|
-
loc0 = "0: $kUnknownKey$"
|
55
|
-
loc1 = "1: This file was automatically generated based on a translation template."
|
56
|
-
loc2 = "2: Remember to CHANGE THE TEMPLATE and not this file!"
|
57
|
-
loc3 = "3: #{@lang}"
|
58
|
-
loc4 = "4: #{@locale}"
|
59
|
-
loc5 = "5: Não sabes nada João das Neves"
|
60
|
-
loc6_1 = "6.1: Não sabes nada %{name}"
|
61
|
-
loc6_2 = "6.2: Não sabes nada %1$s"
|
62
|
-
loc7_1 = "7.1: Sabes %{percentage} por cento %{name}."
|
63
|
-
loc7_2 = "7.2: Sabes %2$d por cento %1$s."
|
64
|
-
loc7_3 = "7.3: Sabes %2$d por cento %1$s."
|
65
|
-
loc8_1 = "8.1: You know nothing John Snow"
|
66
|
-
loc8_2 = "8.2: Não sabes isto João das Neves"
|
67
|
-
loc8_3 = "8.3: $kRegularKey2$"
|
68
|
-
|
69
|
-
[@tios, @tand, @tror].each do |translator|
|
70
|
-
assert_equal translator.send(:localize, orig0, @lang, @locale), loc0
|
71
|
-
assert_equal translator.send(:localize, orig1, @lang, @locale), loc1
|
72
|
-
assert_equal translator.send(:localize, orig2, @lang, @locale), loc2
|
73
|
-
assert_equal translator.send(:localize, orig3, @lang, @locale), loc3
|
74
|
-
assert_equal translator.send(:localize, orig4, @lang, @locale), loc4
|
75
|
-
assert_equal translator.send(:localize, orig5, @lang, @locale), loc5
|
76
|
-
assert_equal translator.send(:localize, orig6_1, @lang, @locale), loc6_1
|
77
|
-
assert_equal translator.send(:localize, orig6_2, @lang, @locale), loc6_2
|
78
|
-
assert_equal translator.send(:localize, orig7_1, @lang, @locale), loc7_1
|
79
|
-
assert_equal translator.send(:localize, orig7_2, @lang, @locale), loc7_2
|
80
|
-
assert_equal translator.send(:localize, orig7_3, @lang, @locale), loc7_3
|
81
|
-
|
82
|
-
assert_equal translator.send(:localize, orig8_1, @incomplete_lang, @locale, @lang), loc8_1
|
83
|
-
assert_equal translator.send(:localize, orig8_2, @incomplete_lang, @locale, @lang), loc8_2
|
84
|
-
assert_equal translator.send(:localize, orig8_3, @incomplete_lang, @locale ), loc8_3
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_ios_translate
|
89
|
-
assert_equal @tios.send(:localize, "1: $kIOSKey$", @lang, @locale), "1: Não sabes nada \\\"João das Neves\\\""
|
90
|
-
assert_equal @tios.send(:localize, "2: $kAtBegin$", @lang, @locale), "2: @hole19golf on twitter"
|
91
|
-
assert_equal @tios.send(:localize, "3: $kAtMiddle$", @lang, @locale), "3: Find us @hole19golf on twitter"
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_android_translate
|
95
|
-
assert_equal @tand.send(:localize, "1: $kAndroidKey1$", @lang, @locale), "1: Não sabes nada \\'João das Neves\\'"
|
96
|
-
assert_equal @tand.send(:localize, "2: $kAndroidKey2$", @lang, @locale), "2: Não sabes nada João das Neves…"
|
97
|
-
assert_equal @tand.send(:localize, "3: $kAndroidKey3$", @lang, @locale), "3: Não sabes nada João das Neves & Pícaros"
|
98
|
-
assert_equal @tand.send(:localize, "4: $kAtBegin$", @lang, @locale), "4: \\@hole19golf on twitter"
|
99
|
-
assert_equal @tand.send(:localize, "5: $kAtMiddle$", @lang, @locale), "5: Find us \\@hole19golf on twitter"
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_missing_translations
|
103
|
-
Bisu::Logger.clean_summary
|
104
|
-
|
105
|
-
assert_equal @tios.send(:localize, "1: $kUnknownKey$.", @lang, @locale), "1: $kUnknownKey$."
|
106
|
-
|
107
|
-
sum = Bisu::Logger.summary
|
108
|
-
assert_equal 1, sum[:warn]
|
109
|
-
assert_equal 0, sum[:error]
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_cannot_find_translation_param
|
113
|
-
Bisu::Logger.clean_summary
|
114
|
-
|
115
|
-
assert_equal @tios.send(:localize, "1: $k2ParametersKey$", @lang, @locale), "1: Sabes %{percentage} por cento %{name}."
|
116
|
-
|
117
|
-
sum = Bisu::Logger.summary
|
118
|
-
assert_equal 0, sum[:warn]
|
119
|
-
assert_equal 2, sum[:error]
|
120
|
-
end
|
121
|
-
end
|
data/test/test_helper.rb
DELETED