bisu 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +76 -0
- data/Rakefile +8 -0
- data/bin/bisu +4 -0
- data/bisu.gem +0 -0
- data/bisu.gemspec +21 -0
- data/lib/bisu/config.rb +38 -0
- data/lib/bisu/knowledge_base.rb +72 -0
- data/lib/bisu/logger.rb +61 -0
- data/lib/bisu/translator.rb +93 -0
- data/lib/bisu.rb +21 -0
- data/test/support/sample_kb_public_info.html +1 -0
- data/test/support/sample_kb_public_sheet.html +1 -0
- data/test/support/sample_translatable.yml +14 -0
- data/test/test_bisu_config.rb +23 -0
- data/test/test_bisu_knowledge_base.rb +42 -0
- data/test/test_bisu_logger.rb +22 -0
- data/test/test_bisu_translator.rb +53 -0
- data/test/test_helper.rb +3 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7f4cb23115b4c94bf3388f524bcdff21ebef2f2a
|
4
|
+
data.tar.gz: d8357042c4d597977ceb6a6831138ed91422f11f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c6e844bba80f1e2e38ecbd71b4f2d605e04ac863c751901c01954d7f58cac6fecfc6d87db4f6ad211eb0a221e2dea13372fba4d969227af2002776c02d39a27e
|
7
|
+
data.tar.gz: c1079b0db9e927d803eb612376d7907682d0b19cc91242c2ff2746f7ebe298db4e55dd2bfa64dda8a405f3b016caf3600764950349c45a4bf7d4bd30993e6ca6
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
H19-Bisu
|
2
|
+
========
|
3
|
+
|
4
|
+
Bisu manages your app iOS and Android localization files for you. No more copy+paste induced errors!
|
5
|
+
|
6
|
+
---
|
7
|
+
|
8
|
+
Instalation
|
9
|
+
-----
|
10
|
+
|
11
|
+
1. Download gem file: [bisu.gem](https://github.com/hole19/h19-bisu/blob/master/bisu.gem?raw=true)
|
12
|
+
1. Run in terminal: `gem install path/to/bisu.gem`
|
13
|
+
|
14
|
+
Usage
|
15
|
+
-----
|
16
|
+
|
17
|
+
1. Open terminal in app project base
|
18
|
+
1. Run: `bisu`
|
19
|
+
1. That's it!*
|
20
|
+
|
21
|
+
*given that someone already configured Bisu
|
22
|
+
|
23
|
+
Configuration
|
24
|
+
-----
|
25
|
+
|
26
|
+
1. Create in your **iOS/Android** app project base folder a translatable.yml:
|
27
|
+
|
28
|
+
```
|
29
|
+
type: <iOS/Android>
|
30
|
+
|
31
|
+
sheet_id: <GOOGLE-DRIVE-SHEET-ID>
|
32
|
+
keys_column: <GOOGLE-DRIVE-KEY-COLUMN-TITLE>
|
33
|
+
|
34
|
+
in:
|
35
|
+
- path/to/1st/file.translatable
|
36
|
+
- path/to/2nd/file.translatable
|
37
|
+
|
38
|
+
out:
|
39
|
+
- language: english
|
40
|
+
folder: path/to/en.lproj/
|
41
|
+
- language: korean
|
42
|
+
folder: path/to/ko.lproj/
|
43
|
+
```
|
44
|
+
|
45
|
+
1. Replace your **iOS** localization files with *.translatable* versions:
|
46
|
+
|
47
|
+
```
|
48
|
+
// $specialKComment1$
|
49
|
+
// $specialKComment2$
|
50
|
+
|
51
|
+
// $specialKLanguage$
|
52
|
+
|
53
|
+
/***********
|
54
|
+
* General
|
55
|
+
************/
|
56
|
+
|
57
|
+
"klGeneral_Delete" = "$kDelete$";
|
58
|
+
"klGeneral_Cancel" = "$kCancel$";
|
59
|
+
"klGeneral_Close" = "$kClose$";
|
60
|
+
```
|
61
|
+
|
62
|
+
1. Replace your **Android** localization files with *.translatable* versions:
|
63
|
+
|
64
|
+
```
|
65
|
+
<?xml version="1.0" encoding="utf-8"?>
|
66
|
+
|
67
|
+
<!-- $specialKComment1$ -->
|
68
|
+
<!-- $specialKComment2$ -->
|
69
|
+
<!-- $specialKLanguage$ -->
|
70
|
+
|
71
|
+
<resources>
|
72
|
+
<string name="delete">$kDelete$</string>
|
73
|
+
<string name="cancel">$kCancel$</string>
|
74
|
+
<string name="close">$kClose$</string>
|
75
|
+
</resources>
|
76
|
+
```
|
data/Rakefile
ADDED
data/bin/bisu
ADDED
data/bisu.gem
ADDED
Binary file
|
data/bisu.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'bisu'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2015-01-28'
|
5
|
+
s.summary = 'Bisu - localization automation service'
|
6
|
+
s.description = 'Bisu is a localization automation service. It was built specially for Hole19'
|
7
|
+
s.authors = ['joaoffcosta']
|
8
|
+
s.email = 'joao.costa@hole19golf.com'
|
9
|
+
s.license = 'MIT'
|
10
|
+
s.homepage = 'https://github.com/hole19/h19-bisu'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.require_paths = ['lib']
|
14
|
+
|
15
|
+
s.executables << 'bisu'
|
16
|
+
|
17
|
+
s.add_runtime_dependency 'safe_yaml', '~> 1.0'
|
18
|
+
s.add_runtime_dependency 'colorize', '~> 0.7'
|
19
|
+
|
20
|
+
s.add_development_dependency 'webmock', '~> 1.20'
|
21
|
+
end
|
data/lib/bisu/config.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Bisu
|
4
|
+
module Config
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def parse(file_name)
|
8
|
+
unless file_name
|
9
|
+
Logger.error("Config file not provided")
|
10
|
+
return nil
|
11
|
+
end
|
12
|
+
|
13
|
+
unless File.exists?(file_name)
|
14
|
+
Logger.error("Could not find config file #{file_name}")
|
15
|
+
return nil
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
deep_sym(YAML::load_file(file_name))
|
20
|
+
rescue Exception => e
|
21
|
+
Logger.error("Could not parse config file #{file_name}: #{e}")
|
22
|
+
return nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def deep_sym(obj)
|
29
|
+
if obj.is_a?(Array)
|
30
|
+
obj.map { |v| deep_sym(v) }
|
31
|
+
elsif obj.is_a?(Hash)
|
32
|
+
obj.inject({}) { |memo, (k,v)| memo[k.to_sym] = deep_sym(v); memo }
|
33
|
+
else
|
34
|
+
obj
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,72 @@
|
|
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
|
+
data = http.get(uri.path, headers)
|
42
|
+
XmlSimple.xml_in(data.body, 'KeyAttr' => 'name')
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_data(sheet_id)
|
46
|
+
Logger.info("Downloading Knowledge Base...")
|
47
|
+
sheet = feed_data("https://spreadsheets.google.com/feeds/worksheets/#{sheet_id}/public/full")
|
48
|
+
feed_data(sheet["entry"][0]["link"][0]["href"])
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse(raw_data, key)
|
52
|
+
Logger.info("Parsing Knowledge Base...")
|
53
|
+
|
54
|
+
remove = ["id", "updated", "category", "title", "content", "link", key]
|
55
|
+
|
56
|
+
kb_keys = {}
|
57
|
+
raw_data["entry"].each do |entry|
|
58
|
+
hash = entry.select { |d| !remove.include?(d) }
|
59
|
+
hash = hash.each.map { |k, v| v.first == {} ? [k, nil] : [k, v.first] }
|
60
|
+
kb_keys[entry[key].first] = Hash[hash]
|
61
|
+
end
|
62
|
+
|
63
|
+
kb = { languages: kb_keys.values.first.keys, keys: kb_keys }
|
64
|
+
|
65
|
+
Logger.info("Knowledge Base parsed successfully!")
|
66
|
+
Logger.info("Found #{kb[:keys].count} keys in #{kb[:languages].count} languages.")
|
67
|
+
|
68
|
+
kb
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/lib/bisu/logger.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "singleton"
|
2
|
+
require "colorize"
|
3
|
+
|
4
|
+
module Bisu
|
5
|
+
module Logger
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def info(msg)
|
9
|
+
log :info, msg
|
10
|
+
end
|
11
|
+
|
12
|
+
def warn(msg)
|
13
|
+
log :warn, msg
|
14
|
+
end
|
15
|
+
|
16
|
+
def error(msg)
|
17
|
+
log :error, msg
|
18
|
+
end
|
19
|
+
|
20
|
+
def clean_summary
|
21
|
+
@levels.each { |k, _| @levels[k] = 0 }
|
22
|
+
end
|
23
|
+
|
24
|
+
def summary
|
25
|
+
@levels
|
26
|
+
end
|
27
|
+
|
28
|
+
def print_summary
|
29
|
+
if @levels[:warn] > 0 || @levels[:error] > 0
|
30
|
+
info ""
|
31
|
+
info "Finished with:"
|
32
|
+
info " #{@levels[:warn]} warnings" if @levels[:warn] > 0
|
33
|
+
info " #{@levels[:error]} errors" if @levels[:error] > 0
|
34
|
+
info ""
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def silent_mode=(value)
|
39
|
+
@silent_mode = value
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
@levels = { info: 0, warn: 0, error: 0 }
|
45
|
+
@silent_mode = false
|
46
|
+
|
47
|
+
def log(level, msg)
|
48
|
+
unless @levels.keys.include?(level)
|
49
|
+
return log(:error, "Unknown log level: #{level}")
|
50
|
+
end
|
51
|
+
|
52
|
+
@levels[level] += 1
|
53
|
+
|
54
|
+
msg = "[#{level.upcase}] #{msg}"
|
55
|
+
msg = msg.yellow if level.eql?(:warn)
|
56
|
+
msg = msg.red if level.eql?(:error)
|
57
|
+
|
58
|
+
puts msg unless @silent_mode
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Bisu
|
2
|
+
class Translator
|
3
|
+
def initialize(knowledge_base, type)
|
4
|
+
@kb = knowledge_base
|
5
|
+
@type = type.downcase.to_sym
|
6
|
+
|
7
|
+
unless [:ios, :android].include?(@type)
|
8
|
+
Logger.error("Unknown type #{@type}")
|
9
|
+
raise
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def translate(language, in_path, out_folder)
|
14
|
+
unless @kb.has_language?(language)
|
15
|
+
Logger.error("Unknown language #{language}")
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
|
19
|
+
in_name = File.basename(in_path)
|
20
|
+
out_name = in_name.gsub(/\.translatable$/, "")
|
21
|
+
out_path = "#{out_folder}#{out_name}"
|
22
|
+
|
23
|
+
unless in_name.match /\.translatable$/
|
24
|
+
Logger.error("Expected .translatable file. Got '#{in_name}'")
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
return false unless in_file = open_file(in_path, "r", true)
|
29
|
+
return false unless out_file = open_file(out_path, "w", false, true)
|
30
|
+
|
31
|
+
Logger.info("Translating #{in_path} to #{language} > #{out_path}...")
|
32
|
+
|
33
|
+
in_file.each_line do |line|
|
34
|
+
out_file.write(localize(line, language))
|
35
|
+
end
|
36
|
+
|
37
|
+
out_file.flush
|
38
|
+
out_file.close
|
39
|
+
in_file.close
|
40
|
+
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def open_file(file_name, method, should_exist, can_overwrite=false)
|
47
|
+
if should_exist == File.file?(File.expand_path(file_name))
|
48
|
+
File.open(File.expand_path(file_name), method)
|
49
|
+
|
50
|
+
elsif should_exist
|
51
|
+
Logger.error("File #{file_name} not found!")
|
52
|
+
nil
|
53
|
+
|
54
|
+
elsif can_overwrite
|
55
|
+
File.open(File.expand_path(file_name), method)
|
56
|
+
|
57
|
+
elsif !should_exist
|
58
|
+
Logger.error("File #{file_name} already exists!")
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def localize(text, language)
|
64
|
+
t = text
|
65
|
+
t = t.gsub("$specialKLanguage$", language.upcase)
|
66
|
+
t = t.gsub("$specialKComment1$", "This file was automatically generated based on a translation template.")
|
67
|
+
t = t.gsub("$specialKComment2$", "Remember to CHANGE THE TEMPLATE and not this file!")
|
68
|
+
|
69
|
+
t = t.gsub(/\$(k[^\$]+)\$/) do |match|
|
70
|
+
if localized = @kb.localize("#{$1}", language)
|
71
|
+
process(localized)
|
72
|
+
else
|
73
|
+
match
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
t.scan(/\$k[^\$]+\$/) { |match| Logger.warn("Could not find translation for #{match} in #{language}") }
|
78
|
+
|
79
|
+
t
|
80
|
+
end
|
81
|
+
|
82
|
+
def process(text)
|
83
|
+
if @type.eql?(:android)
|
84
|
+
text = text.gsub(/[']/, "\\\\'")
|
85
|
+
text = text.gsub("...", "…")
|
86
|
+
text = text.gsub("& ", "& ")
|
87
|
+
|
88
|
+
elsif @type.eql?(:ios)
|
89
|
+
text = text.gsub(/\"/, "\\\\\"")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/bisu.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bisu/logger'
|
2
|
+
require 'bisu/config'
|
3
|
+
require 'bisu/knowledge_base'
|
4
|
+
require 'bisu/translator'
|
5
|
+
|
6
|
+
module Bisu
|
7
|
+
def self.run
|
8
|
+
if config = Bisu::Config.parse("translatable.yml")
|
9
|
+
kbase = Bisu::GoogleDriveKB.new(config[:sheet_id], config[:keys_column])
|
10
|
+
trans = Bisu::Translator.new(kbase, config[:type])
|
11
|
+
|
12
|
+
config[:in].each do |in_path|
|
13
|
+
config[:out].each do |out|
|
14
|
+
trans.translate(out[:language], in_path, out[:folder])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Bisu::Logger.print_summary
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gs='http://schemas.google.com/spreadsheets/2006'><id>https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full</id><updated>2015-02-09T18:59:53.874Z</updated><category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#worksheet'/><title type='text'>H19: Translation Knowledge Base</title><link rel='alternate' type='application/atom+xml' href='https://docs.google.com/spreadsheets/d/abc1234567890/pubhtml'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full'/><link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full'/><link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full'/><author><name>anthony.douglas</name><email>anthony.douglas@hole19golf.com</email></author><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><entry><id>https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full/od6</id><updated>2015-02-09T18:59:53.874Z</updated><category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#worksheet'/><title type='text'>Translations</title><content type='text'>Translations</content><link rel='http://schemas.google.com/spreadsheets/2006#listfeed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full'/><link rel='http://schemas.google.com/spreadsheets/2006#cellsfeed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/cells/abc1234567890/od6/public/full'/><link rel='http://schemas.google.com/visualization/2008#visualizationApi' type='application/atom+xml' href='https://docs.google.com/spreadsheets/d/abc1234567890/gviz/tq?gid=0&pub=1'/><link rel='http://schemas.google.com/spreadsheets/2006#exportcsv' type='text/csv' href='https://docs.google.com/spreadsheets/d/abc1234567890/export?gid=0&format=csv'/><link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/worksheets/abc1234567890/public/full/od6'/><gs:colCount>25</gs:colCount><gs:rowCount>665</gs:rowCount></entry></feed>
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gsx='http://schemas.google.com/spreadsheets/2006/extended'><id>https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full</id><updated>2015-02-09T18:59:53.874Z</updated><category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#list'/><title type='text'>Translations</title><link rel='alternate' type='application/atom+xml' href='https://docs.google.com/spreadsheets/d/abc1234567890/pubhtml'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full'/><link rel='http://schemas.google.com/g/2005#post' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full'/><link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full'/><author><name>anthony.douglas</name><email>anthony.douglas@hole19golf.com</email></author><openSearch:totalResults>664</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><entry><id>https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full/cokwr</id><updated>2015-02-09T18:59:53.874Z</updated><category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#list'/><title type='text'>kConnectFacebook</title><content type='text'>english: Connect with Facebook, german: Mit Facebook verbinden, portuguese: Registar com Facebook, spanish: Conéctate con Facebook, french: Connecter Facebook, dutch: Facebook Verbinden, korean: 페이스북으로 접속, japanese: フェイスブックへ接続, key_column_2: kConnectFacebook</content><link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full/cokwr'/><gsx:key_column>kConnectFacebook</gsx:key_column><gsx:english>Connect with Facebook</gsx:english><gsx:german>Mit Facebook verbinden</gsx:german><gsx:portuguese>Registar com Facebook</gsx:portuguese><gsx:spanish>Conéctate con Facebook</gsx:spanish><gsx:french>Connecter Facebook</gsx:french><gsx:dutch>Facebook Verbinden</gsx:dutch><gsx:korean>페이스북으로 접속</gsx:korean><gsx:japanese>フェイスブックへ接続</gsx:japanese><gsx:key_column_2>kConnectFacebook</gsx:key_column_2></entry><entry><id>https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full/cpzh4</id><updated>2015-02-09T18:59:53.874Z</updated><category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#list'/><title type='text'>kConnectEmail</title><content type='text'>english: Connect with Email, german: Mit E-Mail verbinden, portuguese: Registar com Email, spanish: Conéctate con Email, french: Connecter Email, dutch: Email Verbinden, korean: 이메일로 접속, japanese: 電子メールアカウントに接続, key_column_2: kConnectEmail</content><link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/list/abc1234567890/od6/public/full/cpzh4'/><gsx:key_column>kConnectEmail</gsx:key_column><gsx:english>Connect with Email</gsx:english><gsx:german>Mit E-Mail verbinden</gsx:german><gsx:portuguese>Registar com Email</gsx:portuguese><gsx:spanish>Conéctate con Email</gsx:spanish><gsx:french>Connecter Email</gsx:french><gsx:dutch>Email Verbinden</gsx:dutch><gsx:korean>이메일로 접속</gsx:korean><gsx:japanese>電子メールアカウントに接続</gsx:japanese><gsx:key_column_2>kConnectEmail</gsx:key_column_2></entry></feed>
|
@@ -0,0 +1,23 @@
|
|
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], "iOS"
|
10
|
+
assert_equal config[:sheet_id], "abc1234567890"
|
11
|
+
assert_equal config[:keys_column], "key_name"
|
12
|
+
|
13
|
+
assert_equal config[:in], [
|
14
|
+
"folder/file_1.translatable",
|
15
|
+
"folder/file_2.translatable"
|
16
|
+
]
|
17
|
+
|
18
|
+
assert_equal config[:out], [
|
19
|
+
{ language: "english", folder: "hole19/en.lproj/" },
|
20
|
+
{ language: "portuguese", folder: "hole19/pt.lproj/" }
|
21
|
+
]
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
@@ -0,0 +1,22 @@
|
|
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
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'bisu/translator'
|
3
|
+
|
4
|
+
class BisuTranslatorTest < Minitest::Test
|
5
|
+
|
6
|
+
def setup
|
7
|
+
kb = Bisu::KnowledgeBase.new({
|
8
|
+
languages: ["PT"],
|
9
|
+
keys: {
|
10
|
+
"kRegularKey" => { "PT" => "Não sabes nada João das Neves" },
|
11
|
+
"kIOSKey" => { "PT" => "Não sabes nada \"João das Neves\"" },
|
12
|
+
"kAndroidKey1" => { "PT" => "Não sabes nada 'João das Neves'" },
|
13
|
+
"kAndroidKey2" => { "PT" => "Não sabes nada João das Neves..." },
|
14
|
+
"kAndroidKey3" => { "PT" => "Não sabes nada João das Neves & Pícaros" },
|
15
|
+
}
|
16
|
+
})
|
17
|
+
|
18
|
+
@tios = Bisu::Translator.new(kb, :ios)
|
19
|
+
@tand = Bisu::Translator.new(kb, :android)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_simple_translate
|
23
|
+
orig1 = "1: $specialKComment1$"
|
24
|
+
orig2 = "2: $specialKComment2$"
|
25
|
+
orig3 = "3: $specialKLanguage$"
|
26
|
+
orig4 = "4: $kRegularKey$"
|
27
|
+
|
28
|
+
loc1 = "1: This file was automatically generated based on a translation template."
|
29
|
+
loc2 = "2: Remember to CHANGE THE TEMPLATE and not this file!"
|
30
|
+
loc3 = "3: PT"
|
31
|
+
loc4 = "4: Não sabes nada João das Neves"
|
32
|
+
|
33
|
+
assert_equal @tios.send(:localize, orig1, "PT"), loc1
|
34
|
+
assert_equal @tios.send(:localize, orig2, "PT"), loc2
|
35
|
+
assert_equal @tios.send(:localize, orig3, "PT"), loc3
|
36
|
+
assert_equal @tios.send(:localize, orig4, "PT"), loc4
|
37
|
+
|
38
|
+
assert_equal @tand.send(:localize, orig1, "PT"), loc1
|
39
|
+
assert_equal @tand.send(:localize, orig2, "PT"), loc2
|
40
|
+
assert_equal @tand.send(:localize, orig3, "PT"), loc3
|
41
|
+
assert_equal @tand.send(:localize, orig4, "PT"), loc4
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_ios_translate
|
45
|
+
assert_equal @tios.send(:localize, "1: $kIOSKey$", "PT"), "1: Não sabes nada \\\"João das Neves\\\""
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_android_translate
|
49
|
+
assert_equal @tand.send(:localize, "1: $kAndroidKey1$", "PT"), "1: Não sabes nada \\'João das Neves\\'"
|
50
|
+
assert_equal @tand.send(:localize, "2: $kAndroidKey2$", "PT"), "2: Não sabes nada João das Neves…"
|
51
|
+
assert_equal @tand.send(:localize, "3: $kAndroidKey3$", "PT"), "3: Não sabes nada João das Neves & Pícaros"
|
52
|
+
end
|
53
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bisu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- joaoffcosta
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: safe_yaml
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: colorize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: webmock
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.20'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.20'
|
55
|
+
description: Bisu is a localization automation service. It was built specially for
|
56
|
+
Hole19
|
57
|
+
email: joao.costa@hole19golf.com
|
58
|
+
executables:
|
59
|
+
- bisu
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- bin/bisu
|
66
|
+
- bisu.gem
|
67
|
+
- bisu.gemspec
|
68
|
+
- lib/bisu.rb
|
69
|
+
- lib/bisu/config.rb
|
70
|
+
- lib/bisu/knowledge_base.rb
|
71
|
+
- lib/bisu/logger.rb
|
72
|
+
- lib/bisu/translator.rb
|
73
|
+
- test/support/sample_kb_public_info.html
|
74
|
+
- test/support/sample_kb_public_sheet.html
|
75
|
+
- test/support/sample_translatable.yml
|
76
|
+
- test/test_bisu_config.rb
|
77
|
+
- test/test_bisu_knowledge_base.rb
|
78
|
+
- test/test_bisu_logger.rb
|
79
|
+
- test/test_bisu_translator.rb
|
80
|
+
- test/test_helper.rb
|
81
|
+
homepage: https://github.com/hole19/h19-bisu
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.2.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Bisu - localization automation service
|
105
|
+
test_files: []
|