bisu 1.0.0
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 +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: []
|