bisu 1.2.3 → 1.2.4
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.
- 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