bisu 1.3.1 → 1.4.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 +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +16 -0
- data/README.md +39 -24
- data/lib/bisu/config.rb +33 -4
- data/lib/bisu/google_sheet.rb +4 -4
- data/lib/bisu/one_sky.rb +31 -0
- data/lib/bisu/version.rb +2 -2
- data/lib/bisu.rb +26 -2
- data/spec/fixtures/sample.translatable.yml +1 -0
- data/spec/fixtures/sample_one_sky_response.txt +29 -0
- data/spec/lib/bisu/config_spec.rb +30 -5
- data/spec/lib/bisu/one_sky_spec.rb +36 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 352d33d3ac9d54082135084e8cd3e03a6ace04d5
|
4
|
+
data.tar.gz: 3f07ec0e51bde13656405514a72aedefd63f9f65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3126fa41a9805d8b1fb028e73c2ac4674ea73e981c5808b2cfc28324b31546f6ada14436294941fbf8278148f4987b32afe5dd0a3d2d1138fe3d8923aa6a9a12
|
7
|
+
data.tar.gz: 5f76fd4c33ac8dea50f8c5a9b5472d09f7ad245897b749af15a2c0327df603b04167739ae78244c15d750a33362561ce6c89e8d607048fc69dc48f3ac81b5e88
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -6,7 +6,19 @@ GEM
|
|
6
6
|
crack (0.4.3)
|
7
7
|
safe_yaml (~> 1.0.0)
|
8
8
|
diff-lcs (1.2.5)
|
9
|
+
domain_name (0.5.20161021)
|
10
|
+
unf (>= 0.0.5, < 1.0.0)
|
9
11
|
hashdiff (0.3.0)
|
12
|
+
http-cookie (1.0.3)
|
13
|
+
domain_name (~> 0.5)
|
14
|
+
mime-types (2.99.3)
|
15
|
+
netrc (0.11.0)
|
16
|
+
onesky-ruby (1.0.1)
|
17
|
+
rest-client (~> 1.8)
|
18
|
+
rest-client (1.8.0)
|
19
|
+
http-cookie (>= 1.0.2, < 2.0)
|
20
|
+
mime-types (>= 1.16, < 3.0)
|
21
|
+
netrc (~> 0.7)
|
10
22
|
rspec (3.5.0)
|
11
23
|
rspec-core (~> 3.5.0)
|
12
24
|
rspec-expectations (~> 3.5.0)
|
@@ -24,6 +36,9 @@ GEM
|
|
24
36
|
rspec-support (~> 3.5.0)
|
25
37
|
rspec-support (3.5.0)
|
26
38
|
safe_yaml (1.0.4)
|
39
|
+
unf (0.1.4)
|
40
|
+
unf_ext
|
41
|
+
unf_ext (0.0.7.2)
|
27
42
|
webmock (1.24.6)
|
28
43
|
addressable (>= 2.3.6)
|
29
44
|
crack (>= 0.3.2)
|
@@ -35,6 +50,7 @@ PLATFORMS
|
|
35
50
|
|
36
51
|
DEPENDENCIES
|
37
52
|
colorize (~> 0.7)
|
53
|
+
onesky-ruby
|
38
54
|
rspec
|
39
55
|
rspec-its
|
40
56
|
safe_yaml (~> 1.0)
|
data/README.md
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Bisu 홀
|
2
2
|
========
|
3
3
|
|
4
|
-
Bisu manages your app iOS and
|
4
|
+
Bisu manages your app iOS, Android and RoR localization files for you. No more copy+paste induced errors!
|
5
5
|
|
6
6
|
---
|
7
7
|
|
8
8
|
Instalation
|
9
9
|
-----
|
10
|
-
|
10
|
+
|
11
11
|
```
|
12
12
|
gem install bisu
|
13
13
|
```
|
@@ -24,25 +24,40 @@ Usage
|
|
24
24
|
Configuration
|
25
25
|
-----
|
26
26
|
|
27
|
-
1. Create in your
|
27
|
+
1. Create in your project base folder a translatable.yml:
|
28
28
|
|
29
29
|
```
|
30
|
-
type: <iOS
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
type: <iOS|Android|RoR>
|
31
|
+
|
32
|
+
dictionary:
|
33
|
+
type: google_sheet
|
34
|
+
sheet_id: <GOOGLE-DRIVE-SHEET-ID>
|
35
|
+
keys_column: <GOOGLE-DRIVE-KEY-COLUMN-TITLE>
|
36
|
+
|
37
|
+
translate:
|
38
|
+
- in: path/to/1st/file.translatable
|
39
|
+
out: path/to/%{locale}/strings.xml
|
40
|
+
out_en: path/to/default/strings.xml
|
41
|
+
- in: path/to/2nd/file.translatable
|
42
|
+
out: path/to/2nd-%{locale}/strings.xml
|
43
|
+
|
44
|
+
languages:
|
41
45
|
- locale: en
|
42
|
-
language:
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
language: en
|
47
|
+
- locale: en-US
|
48
|
+
language: en
|
49
|
+
- locale: pt
|
50
|
+
language: pt
|
51
|
+
```
|
52
|
+
|
53
|
+
Also available [OneSky](https://www.oneskyapp.com) integration:
|
54
|
+
```
|
55
|
+
dictionary:
|
56
|
+
type: one_sky
|
57
|
+
api_key: <ONE-SKY-API-KEY>
|
58
|
+
api_secret: <ONE-SKY-API-SECRET>
|
59
|
+
project_id: <ONE-SKY-PROJECT-ID>
|
60
|
+
file_name: <ONE-SKY-FILE-NAME>
|
46
61
|
```
|
47
62
|
|
48
63
|
1. Create a \*.translatable version for your **iOS** localization files:
|
@@ -50,13 +65,13 @@ Configuration
|
|
50
65
|
```
|
51
66
|
// $specialKComment1$
|
52
67
|
// $specialKComment2$
|
53
|
-
|
68
|
+
|
54
69
|
// Locale: $specialKLocale$; Language used: $specialKLanguage$
|
55
|
-
|
70
|
+
|
56
71
|
/***********
|
57
72
|
* General
|
58
73
|
************/
|
59
|
-
|
74
|
+
|
60
75
|
"klGeneral_Delete" = "$kDelete$";
|
61
76
|
"klGeneral_Cancel" = "$kCancel$";
|
62
77
|
"klGeneral_Close" = "$kClose$";
|
@@ -67,11 +82,11 @@ Configuration
|
|
67
82
|
|
68
83
|
```
|
69
84
|
<?xml version="1.0" encoding="utf-8"?>
|
70
|
-
|
85
|
+
|
71
86
|
<!-- $specialKComment1$ -->
|
72
87
|
<!-- $specialKComment2$ -->
|
73
88
|
<!-- Locale: $specialKLocale$; Language used: $specialKLanguage$ -->
|
74
|
-
|
89
|
+
|
75
90
|
<resources>
|
76
91
|
<string name="delete">$kDelete$</string>
|
77
92
|
<string name="cancel">$kCancel$</string>
|
@@ -79,7 +94,7 @@ Configuration
|
|
79
94
|
<string name="request_name">$kRequestName%{user_name: %s}$</string>
|
80
95
|
</resources>
|
81
96
|
```
|
82
|
-
|
97
|
+
|
83
98
|
1. Create a \*.translatable version for your **RoR** localization files:
|
84
99
|
|
85
100
|
```
|
data/lib/bisu/config.rb
CHANGED
@@ -2,7 +2,13 @@ module Bisu
|
|
2
2
|
class Config
|
3
3
|
def initialize(hash:)
|
4
4
|
@hash = hash.deep_symbolize
|
5
|
-
@hash.validate_structure!(
|
5
|
+
@hash.validate_structure!(CONFIG_STRUCT)
|
6
|
+
|
7
|
+
unless dict_struct = DICTIONARY_STRUCT[@hash[:dictionary][:type]]
|
8
|
+
raise ArgumentError.new("unknown dictionary type '#{@hash[:dictionary][:type]}'")
|
9
|
+
end
|
10
|
+
|
11
|
+
@hash[:dictionary].validate_structure!(dict_struct)
|
6
12
|
end
|
7
13
|
|
8
14
|
def to_h
|
@@ -28,13 +34,12 @@ module Bisu
|
|
28
34
|
|
29
35
|
private
|
30
36
|
|
31
|
-
|
37
|
+
CONFIG_STRUCT = {
|
32
38
|
type: Hash,
|
33
39
|
elements: {
|
34
40
|
type: { type: String },
|
35
41
|
dictionary: { type: Hash, elements: {
|
36
|
-
|
37
|
-
keys_column: { type: String }
|
42
|
+
type: { type: String }
|
38
43
|
} },
|
39
44
|
translate: { type: Array, elements: {
|
40
45
|
type: Hash, elements: {
|
@@ -50,5 +55,29 @@ module Bisu
|
|
50
55
|
} }
|
51
56
|
}
|
52
57
|
}
|
58
|
+
|
59
|
+
GOOGLE_SHEET_STRUCT = {
|
60
|
+
type: Hash,
|
61
|
+
elements: {
|
62
|
+
type: { type: String },
|
63
|
+
sheet_id: { type: String },
|
64
|
+
keys_column: { type: String }
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
ONE_SKY_STRUCT = {
|
69
|
+
type: Hash,
|
70
|
+
elements: {
|
71
|
+
api_key: { type: String },
|
72
|
+
api_secret: { type: String },
|
73
|
+
project_id: { type: Integer },
|
74
|
+
file_name: { type: String }
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
DICTIONARY_STRUCT = {
|
79
|
+
"google_sheet" => GOOGLE_SHEET_STRUCT,
|
80
|
+
"one_sky" => ONE_SKY_STRUCT
|
81
|
+
}
|
53
82
|
end
|
54
83
|
end
|
data/lib/bisu/google_sheet.rb
CHANGED
@@ -3,15 +3,15 @@ require "xmlsimple"
|
|
3
3
|
|
4
4
|
module Bisu
|
5
5
|
class GoogleSheet
|
6
|
-
def initialize(sheet_id,
|
6
|
+
def initialize(sheet_id, keys_column)
|
7
7
|
@sheet_id = sheet_id
|
8
|
-
@key_column =
|
8
|
+
@key_column = keys_column
|
9
9
|
end
|
10
10
|
|
11
11
|
def to_i18
|
12
12
|
raw = raw_data(@sheet_id)
|
13
13
|
|
14
|
-
Logger.info("
|
14
|
+
Logger.info("Downloading dictionary from Google Sheet...")
|
15
15
|
|
16
16
|
non_language_columns = ["id", "updated", "category", "title", "content", "link", @key_column]
|
17
17
|
|
@@ -28,7 +28,7 @@ module Bisu
|
|
28
28
|
end
|
29
29
|
|
30
30
|
Logger.info("Google Sheet parsed successfully!")
|
31
|
-
Logger.info("Found #{kb.count}
|
31
|
+
Logger.info("Found #{kb.count} languages.")
|
32
32
|
|
33
33
|
kb
|
34
34
|
end
|
data/lib/bisu/one_sky.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'onesky'
|
2
|
+
|
3
|
+
module Bisu
|
4
|
+
class OneSky
|
5
|
+
def initialize(api_key, api_secret, project_id, file_name)
|
6
|
+
@client = Onesky::Client.new(api_key, api_secret)
|
7
|
+
@project_id = project_id
|
8
|
+
@file_name = file_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_i18
|
12
|
+
Logger.info("Downloading dictionary from OneSky...")
|
13
|
+
|
14
|
+
proj = @client.project(@project_id)
|
15
|
+
file = proj.export_multilingual(source_file_name: @file_name, file_format: "I18NEXT_MULTILINGUAL_JSON")
|
16
|
+
|
17
|
+
hash = JSON.parse(file)
|
18
|
+
hash.each do |lang, v|
|
19
|
+
hash[lang] = v["translation"]
|
20
|
+
hash[lang].each do |key, text|
|
21
|
+
hash[lang][key] = hash[lang][key].join("\n") if hash[lang][key].is_a? Array
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Logger.info("OneSky response parsed successfully!")
|
26
|
+
Logger.info("Found #{hash.count} languages.")
|
27
|
+
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/bisu/version.rb
CHANGED
data/lib/bisu.rb
CHANGED
@@ -5,6 +5,7 @@ require 'bisu/logger'
|
|
5
5
|
require 'bisu/object_extension'
|
6
6
|
require 'bisu/config'
|
7
7
|
require 'bisu/google_sheet'
|
8
|
+
require 'bisu/one_sky'
|
8
9
|
require 'bisu/dictionary'
|
9
10
|
require 'bisu/localizer'
|
10
11
|
require 'bisu/version'
|
@@ -17,8 +18,7 @@ module Bisu
|
|
17
18
|
|
18
19
|
if config_file = open_file("translatable.yml", "r", true)
|
19
20
|
config = Bisu::Config.new(hash: YAML::load(config_file))
|
20
|
-
|
21
|
-
dictionary = Bisu::Dictionary.new(google_sheet.to_i18)
|
21
|
+
dictionary = dictionary_for(config: config.dictionary, save_to_path: options[:dictionary_save_path])
|
22
22
|
localizer = Bisu::Localizer.new(dictionary, config.type)
|
23
23
|
|
24
24
|
config.localize_files do |in_path, out_path, language, locale|
|
@@ -36,6 +36,26 @@ module Bisu
|
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
+
def dictionary_for(config:, save_to_path:)
|
40
|
+
source =
|
41
|
+
case config[:type]
|
42
|
+
when "google_sheet"
|
43
|
+
Bisu::GoogleSheet.new(config[:sheet_id], config[:keys_column])
|
44
|
+
when "one_sky"
|
45
|
+
Bisu::OneSky.new(config[:api_key], config[:api_secret], config[:project_id], config[:file_name])
|
46
|
+
end
|
47
|
+
|
48
|
+
source = source.to_i18
|
49
|
+
|
50
|
+
if save_to_path && file = open_file(save_to_path, "w", false)
|
51
|
+
file.write(source.to_json)
|
52
|
+
file.flush
|
53
|
+
file.close
|
54
|
+
end
|
55
|
+
|
56
|
+
Bisu::Dictionary.new(source)
|
57
|
+
end
|
58
|
+
|
39
59
|
def command_line_options(options)
|
40
60
|
opts_hash = {}
|
41
61
|
|
@@ -44,6 +64,10 @@ module Bisu
|
|
44
64
|
opts_hash[:default_language] = language
|
45
65
|
end
|
46
66
|
|
67
|
+
opts.on("--save-dictionary PATH", "Save downloaded dictionary locally at given path") do |path|
|
68
|
+
opts_hash[:dictionary_save_path] = path
|
69
|
+
end
|
70
|
+
|
47
71
|
opts.on_tail("-h", "--help", "Show this message") do
|
48
72
|
puts opts
|
49
73
|
exit
|
@@ -0,0 +1,29 @@
|
|
1
|
+
{
|
2
|
+
"en": {
|
3
|
+
"translation": {
|
4
|
+
"kConnectFacebook": "Connect with Facebook",
|
5
|
+
"kNoNoNoMr": "No, no, no. Mr %{name} not here"
|
6
|
+
}
|
7
|
+
},
|
8
|
+
"ja": {
|
9
|
+
"translation": {
|
10
|
+
"kConnectFacebook": "\u30d5\u30a7\u30a4\u30b9\u30d6\u30c3\u30af\u3078\u63a5\u7d9a"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
"fr": {
|
14
|
+
"translation": {
|
15
|
+
"kConnectFacebook": "Connexion par Facebook"
|
16
|
+
}
|
17
|
+
},
|
18
|
+
"de": {
|
19
|
+
"translation": {
|
20
|
+
"kConnectFacebook": "Mit Facebook verbinden"
|
21
|
+
}
|
22
|
+
},
|
23
|
+
"ko": {
|
24
|
+
"translation": {
|
25
|
+
"kConnectFacebook": "\ud398\uc774\uc2a4\ubd81\uc73c\ub85c \uc811\uc18d",
|
26
|
+
"kTwitterServer": ["트위터 서버연결 실패. ", "잠시 후 재시도."]
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
@@ -4,8 +4,9 @@ describe Bisu::Config do
|
|
4
4
|
let(:hash) { {
|
5
5
|
type: "BisuOS",
|
6
6
|
dictionary: {
|
7
|
-
|
8
|
-
|
7
|
+
type: "google_sheet",
|
8
|
+
sheet_id: "abc1234567890",
|
9
|
+
keys_column: "key_name"
|
9
10
|
},
|
10
11
|
translate: [
|
11
12
|
{ in: "path/to/file/to/1.ext.translatable",
|
@@ -30,9 +31,33 @@ describe Bisu::Config do
|
|
30
31
|
it { expect { config }.to raise_error /missing keys/i }
|
31
32
|
end
|
32
33
|
|
33
|
-
its(:to_h)
|
34
|
-
its(:type)
|
35
|
-
|
34
|
+
its(:to_h) { should eq(hash) }
|
35
|
+
its(:type) { should eq("BisuOS") }
|
36
|
+
|
37
|
+
describe "#dictionary" do
|
38
|
+
subject(:dictionary) { config.dictionary }
|
39
|
+
|
40
|
+
it { should eq({ type: "google_sheet", sheet_id: "abc1234567890", keys_column: "key_name" }) }
|
41
|
+
|
42
|
+
context "when given a OneSky type dictionary" do
|
43
|
+
before do
|
44
|
+
hash[:dictionary] = {
|
45
|
+
type: "one_sky",
|
46
|
+
api_key: "as387oavh48",
|
47
|
+
api_secret: "bp0s5avo8a59",
|
48
|
+
project_id: 328742,
|
49
|
+
file_name: "file.json"
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
it { should eq({ type: "one_sky", api_key: "as387oavh48", api_secret: "bp0s5avo8a59", project_id: 328742, file_name: "file.json" }) }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when given an unknown type dictionary" do
|
57
|
+
before { hash[:dictionary] = { type: "i_dunno" } }
|
58
|
+
it { expect { config }.to raise_error /unknown dictionary type 'i_dunno'/i }
|
59
|
+
end
|
60
|
+
end
|
36
61
|
|
37
62
|
describe "#localize_files" do
|
38
63
|
it "yields 5 times with the expected arguments" do
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe Bisu::OneSky do
|
2
|
+
subject(:to_i18) { Bisu::OneSky.new(api_key, api_secret, project_id, file_name).to_i18 }
|
3
|
+
|
4
|
+
let(:api_key) { "a123" }
|
5
|
+
let(:api_secret) { "b123" }
|
6
|
+
let(:project_id) { 98765 }
|
7
|
+
let(:file_name) { "file456.json" }
|
8
|
+
|
9
|
+
let(:os_response) { File.read("spec/fixtures/sample_one_sky_response.txt") }
|
10
|
+
|
11
|
+
before do
|
12
|
+
project = double("OSProject")
|
13
|
+
allow_any_instance_of(Onesky::Client).to receive(:project).with(project_id).and_return(project)
|
14
|
+
allow(project).to receive(:export_multilingual).with(source_file_name: file_name, file_format: "I18NEXT_MULTILINGUAL_JSON").and_return(os_response)
|
15
|
+
end
|
16
|
+
|
17
|
+
it { expect { to_i18 }.not_to raise_error }
|
18
|
+
|
19
|
+
it "returns an hash in i18 format" do
|
20
|
+
expect(to_i18).to eq({
|
21
|
+
"en" => { "kConnectFacebook" => "Connect with Facebook", "kNoNoNoMr" => "No, no, no. Mr %{name} not here" },
|
22
|
+
"ja" => { "kConnectFacebook" => "フェイスブックへ接続" },
|
23
|
+
"fr" => { "kConnectFacebook" => "Connexion par Facebook" },
|
24
|
+
"de" => { "kConnectFacebook" => "Mit Facebook verbinden" },
|
25
|
+
"ko" => { "kConnectFacebook" => "페이스북으로 접속", "kTwitterServer" => "트위터 서버연결 실패. \n잠시 후 재시도." }
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when OneSky raises an error" do
|
30
|
+
before { allow_any_instance_of(Onesky::Client).to receive(:project).and_raise("ups... not allowed!") }
|
31
|
+
|
32
|
+
it "raises that same error" do
|
33
|
+
expect { to_i18 }.to raise_error /not allowed/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bisu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- joaoffcosta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: safe_yaml
|
@@ -90,16 +90,19 @@ files:
|
|
90
90
|
- lib/bisu/localizer.rb
|
91
91
|
- lib/bisu/logger.rb
|
92
92
|
- lib/bisu/object_extension.rb
|
93
|
+
- lib/bisu/one_sky.rb
|
93
94
|
- lib/bisu/version.rb
|
94
95
|
- spec/fixtures/sample.translatable.yml
|
95
96
|
- spec/fixtures/sample_kb_public_info.html
|
96
97
|
- spec/fixtures/sample_kb_public_sheet.html
|
98
|
+
- spec/fixtures/sample_one_sky_response.txt
|
97
99
|
- spec/lib/bisu/config_spec.rb
|
98
100
|
- spec/lib/bisu/dictionary_spec.rb
|
99
101
|
- spec/lib/bisu/google_sheet_spec.rb
|
100
102
|
- spec/lib/bisu/localizer_spec.rb
|
101
103
|
- spec/lib/bisu/logger_spec.rb
|
102
104
|
- spec/lib/bisu/object_extension_spec.rb
|
105
|
+
- spec/lib/bisu/one_sky_spec.rb
|
103
106
|
- spec/lib/bisu_spec.rb
|
104
107
|
- spec/spec_helper.rb
|
105
108
|
homepage: https://github.com/hole19/bisu
|